From b8453da881d024aeeb7e711b411b2bde0f90b96c Mon Sep 17 00:00:00 2001 From: Josh Miklos Date: Mon, 22 Jun 2020 16:09:34 -0700 Subject: [PATCH] Added bus_info for v4l2. Added optional forcing OpenCV or V4L2. Added non-linear transform. Added transparent overlay. --- .github/workflows/publish.yml | 6 +- .github/workflows/pythonpackage.yml | 5 +- displayarray/effects/__init__.py | 2 +- displayarray/effects/overlay.py | 54 ++ displayarray/effects/transform.py | 45 ++ displayarray/frame/frame_publishing.py | 57 +- displayarray/frame/frame_updater.py | 8 +- displayarray/frame/subscriber_dictionary.py | 7 +- displayarray/window/subscriber_windows.py | 63 +- docs_test/.doctrees/display.doctree | Bin 0 -> 35710 bytes docs_test/.doctrees/displayarray_bash.doctree | Bin 0 -> 12951 bytes docs_test/.doctrees/effects.doctree | Bin 0 -> 44328 bytes docs_test/.doctrees/frame.doctree | Bin 0 -> 25780 bytes docs_test/.doctrees/index.doctree | Bin 0 -> 6724 bytes docs_test/.doctrees/input.doctree | Bin 0 -> 9240 bytes examples/callbacks/black_and_white.py | 2 +- examples/videos/__init__.py | 12 +- poetry.lock | 599 ------------------ pyproject.toml | 36 -- setup.py | 64 ++ tests/frame/test_frame_publishing.py | 2 +- tests/frame/test_frame_updater.py | 2 +- tests/window/test_subscriber_windows.py | 57 +- tox.ini | 32 +- 24 files changed, 334 insertions(+), 719 deletions(-) create mode 100644 displayarray/effects/overlay.py create mode 100644 displayarray/effects/transform.py create mode 100644 docs_test/.doctrees/display.doctree create mode 100644 docs_test/.doctrees/displayarray_bash.doctree create mode 100644 docs_test/.doctrees/effects.doctree create mode 100644 docs_test/.doctrees/frame.doctree create mode 100644 docs_test/.doctrees/index.doctree create mode 100644 docs_test/.doctrees/input.doctree delete mode 100644 poetry.lock delete mode 100644 pyproject.toml create mode 100644 setup.py diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 72eb78b..67849f1 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -14,10 +14,10 @@ jobs: with: python-version: 3.7 - uses: dschep/install-poetry-action@v1.2 - - name: Install dependencies - run: poetry install + - name: Install and build + run: pip install . - name: Build with Poetry - run: poetry build + run: python setup.py sdist bdist_wheel - name: Publish distribution 📦 to Test PyPI uses: pypa/gh-action-pypi-publish@master with: diff --git a/.github/workflows/pythonpackage.yml b/.github/workflows/pythonpackage.yml index 5a9afd0..9eefd89 100644 --- a/.github/workflows/pythonpackage.yml +++ b/.github/workflows/pythonpackage.yml @@ -18,8 +18,7 @@ jobs: uses: actions/setup-python@v1 with: python-version: ${{ matrix.python-version }} - - uses: dschep/install-poetry-action@v1.2 - name: Install dependencies - run: poetry install + run: pip install . - name: Test with tox - run: poetry run tox -p auto -o + run: tox -p auto -o diff --git a/displayarray/effects/__init__.py b/displayarray/effects/__init__.py index b066ad7..901c494 100644 --- a/displayarray/effects/__init__.py +++ b/displayarray/effects/__init__.py @@ -1,3 +1,3 @@ """Effects to run on numpy arrays to make data clearer.""" -from . import crop, lens, select_channels +from . import crop, lens, select_channels, overlay, transform diff --git a/displayarray/effects/overlay.py b/displayarray/effects/overlay.py new file mode 100644 index 0000000..f82959b --- /dev/null +++ b/displayarray/effects/overlay.py @@ -0,0 +1,54 @@ +"""Overlay functions.""" + + +def overlay_transparent(background, overlay, x=None, y=None): + """ + Overlay a transparent image on top of a background image. + + :param background: background rgb image to overlay on top of + :param overlay: rgba image to overlay on top of the background + :param x: leftmost part to overlay at on the background + :param y: topmost part to overlay at on the background + """ + # https://stackoverflow.com/a/54058766/782170 + assert overlay.shape[2] == 4, "Overlay must be BGRA" + + background_width = background.shape[1] + background_height = background.shape[0] + + if (x is not None and x >= background_width) or ( + y is not None and y >= background_height + ): + return background + + h, w = overlay.shape[0], overlay.shape[1] + + if x is None: + x = int(background_width / 2 - w / 2) + if y is None: + y = int(background_height / 2 - h / 2) + + if x < 0: + w += x + overlay = overlay[:, -x:] + + if y < 0: + w += y + overlay = overlay[:, -y:] + + if x + w > background_width: + w = background_width - x + overlay = overlay[:, :w] + + if y + h > background_height: + h = background_height - y + overlay = overlay[:h] + + overlay_image = overlay[..., :3] + mask = overlay[..., 3:] / 255.0 + + background[y : y + h, x : x + w] = (1.0 - mask) * background[ + y : y + h, x : x + w + ] + mask * overlay_image + + return background diff --git a/displayarray/effects/transform.py b/displayarray/effects/transform.py new file mode 100644 index 0000000..215dc33 --- /dev/null +++ b/displayarray/effects/transform.py @@ -0,0 +1,45 @@ +"""Transform functions.""" + +import numpy as np +import cv2 + + +def transform_about_center( + arr, scale_multiplier=(1, 1), rotation_degrees=0, translation=(0, 0), skew=(0, 0) +): + """ + Transform an image about its center. + + :param arr: numpy image to be transformed + :param scale_multiplier: grow/shrink in x and y + :param rotation_degrees: degrees to rotate, from 0 to 360 + :param translation: pixels to translate the image + :param skew: mimics rotation along screen axes. In degrees. 90 degrees should give a line. + :return: transformed numpy image + """ + center_scale_xform = np.eye(3) + center_scale_xform[0, 0] = scale_multiplier[1] + center_scale_xform[1, 1] = scale_multiplier[0] + center_scale_xform[0:2, -1] = [arr.shape[1] // 2, arr.shape[0] // 2] + + rotation_xform = np.eye(3) + + theta = np.radians(rotation_degrees) + c, s = np.cos(theta), np.sin(theta) + R = np.array(((c, -s), (s, c))) + rotation_xform[0:2, 0:2] = R + skew = np.radians(skew) + skew = np.tan(skew) + rotation_xform[-1, 0:2] = [skew[1] / arr.shape[1], skew[0] / arr.shape[0]] + + translation_skew_xform = np.eye(3) + translation_skew_xform[0:2, -1] = [ + (-arr.shape[1] - translation[1]) // 2, + (-arr.shape[0] - translation[0]) // 2, + ] + + full_xform = center_scale_xform @ rotation_xform @ translation_skew_xform + xformd_arr = cv2.warpPerspective( + arr, full_xform, tuple(reversed(arr.shape[:2])), flags=0 + ) + return xformd_arr diff --git a/displayarray/frame/frame_publishing.py b/displayarray/frame/frame_publishing.py index 29934af..87890a7 100644 --- a/displayarray/frame/frame_publishing.py +++ b/displayarray/frame/frame_publishing.py @@ -11,8 +11,10 @@ import cv2 using_pyv4l2cam = False try: if sys.platform == "linux": - from PyV4L2Cam.camera import Camera as pyv4lcamera - from PyV4L2Cam.controls import ControlIDs as pyv4lcontrolids + from PyV4L2Cam.camera import Camera as pyv4lcamera # type: ignore + from PyV4L2Cam.controls import ControlIDs as pyv4lcontrolids # type: ignore + from PyV4L2Cam import convert_mjpeg, convert_rgb24 # type: ignore + from PyV4L2Cam.get_camera import get_camera_by_bus_info, get_camera_by_string # type: ignore using_pyv4l2cam = True except ImportError: @@ -32,25 +34,6 @@ from typing import Union, Tuple, Optional, Dict, Any, List, Callable FrameCallable = Callable[[np.ndarray], Optional[np.ndarray]] -def _v4l2_convert_mjpeg(mjpeg: bytes) -> Optional[np.ndarray]: - # Thanks: https://stackoverflow.com/a/21844162 - a = mjpeg.find(b"\xff\xd8") - b = mjpeg.find(b"\xff\xd9") - - if a == -1 or b == -1: - return None - else: - jpg = mjpeg[a : b + 2] - frame = cv2.imdecode(np.frombuffer(jpg, dtype=np.uint8), cv2.IMREAD_COLOR) - return frame - - -def _v4l2_convert_rgb24(rgb24: bytes, width: int, height: int) -> Optional[np.ndarray]: - nparr = np.frombuffer(rgb24, np.uint8) - np_frame = nparr.reshape((height, width, 3)) - return np_frame - - def pub_cam_loop_pyv4l2( cam_id: Union[int, str, np.ndarray], request_size: Tuple[int, int] = (-1, -1), @@ -77,13 +60,16 @@ def pub_cam_loop_pyv4l2( f"/dev/video{cam_id}", *request_size ) else: - cam = pyv4lcamera(cam_id, *request_size) # type: ignore + if "usb" in cam_id: + cam = get_camera_by_bus_info(cam_id, *request_size) + else: + cam = get_camera_by_string(cam_id, *request_size) # type: ignore else: raise TypeError( "Only strings or ints representing cameras are supported with v4l2." ) - subscriber_dictionary.register_cam(name) + subscriber_dictionary.register_cam(name, cam) sub = subscriber_dictionary.cam_cmd_sub(name) sub.return_on_no_data = "" @@ -99,9 +85,9 @@ def pub_cam_loop_pyv4l2( frame_bytes = cam.get_frame() # type: bytes if cam.pixel_format == "MJPEG": - nd_frame = _v4l2_convert_mjpeg(frame_bytes) + nd_frame = convert_mjpeg(frame_bytes) elif cam.pixel_format == "RGB24": - nd_frame = _v4l2_convert_rgb24(frame_bytes, cam.width, cam.height) + nd_frame = convert_rgb24(frame_bytes, cam.width, cam.height) else: raise NotImplementedError(f"{cam.pixel_format} format not supported.") @@ -149,7 +135,7 @@ def pub_cam_loop_opencv( "Only strings or ints representing cameras, or numpy arrays representing pictures supported." ) - subscriber_dictionary.register_cam(name) + subscriber_dictionary.register_cam(name, cam) frame_counter = 0 @@ -158,7 +144,10 @@ def pub_cam_loop_opencv( msg = "" if high_speed: - cam.set(cv2.CAP_PROP_FOURCC, cv2.CAP_OPENCV_MJPEG) + try: + cam.set(cv2.CAP_PROP_FOURCC, cv2.CAP_OPENCV_MJPEG) + except AttributeError: + warnings.warn("Please update OpenCV") cam.set(cv2.CAP_PROP_FRAME_WIDTH, request_size[0]) cam.set(cv2.CAP_PROP_FRAME_HEIGHT, request_size[1]) @@ -196,6 +185,7 @@ def pub_cam_thread( request_ize: Tuple[int, int] = (-1, -1), high_speed: bool = True, fps_limit: float = float("inf"), + force_backend="", ) -> threading.Thread: """Run pub_cam_loop in a new thread. Starts on creation.""" @@ -203,15 +193,20 @@ def pub_cam_thread( if name in uid_dict.keys(): t = uid_dict[name] else: - if ( + if "cv" in force_backend.lower(): + pub_cam_loop = pub_cam_loop_opencv + elif ( sys.platform == "linux" and using_pyv4l2cam and ( isinstance(cam_id, int) - or (isinstance(cam_id, str) and "/dev/video" in cam_id) + or ( + isinstance(cam_id, str) + and any(["/dev/video" in cam_id, "usb" in cam_id]) + ) ) - ): - pub_cam_loop = pub_cam_loop_pyv4l2 + ) or "v4l2" in force_backend.lower(): + pub_cam_loop = pub_cam_loop_pyv4l2 # type: ignore else: pub_cam_loop = pub_cam_loop_opencv diff --git a/displayarray/frame/frame_updater.py b/displayarray/frame/frame_updater.py index 4cd79a1..e09c090 100644 --- a/displayarray/frame/frame_updater.py +++ b/displayarray/frame/frame_updater.py @@ -27,6 +27,7 @@ class FrameUpdater(threading.Thread): request_size: Tuple[int, int] = (-1, -1), high_speed: bool = True, fps_limit: float = float("inf"), + force_backend="", ): """Create the frame updater thread.""" super(FrameUpdater, self).__init__(target=self.loop, args=()) @@ -42,6 +43,7 @@ class FrameUpdater(threading.Thread): self.high_speed = high_speed self.fps_limit = fps_limit self.exception_raised = None + self.force_backend = force_backend def __wait_for_cam_id(self): while str(self.cam_id) not in subscriber_dictionary.CV_CAMS_DICT: @@ -84,7 +86,11 @@ class FrameUpdater(threading.Thread): def loop(self): """Continually get frames from the video publisher, run callbacks on them, and listen to commands.""" t = pub_cam_thread( - self.video_source, self.request_size, self.high_speed, self.fps_limit + self.video_source, + self.request_size, + self.high_speed, + self.fps_limit, + self.force_backend, ) self.__wait_for_cam_id() diff --git a/displayarray/frame/subscriber_dictionary.py b/displayarray/frame/subscriber_dictionary.py index 1955579..11f7d97 100644 --- a/displayarray/frame/subscriber_dictionary.py +++ b/displayarray/frame/subscriber_dictionary.py @@ -20,22 +20,23 @@ class CamHandler(object): class Cam(object): """A camera publisher instance that will send frames, status, and commands out.""" - def __init__(self, name): + def __init__(self, name, cam_instance=None): """Create the cam.""" self.name = name self.cmd = None self.frame_pub = VariablePub() self.cmd_pub = VariablePub() self.status_pub = VariablePub() + self.cam_instance = cam_instance CV_CAM_HANDLERS_DICT: Dict[str, CamHandler] = {} CV_CAMS_DICT: Dict[str, Cam] = {} -def register_cam(cam_id): +def register_cam(cam_id, cam_instance=None): """Register camera "cam_id" to a global list so it can be picked up.""" - cam = Cam(str(cam_id)) + cam = Cam(str(cam_id), cam_instance) CV_CAMS_DICT[str(cam_id)] = cam CV_CAM_HANDLERS_DICT[str(cam_id)] = CamHandler( str(cam_id), cam.frame_pub.make_sub() diff --git a/displayarray/window/subscriber_windows.py b/displayarray/window/subscriber_windows.py index 5c47ce1..7139ed6 100644 --- a/displayarray/window/subscriber_windows.py +++ b/displayarray/window/subscriber_windows.py @@ -13,11 +13,22 @@ from displayarray._uid import uid_for_source from displayarray.frame import subscriber_dictionary from displayarray.frame.frame_updater import FrameCallable from displayarray.frame.frame_updater import FrameUpdater +from displayarray.frame.subscriber_dictionary import CV_CAMS_DICT from displayarray.input import MouseEvent from displayarray.window import window_commands from displayarray._util import WeakMethod from displayarray.effects.select_channels import SelectChannels +try: + import sys + + if sys.platform == "linux": + from PyV4L2Cam.get_camera import get_bus_info_from_camera # type: ignore + else: + get_bus_info_from_camera = None +except: + get_bus_info_from_camera = None + class SubscriberWindows(object): """Windows that subscribe to updates to cameras, videos, and arrays.""" @@ -266,12 +277,26 @@ class SubscriberWindows(object): window_commands.quit(force_all_read=False) self.__stop_all_cams() + @property + def cams(self): + """Get the camera instances. Can be used for OpenCV or V4L2 functions, depending on backend.""" + return [CV_CAMS_DICT[v].cam_instance for v in self.input_vid_global_names] + + @property + def busses(self): + """Get the busses the cameras are plugged into. Can be used as UIDs. Requires V4L2 backend.""" + if get_bus_info_from_camera is not None: + return [get_bus_info_from_camera(c) for c in self.cams] + else: + raise RuntimeError("Getting bus info not supported on this system") + def _get_video_callback_dict_threads( *vids, callbacks: Optional[Dict[Any, Union[FrameCallable, List[FrameCallable]]]] = None, fps=float("inf"), size=(-1, -1), + force_backend="", ): assert callbacks is not None vid_threads = [] @@ -289,7 +314,13 @@ def _get_video_callback_dict_threads( elif callable(callbacks[v]): v_callbacks.append(callbacks[v]) # type: ignore vid_threads.append( - FrameUpdater(v, callbacks=v_callbacks, fps_limit=fps, request_size=size) + FrameUpdater( + v, + callbacks=v_callbacks, + fps_limit=fps, + request_size=size, + force_backend=force_backend, + ) ) return vid_threads @@ -305,6 +336,7 @@ def _get_video_threads( ] = None, fps=float("inf"), size=(-1, -1), + force_backend="", ): vid_threads: List[Thread] = [] if isinstance(callbacks, Dict): @@ -314,17 +346,33 @@ def _get_video_threads( elif isinstance(callbacks, List): for v in vids: vid_threads.append( - FrameUpdater(v, callbacks=callbacks, fps_limit=fps, request_size=size) + FrameUpdater( + v, + callbacks=callbacks, + fps_limit=fps, + request_size=size, + force_backend=force_backend, + ) ) elif callable(callbacks): for v in vids: vid_threads.append( - FrameUpdater(v, callbacks=[callbacks], fps_limit=fps, request_size=size) + FrameUpdater( + v, + callbacks=[callbacks], + fps_limit=fps, + request_size=size, + force_backend=force_backend, + ) ) else: for v in vids: if v is not None: - vid_threads.append(FrameUpdater(v, fps_limit=fps, request_size=size)) + vid_threads.append( + FrameUpdater( + v, fps_limit=fps, request_size=size, force_backend=force_backend + ) + ) return vid_threads @@ -342,6 +390,7 @@ def display( fps_limit=float("inf"), size=(-1, -1), silent=False, + force_backend="", ): """ Display all the arrays, cameras, and videos passed in. @@ -351,7 +400,11 @@ def display( Window names end up becoming the title of the windows """ vid_threads = _get_video_threads( - *vids, callbacks=callbacks, fps=fps_limit, size=size + *vids, + callbacks=callbacks, + fps=fps_limit, + size=size, + force_backend=force_backend, ) for v in vid_threads: v.start() diff --git a/docs_test/.doctrees/display.doctree b/docs_test/.doctrees/display.doctree new file mode 100644 index 0000000000000000000000000000000000000000..0eef6e2ee16a80e3f183cbdff17c8fc5119f3c79 GIT binary patch literal 35710 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 ar0_5y-KQQiosR&=uww+|leOJhS^R%IEk1t$ literal 0 HcmV?d00001 diff --git a/docs_test/.doctrees/displayarray_bash.doctree b/docs_test/.doctrees/displayarray_bash.doctree new file mode 100644 index 0000000000000000000000000000000000000000..a061d4fdbafc892d51d0e261dd45c11576d5f071 GIT binary patch literal 12951 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 Z@mBemO8F$5=lLX|u^RISDG{{xcEPGJB5 literal 0 HcmV?d00001 diff --git a/docs_test/.doctrees/frame.doctree b/docs_test/.doctrees/frame.doctree new file mode 100644 index 0000000000000000000000000000000000000000..d956149b6eda0665fcedee47180a7c72beb22d3d GIT binary patch literal 25780 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 literal 0 HcmV?d00001 diff --git a/docs_test/.doctrees/index.doctree b/docs_test/.doctrees/index.doctree new file mode 100644 index 0000000000000000000000000000000000000000..109ce4b48d535ea5749f0b73ac5cf0c3758f2863 GIT binary patch literal 6724 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 literal 0 HcmV?d00001 diff --git a/docs_test/.doctrees/input.doctree b/docs_test/.doctrees/input.doctree new file mode 100644 index 0000000000000000000000000000000000000000..a0221648959481ea2a1f835bdd935e4220b64dc1 GIT binary patch literal 9240 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 literal 0 HcmV?d00001 diff --git a/examples/callbacks/black_and_white.py b/examples/callbacks/black_and_white.py index f7e050d..bf2b5f1 100644 --- a/examples/callbacks/black_and_white.py +++ b/examples/callbacks/black_and_white.py @@ -9,7 +9,7 @@ def black_and_white(arr): import time t0 = t1 = time.time() -for up in display(0, size=(1, 1), callbacks=black_and_white): +for up in display("usb-0000:00:14.0-7"): if up: t1 = time.time() print(1.0 / (t1 - t0)) diff --git a/examples/videos/__init__.py b/examples/videos/__init__.py index 006f19a..a28a427 100644 --- a/examples/videos/__init__.py +++ b/examples/videos/__init__.py @@ -9,25 +9,25 @@ test_video_3 = str(Path.joinpath(Path(__file__).parent, "fractal test 3.mp4")) urls = { "test_video": "https://www.youtube.com/watch?v=LpWhaBVIrZw", "test_video_2": "https://www.youtube.com/watch?v=GASynpGr-c8", - "test_video_3": "https://www.youtube.com/watch?v=u_P83LcI8Oc" + "test_video_3": "https://www.youtube.com/watch?v=u_P83LcI8Oc", } def populate_videos(fps=60, res="720p", ext="mp4"): from pytube import YouTube # Note: pip install pytube3, not pytube from pathlib import Path + for n, v in globals().items(): - if 'test_video' in n: + if "test_video" in n: print(f"Checking if '{n}' is downloaded.") if Path(v).exists(): print("Video already downloaded.") else: the_path = Path(v) print("Downloading...") - YouTube(urls[n]) \ - .streams \ - .filter(fps=fps, res=res, file_extension=ext)[0] \ - .download(output_path=the_path.parent, filename=the_path.stem) + YouTube(urls[n]).streams.filter(fps=fps, res=res, file_extension=ext)[ + 0 + ].download(output_path=the_path.parent, filename=the_path.stem) if __name__ == "__main__": diff --git a/poetry.lock b/poetry.lock deleted file mode 100644 index 1914a5b..0000000 --- a/poetry.lock +++ /dev/null @@ -1,599 +0,0 @@ -[[package]] -category = "dev" -description = "A configurable sidebar-enabled Sphinx theme" -name = "alabaster" -optional = false -python-versions = "*" -version = "0.7.12" - -[[package]] -category = "main" -description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." -name = "appdirs" -optional = false -python-versions = "*" -version = "1.4.3" - -[[package]] -category = "dev" -description = "Atomic file writes." -name = "atomicwrites" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "1.3.0" - -[[package]] -category = "main" -description = "Classes Without Boilerplate" -name = "attrs" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "19.3.0" - -[[package]] -category = "dev" -description = "Internationalization utilities" -name = "babel" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "2.7.0" - -[package.dependencies] -pytz = ">=2015.7" - -[[package]] -category = "main" -description = "The uncompromising code formatter." -name = "black" -optional = false -python-versions = ">=3.6" -version = "18.9b0" - -[package.dependencies] -appdirs = "*" -attrs = ">=17.4.0" -click = ">=6.5" -toml = ">=0.9.4" - -[[package]] -category = "dev" -description = "Python package for providing Mozilla's CA Bundle." -name = "certifi" -optional = false -python-versions = "*" -version = "2019.9.11" - -[[package]] -category = "dev" -description = "Universal encoding detector for Python 2 and 3" -name = "chardet" -optional = false -python-versions = "*" -version = "3.0.4" - -[[package]] -category = "main" -description = "Composable command line interface toolkit" -name = "click" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "7.0" - -[[package]] -category = "dev" -description = "Cross-platform colored terminal text." -marker = "sys_platform == \"win32\"" -name = "colorama" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "0.4.1" - -[[package]] -category = "dev" -description = "Code coverage measurement for Python" -name = "coverage" -optional = false -python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*, <4" -version = "4.5.4" - -[[package]] -category = "main" -description = "Pythonic argument parser, that will make you smile" -name = "docopt" -optional = false -python-versions = "*" -version = "0.6.2" - -[[package]] -category = "dev" -description = "Docutils -- Python Documentation Utilities" -name = "docutils" -optional = false -python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" -version = "0.15.2" - -[[package]] -category = "dev" -description = "A platform independent file lock." -name = "filelock" -optional = false -python-versions = "*" -version = "3.0.12" - -[[package]] -category = "dev" -description = "Internationalized Domain Names in Applications (IDNA)" -name = "idna" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "2.8" - -[[package]] -category = "dev" -description = "Getting image size from png/jpeg/jpeg2000/gif file" -name = "imagesize" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "1.1.0" - -[[package]] -category = "dev" -description = "Read metadata from Python packages" -marker = "python_version < \"3.8\"" -name = "importlib-metadata" -optional = false -python-versions = ">=2.7,!=3.0,!=3.1,!=3.2,!=3.3" -version = "0.23" - -[package.dependencies] -zipp = ">=0.5" - -[[package]] -category = "dev" -description = "A very fast and expressive template engine." -name = "jinja2" -optional = false -python-versions = "*" -version = "2.10.3" - -[package.dependencies] -MarkupSafe = ">=0.23" - -[[package]] -category = "main" -description = "" -name = "localpubsub" -optional = false -python-versions = "*" -version = "0.0.4" - -[[package]] -category = "dev" -description = "Safely add untrusted strings to HTML/XML markup." -name = "markupsafe" -optional = false -python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*" -version = "1.1.1" - -[[package]] -category = "dev" -description = "Rolling backport of unittest.mock for all Pythons" -name = "mock" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "3.0.5" - -[package.dependencies] -six = "*" - -[[package]] -category = "dev" -description = "More routines for operating on iterables, beyond itertools" -name = "more-itertools" -optional = false -python-versions = ">=3.4" -version = "7.2.0" - -[[package]] -category = "main" -description = "Optional static typing for Python" -name = "mypy" -optional = false -python-versions = ">=3.5" -version = "0.740" - -[package.dependencies] -mypy-extensions = ">=0.4.0,<0.5.0" -typed-ast = ">=1.4.0,<1.5.0" -typing-extensions = ">=3.7.4" - -[[package]] -category = "main" -description = "Experimental type system extensions for programs checked with the mypy typechecker." -name = "mypy-extensions" -optional = false -python-versions = "*" -version = "0.4.3" - -[[package]] -category = "main" -description = "NumPy is the fundamental package for array computing with Python." -name = "numpy" -optional = false -python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*" -version = "1.16.1" - -[[package]] -category = "main" -description = "Wrapper package for OpenCV python bindings." -name = "opencv-python" -optional = false -python-versions = "*" -version = "3.4.5.20" - -[package.dependencies] -numpy = ">=1.11.1" - -[[package]] -category = "dev" -description = "Core utilities for Python packages" -name = "packaging" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "19.2" - -[package.dependencies] -pyparsing = ">=2.0.2" -six = "*" - -[[package]] -category = "dev" -description = "plugin and hook calling mechanisms for python" -name = "pluggy" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "0.13.0" - -[package.dependencies] -[package.dependencies.importlib-metadata] -python = "<3.8" -version = ">=0.12" - -[[package]] -category = "dev" -description = "library with cross-python path, ini-parsing, io, code, log facilities" -name = "py" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "1.8.0" - -[[package]] -category = "main" -description = "Python docstring style checker" -name = "pydocstyle" -optional = false -python-versions = ">=3.4" -version = "4.0.1" - -[package.dependencies] -snowballstemmer = "*" - -[[package]] -category = "dev" -description = "Pygments is a syntax highlighting package written in Python." -name = "pygments" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -version = "2.4.2" - -[[package]] -category = "dev" -description = "Python parsing module" -name = "pyparsing" -optional = false -python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" -version = "2.4.4" - -[[package]] -category = "dev" -description = "pytest: simple powerful testing with Python" -name = "pytest" -optional = false -python-versions = ">=3.5" -version = "5.2.1" - -[package.dependencies] -atomicwrites = ">=1.0" -attrs = ">=17.4.0" -colorama = "*" -more-itertools = ">=4.0.0" -packaging = "*" -pluggy = ">=0.12,<1.0" -py = ">=1.5.0" -wcwidth = "*" - -[package.dependencies.importlib-metadata] -python = "<3.8" -version = ">=0.12" - -[[package]] -category = "dev" -description = "World timezone definitions, modern and historical" -name = "pytz" -optional = false -python-versions = "*" -version = "2019.3" - -[[package]] -category = "main" -description = "Python bindings for 0MQ" -name = "pyzmq" -optional = false -python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*" -version = "18.1.0" - -[[package]] -category = "dev" -description = "Python HTTP for Humans." -name = "requests" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -version = "2.22.0" - -[package.dependencies] -certifi = ">=2017.4.17" -chardet = ">=3.0.2,<3.1.0" -idna = ">=2.5,<2.9" -urllib3 = ">=1.21.1,<1.25.0 || >1.25.0,<1.25.1 || >1.25.1,<1.26" - -[[package]] -category = "dev" -description = "Python 2 and 3 compatibility utilities" -name = "six" -optional = false -python-versions = ">=2.6, !=3.0.*, !=3.1.*" -version = "1.13.0" - -[[package]] -category = "main" -description = "This package provides 26 stemmers for 25 languages generated from Snowball algorithms." -name = "snowballstemmer" -optional = false -python-versions = "*" -version = "2.0.0" - -[[package]] -category = "dev" -description = "Python documentation generator" -name = "sphinx" -optional = false -python-versions = ">=3.5" -version = "2.2.1" - -[package.dependencies] -Jinja2 = ">=2.3" -Pygments = ">=2.0" -alabaster = ">=0.7,<0.8" -babel = ">=1.3,<2.0 || >2.0" -colorama = ">=0.3.5" -docutils = ">=0.12" -imagesize = "*" -packaging = "*" -requests = ">=2.5.0" -setuptools = "*" -snowballstemmer = ">=1.1" -sphinxcontrib-applehelp = "*" -sphinxcontrib-devhelp = "*" -sphinxcontrib-htmlhelp = "*" -sphinxcontrib-jsmath = "*" -sphinxcontrib-qthelp = "*" -sphinxcontrib-serializinghtml = "*" - -[[package]] -category = "dev" -description = "" -name = "sphinxcontrib-applehelp" -optional = false -python-versions = "*" -version = "1.0.1" - -[[package]] -category = "dev" -description = "" -name = "sphinxcontrib-devhelp" -optional = false -python-versions = "*" -version = "1.0.1" - -[[package]] -category = "dev" -description = "" -name = "sphinxcontrib-htmlhelp" -optional = false -python-versions = "*" -version = "1.0.2" - -[[package]] -category = "dev" -description = "A sphinx extension which renders display math in HTML via JavaScript" -name = "sphinxcontrib-jsmath" -optional = false -python-versions = ">=3.5" -version = "1.0.1" - -[[package]] -category = "dev" -description = "" -name = "sphinxcontrib-qthelp" -optional = false -python-versions = "*" -version = "1.0.2" - -[[package]] -category = "dev" -description = "" -name = "sphinxcontrib-serializinghtml" -optional = false -python-versions = "*" -version = "1.1.3" - -[[package]] -category = "main" -description = "Python Library for Tom's Obvious, Minimal Language" -name = "toml" -optional = false -python-versions = "*" -version = "0.10.0" - -[[package]] -category = "dev" -description = "tox is a generic virtualenv management and test command line tool" -name = "tox" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -version = "3.14.0" - -[package.dependencies] -filelock = ">=3.0.0,<4" -packaging = ">=14" -pluggy = ">=0.12.0,<1" -py = ">=1.4.17,<2" -six = ">=1.0.0,<2" -toml = ">=0.9.4" -virtualenv = ">=14.0.0" - -[package.dependencies.importlib-metadata] -python = "<3.8" -version = ">=0.12,<1" - -[[package]] -category = "dev" -description = "Seamless integration of tox into GitHub Actions" -name = "tox-gh-actions" -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" -version = "0.3.0" - -[package.dependencies] -tox = ">=3.12.2" - -[[package]] -category = "main" -description = "a fork of Python 2 and 3 ast modules with type comment support" -name = "typed-ast" -optional = false -python-versions = "*" -version = "1.4.0" - -[[package]] -category = "dev" -description = "Type Hints for Python" -name = "typing" -optional = false -python-versions = "*" -version = "3.7.4.1" - -[[package]] -category = "main" -description = "Backported and Experimental Type Hints for Python 3.5+" -name = "typing-extensions" -optional = false -python-versions = "*" -version = "3.7.4.1" - -[[package]] -category = "dev" -description = "HTTP library with thread-safe connection pooling, file post, and more." -name = "urllib3" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, <4" -version = "1.25.6" - -[[package]] -category = "dev" -description = "Virtual Python Environment builder" -name = "virtualenv" -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7" -version = "16.7.7" - -[[package]] -category = "dev" -description = "Measures number of Terminal column cells of wide-character codes" -name = "wcwidth" -optional = false -python-versions = "*" -version = "0.1.7" - -[[package]] -category = "dev" -description = "Backport of pathlib-compatible object wrapper for zip files" -marker = "python_version < \"3.8\"" -name = "zipp" -optional = false -python-versions = ">=2.7" -version = "0.6.0" - -[package.dependencies] -more-itertools = "*" - -[metadata] -content-hash = "2e6c77bc331fe05281692b38131903b8bb0c893df53e30e476e9cf18a8f3c540" -python-versions = "^3.6" - -[metadata.hashes] -alabaster = ["446438bdcca0e05bd45ea2de1668c1d9b032e1a9154c2c259092d77031ddd359", "a661d72d58e6ea8a57f7a86e37d86716863ee5e92788398526d58b26a4e4dc02"] -appdirs = ["9e5896d1372858f8dd3344faf4e5014d21849c756c8d5701f78f8a103b372d92", "d8b24664561d0d34ddfaec54636d502d7cea6e29c3eaf68f3df6180863e2166e"] -atomicwrites = ["03472c30eb2c5d1ba9227e4c2ca66ab8287fbfbbda3888aa93dc2e28fc6811b4", "75a9445bac02d8d058d5e1fe689654ba5a6556a1dfd8ce6ec55a0ed79866cfa6"] -attrs = ["08a96c641c3a74e44eb59afb61a24f2cb9f4d7188748e76ba4bb5edfa3cb7d1c", "f7b7ce16570fe9965acd6d30101a28f62fb4a7f9e926b3bbc9b61f8b04247e72"] -babel = ["af92e6106cb7c55286b25b38ad7695f8b4efb36a90ba483d7f7a6628c46158ab", "e86135ae101e31e2c8ec20a4e0c5220f4eed12487d5cf3f78be7e98d3a57fc28"] -black = ["817243426042db1d36617910df579a54f1afd659adb96fc5032fcf4b36209739", "e030a9a28f542debc08acceb273f228ac422798e5215ba2a791a6ddeaaca22a5"] -certifi = ["e4f3620cfea4f83eedc95b24abd9cd56f3c4b146dd0177e83a21b4eb49e21e50", "fd7c7c74727ddcf00e9acd26bba8da604ffec95bf1c2144e67aff7a8b50e6cef"] -chardet = ["84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae", "fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691"] -click = ["2335065e6395b9e67ca716de5f7526736bfa6ceead690adf616d925bdc622b13", "5b94b49521f6456670fdb30cd82a4eca9412788a93fa6dd6df72c94d5a8ff2d7"] -colorama = ["05eed71e2e327246ad6b38c540c4a3117230b19679b875190486ddd2d721422d", "f8ac84de7840f5b9c4e3347b3c1eaa50f7e49c2b07596221daec5edaabbd7c48"] -coverage = ["08907593569fe59baca0bf152c43f3863201efb6113ecb38ce7e97ce339805a6", "0be0f1ed45fc0c185cfd4ecc19a1d6532d72f86a2bac9de7e24541febad72650", "141f08ed3c4b1847015e2cd62ec06d35e67a3ac185c26f7635f4406b90afa9c5", "19e4df788a0581238e9390c85a7a09af39c7b539b29f25c89209e6c3e371270d", "23cc09ed395b03424d1ae30dcc292615c1372bfba7141eb85e11e50efaa6b351", "245388cda02af78276b479f299bbf3783ef0a6a6273037d7c60dc73b8d8d7755", "331cb5115673a20fb131dadd22f5bcaf7677ef758741312bee4937d71a14b2ef", "386e2e4090f0bc5df274e720105c342263423e77ee8826002dcffe0c9533dbca", "3a794ce50daee01c74a494919d5ebdc23d58873747fa0e288318728533a3e1ca", "60851187677b24c6085248f0a0b9b98d49cba7ecc7ec60ba6b9d2e5574ac1ee9", "63a9a5fc43b58735f65ed63d2cf43508f462dc49857da70b8980ad78d41d52fc", "6b62544bb68106e3f00b21c8930e83e584fdca005d4fffd29bb39fb3ffa03cb5", "6ba744056423ef8d450cf627289166da65903885272055fb4b5e113137cfa14f", "7494b0b0274c5072bddbfd5b4a6c6f18fbbe1ab1d22a41e99cd2d00c8f96ecfe", "826f32b9547c8091679ff292a82aca9c7b9650f9fda3e2ca6bf2ac905b7ce888", "93715dffbcd0678057f947f496484e906bf9509f5c1c38fc9ba3922893cda5f5", "9a334d6c83dfeadae576b4d633a71620d40d1c379129d587faa42ee3e2a85cce", "af7ed8a8aa6957aac47b4268631fa1df984643f07ef00acd374e456364b373f5", "bf0a7aed7f5521c7ca67febd57db473af4762b9622254291fbcbb8cd0ba5e33e", "bf1ef9eb901113a9805287e090452c05547578eaab1b62e4ad456fcc049a9b7e", "c0afd27bc0e307a1ffc04ca5ec010a290e49e3afbe841c5cafc5c5a80ecd81c9", "dd579709a87092c6dbee09d1b7cfa81831040705ffa12a1b248935274aee0437", "df6712284b2e44a065097846488f66840445eb987eb81b3cc6e4149e7b6982e1", "e07d9f1a23e9e93ab5c62902833bf3e4b1f65502927379148b6622686223125c", "e2ede7c1d45e65e209d6093b762e98e8318ddeff95317d07a27a2140b80cfd24", "e4ef9c164eb55123c62411f5936b5c2e521b12356037b6e1c2617cef45523d47", "eca2b7343524e7ba246cab8ff00cab47a2d6d54ada3b02772e908a45675722e2", "eee64c616adeff7db37cc37da4180a3a5b6177f5c46b187894e633f088fb5b28", "ef824cad1f980d27f26166f86856efe11eff9912c4fed97d3804820d43fa550c", "efc89291bd5a08855829a3c522df16d856455297cf35ae827a37edac45f466a7", "fa964bae817babece5aa2e8c1af841bebb6d0b9add8e637548809d040443fee0", "ff37757e068ae606659c28c3bd0d923f9d29a85de79bf25b2b34b148473b5025"] -docopt = ["49b3a825280bd66b3aa83585ef59c4a8c82f2c8a522dbe754a8bc8d08c85c491"] -docutils = ["6c4f696463b79f1fb8ba0c594b63840ebd41f059e92b31957c46b74a4599b6d0", "9e4d7ecfc600058e07ba661411a2b7de2fd0fafa17d1a7f7361cd47b1175c827", "a2aeea129088da402665e92e0b25b04b073c04b2dce4ab65caaa38b7ce2e1a99"] -filelock = ["18d82244ee114f543149c66a6e0c14e9c4f8a1044b5cdaadd0f82159d6a6ff59", "929b7d63ec5b7d6b71b0fa5ac14e030b3f70b75747cef1b10da9b879fef15836"] -idna = ["c357b3f628cf53ae2c4c05627ecc484553142ca23264e593d327bcde5e9c3407", "ea8b7f6188e6fa117537c3df7da9fc686d485087abf6ac197f9c46432f7e4a3c"] -imagesize = ["3f349de3eb99145973fefb7dbe38554414e5c30abd0c8e4b970a7c9d09f3a1d8", "f3832918bc3c66617f92e35f5d70729187676313caa60c187eb0f28b8fe5e3b5"] -importlib-metadata = ["aa18d7378b00b40847790e7c27e11673d7fed219354109d0e7b9e5b25dc3ad26", "d5f18a79777f3aa179c145737780282e27b508fc8fd688cb17c7a813e8bd39af"] -jinja2 = ["74320bb91f31270f9551d46522e33af46a80c3d619f4a4bf42b3164d30b5911f", "9fe95f19286cfefaa917656583d020be14e7859c6b0252588391e47db34527de"] -localpubsub = ["ec8f00993a53841b41d3455ea311b310c6e716b580dfbf7eddb73b18ab0c3207"] -markupsafe = ["00bc623926325b26bb9605ae9eae8a215691f33cae5df11ca5424f06f2d1f473", "09027a7803a62ca78792ad89403b1b7a73a01c8cb65909cd876f7fcebd79b161", "09c4b7f37d6c648cb13f9230d847adf22f8171b1ccc4d5682398e77f40309235", "1027c282dad077d0bae18be6794e6b6b8c91d58ed8a8d89a89d59693b9131db5", "24982cc2533820871eba85ba648cd53d8623687ff11cbb805be4ff7b4c971aff", "29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b", "43a55c2930bbc139570ac2452adf3d70cdbb3cfe5912c71cdce1c2c6bbd9c5d1", "46c99d2de99945ec5cb54f23c8cd5689f6d7177305ebff350a58ce5f8de1669e", "500d4957e52ddc3351cabf489e79c91c17f6e0899158447047588650b5e69183", "535f6fc4d397c1563d08b88e485c3496cf5784e927af890fb3c3aac7f933ec66", "62fe6c95e3ec8a7fad637b7f3d372c15ec1caa01ab47926cfdf7a75b40e0eac1", "6dd73240d2af64df90aa7c4e7481e23825ea70af4b4922f8ede5b9e35f78a3b1", "717ba8fe3ae9cc0006d7c451f0bb265ee07739daf76355d06366154ee68d221e", "79855e1c5b8da654cf486b830bd42c06e8780cea587384cf6545b7d9ac013a0b", "7c1699dfe0cf8ff607dbdcc1e9b9af1755371f92a68f706051cc8c37d447c905", "88e5fcfb52ee7b911e8bb6d6aa2fd21fbecc674eadd44118a9cc3863f938e735", "8defac2f2ccd6805ebf65f5eeb132adcf2ab57aa11fdf4c0dd5169a004710e7d", "98c7086708b163d425c67c7a91bad6e466bb99d797aa64f965e9d25c12111a5e", "9add70b36c5666a2ed02b43b335fe19002ee5235efd4b8a89bfcf9005bebac0d", "9bf40443012702a1d2070043cb6291650a0841ece432556f784f004937f0f32c", "ade5e387d2ad0d7ebf59146cc00c8044acbd863725f887353a10df825fc8ae21", "b00c1de48212e4cc9603895652c5c410df699856a2853135b3967591e4beebc2", "b1282f8c00509d99fef04d8ba936b156d419be841854fe901d8ae224c59f0be5", "b2051432115498d3562c084a49bba65d97cf251f5a331c64a12ee7e04dacc51b", "ba59edeaa2fc6114428f1637ffff42da1e311e29382d81b339c1817d37ec93c6", "c8716a48d94b06bb3b2524c2b77e055fb313aeb4ea620c8dd03a105574ba704f", "cd5df75523866410809ca100dc9681e301e3c27567cf498077e8551b6d20e42f", "e249096428b3ae81b08327a63a485ad0878de3fb939049038579ac0ef61e17e7"] -mock = ["83657d894c90d5681d62155c82bda9c1187827525880eda8ff5df4ec813437c3", "d157e52d4e5b938c550f39eb2fd15610db062441a9c2747d3dbfa9298211d0f8"] -more-itertools = ["409cd48d4db7052af495b09dec721011634af3753ae1ef92d2b32f73a745f832", "92b8c4b06dac4f0611c0729b2f2ede52b2e1bac1ab48f089c7ddc12e26bb60c4"] -mypy = ["1521c186a3d200c399bd5573c828ea2db1362af7209b2adb1bb8532cea2fb36f", "31a046ab040a84a0fc38bc93694876398e62bc9f35eca8ccbf6418b7297f4c00", "3b1a411909c84b2ae9b8283b58b48541654b918e8513c20a400bb946aa9111ae", "48c8bc99380575deb39f5d3400ebb6a8a1cb5cc669bbba4d3bb30f904e0a0e7d", "540c9caa57a22d0d5d3c69047cc9dd0094d49782603eb03069821b41f9e970e9", "672e418425d957e276c291930a3921b4a6413204f53fe7c37cad7bc57b9a3391", "6ed3b9b3fdc7193ea7aca6f3c20549b377a56f28769783a8f27191903a54170f", "9371290aa2cad5ad133e4cdc43892778efd13293406f7340b9ffe99d5ec7c1d9", "ace6ac1d0f87d4072f05b5468a084a45b4eda970e4d26704f201e06d47ab2990", "b428f883d2b3fe1d052c630642cc6afddd07d5cd7873da948644508be3b9d4a7", "d5bf0e6ec8ba346a2cf35cb55bf4adfddbc6b6576fcc9e10863daa523e418dbb", "d7574e283f83c08501607586b3167728c58e8442947e027d2d4c7dcd6d82f453", "dc889c84241a857c263a2b1cd1121507db7d5b5f5e87e77147097230f374d10b", "f4748697b349f373002656bf32fede706a0e713d67bfdcf04edf39b1f61d46eb"] -mypy-extensions = ["090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d", "2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"] -numpy = ["0cdbbaa30ae69281b18dd995d3079c4e552ad6d5426977f66b9a2a95f11f552a", "2b0cca1049bd39d1879fa4d598624cafe82d35529c72de1b3d528d68031cdd95", "31d3fe5b673e99d33d70cfee2ea8fe8dccd60f265c3ed990873a88647e3dd288", "34dd4922aab246c39bf5df03ca653d6265e65971deca6784c956bf356bca6197", "384e2dfa03da7c8d54f8f934f61b6a5e4e1ebb56a65b287567629d6c14578003", "392e2ea22b41a22c0289a88053204b616181288162ba78e6823e1760309d5277", "4341a39fc085f31a583be505eabf00e17c619b469fef78dc7e8241385bfddaa4", "45080f065dcaa573ebecbfe13cdd86e8c0a68c4e999aa06bd365374ea7137706", "485cb1eb4c9962f4cd042fed9424482ec1d83fee5dc2ef3f2552ac47852cb259", "575cefd28d3e0da85b0864506ae26b06483ee4a906e308be5a7ad11083f9d757", "62784b35df7de7ca4d0d81c5b6af5983f48c5cdef32fc3635b445674e56e3266", "69c152f7c11bf3b4fc11bc4cc62eb0334371c0db6844ebace43b7c815b602805", "6ccfdcefd287f252cf1ea7a3f1656070da330c4a5658e43ad223269165cdf977", "7298fbd73c0b3eff1d53dc9b9bdb7add8797bb55eeee38c8ccd7906755ba28af", "79463d918d1bf3aeb9186e3df17ddb0baca443f41371df422f99ee94f4f2bbfe", "8bbee788d82c0ac656536de70e817af09b7694f5326b0ef08e5c1014fcb96bb3", "a863957192855c4c57f60a75a1ac06ce5362ad18506d362dd807e194b4baf3ce", "ae602ba425fb2b074e16d125cdce4f0194903da935b2e7fe284ebecca6d92e76", "b13faa258b20fa66d29011f99fdf498641ca74a0a6d9266bc27d83c70fea4a6a", "c2c39d69266621dd7464e2bb740d6eb5abc64ddc339cc97aa669f3bb4d75c103", "e9c88f173d31909d881a60f08a8494e63f1aff2a4052476b24d4f50e82c47e24", "f1a29267ac29fff0913de0f11f3a9edfcd3f39595f467026c29376fad243ebe3", "f69dde0c5a137d887676a8129373e44366055cf19d1b434e853310c7a1e68f93"] -opencv-python = ["042b141424978d2cc9b32905a22b137d39d9f61d60f9cd970d9ed35da8b508d8", "0550060919e4aa0083c552e1e9d3e6548fe946a34bbe573b94ea6e9bf9d8da4e", "154daf889e23b0c6b27449033561699378094230e3b2a29515f74b06a682e806", "1f48aa26bde4607d7e797b768ec7cac796f8b98e3cc313de4942193731daa155", "2c6c43d95e618f7c97c81553daa6cc476f83cb9b4782c131b104171d909427cc", "42d53bdb47fadc7d266c88a00120f452171bfda06f8cbb12706106c26a28322d", "45ea2d208277c044d7fb9ec0f47f44227bcabfcacb0cd4687f217cb01e7c133d", "4fb8bcc669c5be8f342b6ea7dcba00c7c4bba9e0dd68a48a5e3428e396853150", "54bfe1e32f0fcd919c1883f173787bef019aa38c6202259265b1fa15270602f4", "5ffc9d9d7922b808fed6ed4bbbc596b799d2ba93cceb2dd87a03b6489051d7e2", "70cb9b121649c5bfba3aba29b517e9ed34ae9fb9dbff5e211f979a778f230cc2", "77cc97703bbecad79484cfcd49a7e21b81ba7d481ae7a030a482347760fd6694", "90ad5029ff9a8dde58b01aa6d8903989dde9c13fc88f403d1af20a4ae8917ba2", "9fdaab937a0f9e8237c89bac8ff01279b2321e74fe0cdeaeb3710854d96819c8", "a1298bfdb7475740a825c28c9c0ecce4d80225376702c72b7fe296f7eb9f3e0b", "a16698f2d1a4c7f8c604482f252ac3b44fb680878e84e2b091b76ba6cb23d4b0", "a2141cfb98c7e6d3ab7c50b511b02d688057417ac0a89d64795394a0e91369b4", "ac3d16be4662ce179187b51ae5698f0d25b970ab9e79d7216f6587623703c61a", "b1951fece88abb0d630a8b93eae2fa6cbf085dfcd727b34ccd9151008965cc7c", "c5c95a5e8f7aaa90da39604fe2e467b914183c81c7c776e2cade0173922c48cc", "cfe04992f508389e0a21eebb3b109c560b4b55ce66eab9783baa74f4b51aef3b", "d7eae953eaf8f9a0d9c3aa54dc59ff80322f156a5293940e5ab50ff7d46f6659", "de08cda9999a6095552d26ed96fa86519c93bccd80a1cd7762feec9e4f935e43", "e4f46417e7a9b9df050b1bc2596a33cc7036a2cb0ec8d4a03bd80c7601ef87be", "e50f2897b85eb40bf6b9a51fb62ecc0b00fb18edaf376febf8cf55d29baadf58", "e91df696f8e84a306b3c95c041df2e19d752ede94006f388483d47105e15185d", "ee8de5169d1f2639e9a7f76a59eb1c5d7708051fc3f7e336bf430b1b61533922"] -packaging = ["28b924174df7a2fa32c1953825ff29c61e2f5e082343165438812f00d3a7fc47", "d9551545c6d761f3def1677baf08ab2a3ca17c56879e70fecba2fc4dde4ed108"] -pluggy = ["0db4b7601aae1d35b4a033282da476845aa19185c1e6964b25cf324b5e4ec3e6", "fa5fa1622fa6dd5c030e9cad086fa19ef6a0cf6d7a2d12318e10cb49d6d68f34"] -py = ["64f65755aee5b381cea27766a3a147c3f15b9b6b9ac88676de66ba2ae36793fa", "dc639b046a6e2cff5bbe40194ad65936d6ba360b52b3c3fe1d08a82dd50b5e53"] -pydocstyle = ["04c84e034ebb56eb6396c820442b8c4499ac5eb94a3bda88951ac3dc519b6058", "66aff87ffe34b1e49bff2dd03a88ce6843be2f3346b0c9814410d34987fbab59"] -pygments = ["71e430bc85c88a430f000ac1d9b331d2407f681d6f6aec95e8bcfbc3df5b0127", "881c4c157e45f30af185c1ffe8d549d48ac9127433f2c380c24b84572ad66297"] -pyparsing = ["4acadc9a2b96c19fe00932a38ca63e601180c39a189a696abce1eaab641447e1", "61b5ed888beab19ddccab3478910e2076a6b5a0295dffc43021890e136edf764"] -pytest = ["7e4800063ccfc306a53c461442526c5571e1462f61583506ce97e4da6a1d88c8", "ca563435f4941d0cb34767301c27bc65c510cb82e90b9ecf9cb52dc2c63caaa0"] -pytz = ["1c557d7d0e871de1f5ccd5833f60fb2550652da6be2693c1e02300743d21500d", "b02c06db6cf09c12dd25137e563b31700d3b80fcc4ad23abb7a315f2789819be"] -pyzmq = ["01636e95a88d60118479041c6aaaaf5419c6485b7b1d37c9c4dd424b7b9f1121", "021dba0d1436516092c624359e5da51472b11ba8edffa334218912f7e8b65467", "0463bd941b6aead494d4035f7eebd70035293dd6caf8425993e85ad41de13fa3", "05fd51edd81eed798fccafdd49c936b6c166ffae7b32482e4d6d6a2e196af4e6", "1fadc8fbdf3d22753c36d4172169d184ee6654f8d6539e7af25029643363c490", "22efa0596cf245a78a99060fe5682c4cd00c58bb7614271129215c889062db80", "260c70b7c018905ec3659d0f04db735ac830fe27236e43b9dc0532cf7c9873ef", "2762c45e289732d4450406cedca35a9d4d71e449131ba2f491e0bf473e3d2ff2", "2fc6cada8dc53521c1189596f1898d45c5f68603194d3a6453d6db4b27f4e12e", "343b9710a61f2b167673bea1974e70b5dccfe64b5ed10626798f08c1f7227e72", "41bf96d5f554598a0632c3ec28e3026f1d6591a50f580df38eff0b8067efb9e7", "856b2cdf7a1e2cbb84928e1e8db0ea4018709b39804103d3a409e5584f553f57", "85b869abc894672de9aecdf032158ea8ad01e2f0c3b09ef60e3687fb79418096", "9055ed3f443edae7dc80f253fc54257f8455fc3062a7832c60887409e27c9f82", "93f44739db69234c013a16990e43db1aa0af3cf5a4b8b377d028ff24515fbeb3", "98fa3e75ccb22c0dc99654e3dd9ff693b956861459e8c8e8734dd6247b89eb29", "9a22c94d2e93af8bebd4fcf5fa38830f5e3b1ff0d4424e2912b07651eb1bafb4", "a7d3f4b4bbb5d7866ae727763268b5c15797cbd7b63ea17f3b0ec1067da8994b", "b645a49376547b3816433a7e2d2a99135c8e651e50497e7ecac3bd126e4bea16", "cf0765822e78cf9e45451647a346d443f66792aba906bc340f4e0ac7870c169c", "dc398e1e047efb18bfab7a8989346c6921a847feae2cad69fedf6ca12fb99e2c", "dd5995ae2e80044e33b5077fb4bc2b0c1788ac6feaf15a6b87a00c14b4bdd682", "e03fe5e07e70f245dc9013a9d48ae8cc4b10c33a1968039c5a3b64b5d01d083d", "ea09a306144dff2795e48439883349819bef2c53c0ee62a3c2fae429451843bb", "f4e37f33da282c3c319849877e34f97f0a3acec09622ec61b7333205bdd13b52", "fa4bad0d1d173dee3e8ef3c3eb6b2bb6c723fc7a661eeecc1ecb2fa99860dd45"] -requests = ["11e007a8a2aa0323f5a921e9e6a2d7e4e67d9877e85773fba9ba6419025cbeb4", "9cf5292fcd0f598c671cfc1e0d7d1a7f13bb8085e9a590f48c010551dc6c4b31"] -six = ["1f1b7d42e254082a9db6279deae68afb421ceba6158efa6131de7b3003ee93fd", "30f610279e8b2578cab6db20741130331735c781b56053c59c4076da27f06b66"] -snowballstemmer = ["209f257d7533fdb3cb73bdbd24f436239ca3b2fa67d56f6ff88e86be08cc5ef0", "df3bac3df4c2c01363f3dd2cfa78cce2840a79b9f1c2d2de9ce8d31683992f52"] -sphinx = ["31088dfb95359384b1005619827eaee3056243798c62724fd3fa4b84ee4d71bd", "52286a0b9d7caa31efee301ec4300dbdab23c3b05da1c9024b4e84896fb73d79"] -sphinxcontrib-applehelp = ["edaa0ab2b2bc74403149cb0209d6775c96de797dfd5b5e2a71981309efab3897", "fb8dee85af95e5c30c91f10e7eb3c8967308518e0f7488a2828ef7bc191d0d5d"] -sphinxcontrib-devhelp = ["6c64b077937330a9128a4da74586e8c2130262f014689b4b89e2d08ee7294a34", "9512ecb00a2b0821a146736b39f7aeb90759834b07e81e8cc23a9c70bacb9981"] -sphinxcontrib-htmlhelp = ["4670f99f8951bd78cd4ad2ab962f798f5618b17675c35c5ac3b2132a14ea8422", "d4fd39a65a625c9df86d7fa8a2d9f3cd8299a3a4b15db63b50aac9e161d8eff7"] -sphinxcontrib-jsmath = ["2ec2eaebfb78f3f2078e73666b1415417a116cc848b72e5172e596c871103178", "a9925e4a4587247ed2191a22df5f6970656cb8ca2bd6284309578f2153e0c4b8"] -sphinxcontrib-qthelp = ["513049b93031beb1f57d4daea74068a4feb77aa5630f856fcff2e50de14e9a20", "79465ce11ae5694ff165becda529a600c754f4bc459778778c7017374d4d406f"] -sphinxcontrib-serializinghtml = ["c0efb33f8052c04fd7a26c0a07f1678e8512e0faec19f4aa8f2473a8b81d5227", "db6615af393650bf1151a6cd39120c29abaf93cc60db8c48eb2dddbfdc3a9768"] -toml = ["229f81c57791a41d65e399fc06bf0848bab550a9dfd5ed66df18ce5f05e73d5c", "235682dd292d5899d361a811df37e04a8828a5b1da3115886b73cf81ebc9100e", "f1db651f9657708513243e61e6cc67d101a39bad662eaa9b5546f789338e07a3"] -tox = ["0bc216b6a2e6afe764476b4a07edf2c1dab99ed82bb146a1130b2e828f5bff5e", "c4f6b319c20ba4913dbfe71ebfd14ff95d1853c4231493608182f66e566ecfe1"] -tox-gh-actions = ["202c23c7de04f060d956961c65bfabcb6a13f08321225a05f902470b1a3e824a", "f943d9a7009d97ed1aac1b0051b3eef97b07176bc040a2307de9461629fcdf88"] -typed-ast = ["1170afa46a3799e18b4c977777ce137bb53c7485379d9706af8a59f2ea1aa161", "18511a0b3e7922276346bcb47e2ef9f38fb90fd31cb9223eed42c85d1312344e", "262c247a82d005e43b5b7f69aff746370538e176131c32dda9cb0f324d27141e", "2b907eb046d049bcd9892e3076c7a6456c93a25bebfe554e931620c90e6a25b0", "354c16e5babd09f5cb0ee000d54cfa38401d8b8891eefa878ac772f827181a3c", "48e5b1e71f25cfdef98b013263a88d7145879fbb2d5185f2a0c79fa7ebbeae47", "4e0b70c6fc4d010f8107726af5fd37921b666f5b31d9331f0bd24ad9a088e631", "630968c5cdee51a11c05a30453f8cd65e0cc1d2ad0d9192819df9978984529f4", "66480f95b8167c9c5c5c87f32cf437d585937970f3fc24386f313a4c97b44e34", "71211d26ffd12d63a83e079ff258ac9d56a1376a25bc80b1cdcdf601b855b90b", "7954560051331d003b4e2b3eb822d9dd2e376fa4f6d98fee32f452f52dd6ebb2", "838997f4310012cf2e1ad3803bce2f3402e9ffb71ded61b5ee22617b3a7f6b6e", "95bd11af7eafc16e829af2d3df510cecfd4387f6453355188342c3e79a2ec87a", "bc6c7d3fa1325a0c6613512a093bc2a2a15aeec350451cbdf9e1d4bffe3e3233", "cc34a6f5b426748a507dd5d1de4c1978f2eb5626d51326e43280941206c209e1", "d755f03c1e4a51e9b24d899561fec4ccaf51f210d52abdf8c07ee2849b212a36", "d7c45933b1bdfaf9f36c579671fec15d25b06c8398f113dab64c18ed1adda01d", "d896919306dd0aa22d0132f62a1b78d11aaf4c9fc5b3410d3c666b818191630a", "fdc1c9bbf79510b76408840e009ed65958feba92a88833cdceecff93ae8fff66", "ffde2fbfad571af120fcbfbbc61c72469e72f550d676c3342492a9dfdefb8f12"] -typing = ["91dfe6f3f706ee8cc32d38edbbf304e9b7583fb37108fef38229617f8b3eba23", "c8cabb5ab8945cd2f54917be357d134db9cc1eb039e59d1606dc1e60cb1d9d36", "f38d83c5a7a7086543a0f649564d661859c5146a85775ab90c0d2f93ffaa9714"] -typing-extensions = ["091ecc894d5e908ac75209f10d5b4f118fbdb2eb1ede6a63544054bb1edb41f2", "910f4656f54de5993ad9304959ce9bb903f90aadc7c67a0bef07e678014e892d", "cf8b63fedea4d89bab840ecbb93e75578af28f76f66c35889bd7065f5af88575"] -urllib3 = ["3de946ffbed6e6746608990594d08faac602528ac7015ac28d33cee6a45b7398", "9a107b99a5393caf59c7aa3c1249c16e6879447533d0887f4336dde834c7be86"] -virtualenv = ["11cb4608930d5fd3afb545ecf8db83fa50e1f96fc4fca80c94b07d2c83146589", "d257bb3773e48cac60e475a19b608996c73f4d333b3ba2e4e57d5ac6134e0136"] -wcwidth = ["3df37372226d6e63e1b1e1eda15c594bca98a22d33a23832a90998faa96bc65e", "f4ebe71925af7b40a864553f761ed559b43544f8f71746c2d756c7fe788ade7c"] -zipp = ["3718b1cbcd963c7d4c5511a8240812904164b7f381b647143a89d3b98f9bcd8e", "f06903e9f1f43b12d371004b4ac7b06ab39a44adc747266928ae6debfa7b3335"] diff --git a/pyproject.toml b/pyproject.toml deleted file mode 100644 index 0dfb68f..0000000 --- a/pyproject.toml +++ /dev/null @@ -1,36 +0,0 @@ -[tool.poetry] -name = 'displayarray' -version = '1.1.1' -description = 'Tool for displaying numpy arrays.' -authors = ['SimLeek '] -license = 'MIT' -readme = "README.rst" -repository = "https://github.com/simleek/displayarray" - -[tool.poetry.dependencies] -python = "^3.6" -opencv_python = "^4*" -docopt = "0.6.2" -numpy = "1.16.1" -localpubsub = "0.0.4" -pyzmq = "18.1.0" - -[tool.poetry.dev-dependencies] -pytest = "5.2.1" -typing = "3.7.4.1" -mock = "^3.0" -tox = "^3.14" -tox-gh-actions = "^0.3.0" -coverage = "^4.5" -sphinx = "^2.2" -black = {version = "^18.3-alpha.0", allows-prereleases = true} -mypy = "^0.740.0" -pydocstyle = "^4.0" - -[tool.poetry.scripts] -displayarray = "displayarray.__main__:main" - -[build-system] -requires = ['poetry'] -build-backend = "poetry.masonry.api" - diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..0326a7f --- /dev/null +++ b/setup.py @@ -0,0 +1,64 @@ +# -*- coding: utf-8 -*- + +# DO NOT EDIT THIS FILE! +# This file has been autogenerated by dephell <3 +# https://github.com/dephell/dephell + +try: + from setuptools import setup +except ImportError: + from distutils.core import setup + + +import os.path + +readme = "" +here = os.path.abspath(os.path.dirname(__file__)) +readme_path = os.path.join(here, "README.rst") +if os.path.exists(readme_path): + with open(readme_path, "rb") as stream: + readme = stream.read().decode("utf8") + + +setup( + long_description=readme, + name="displayarray", + version="1.2.0", + description="Tool for displaying numpy arrays.", + python_requires="==3.*,>=3.6.0", + project_urls={"repository": "https://github.com/simleek/displayarray"}, + author="SimLeek", + author_email="simulator.leek@gmail.com", + license="MIT", + entry_points={"console_scripts": ["displayarray = displayarray.__main__:main"]}, + packages=[ + "displayarray", + "displayarray.effects", + "displayarray.frame", + "displayarray.window", + ], + package_dir={"": "."}, + package_data={}, + install_requires=[ + "docopt==0.6.2", + "localpubsub==0.0.4", + "numpy==1.16.1", + "opencv-python==4.*,>=4.0.0", + "pyzmq==18.1.0", + ], + extras_require={ + "linux": ["PyV4L2Cam @ git+https://github.com/SimLeek/PyV4L2Cam"], + "dev": [ + "black==18.*,>=18.3.0.a0", + "coverage==4.*,>=4.5.0", + "mock==3.*,>=3.0.0", + "mypy==0.*,>=0.740.0", + "pydocstyle==4.*,>=4.0.0", + "pytest==5.2.1", + "sphinx==2.*,>=2.2.0", + "tox==3.*,>=3.14.0", + "tox-gh-actions==0.*,>=0.3.0", + "typing==3.7.4.1", + ], + }, +) diff --git a/tests/frame/test_frame_publishing.py b/tests/frame/test_frame_publishing.py index 2f73124..c01c2a4 100644 --- a/tests/frame/test_frame_publishing.py +++ b/tests/frame/test_frame_publishing.py @@ -42,7 +42,7 @@ def test_pub_cam_int(): cam_pub.assert_has_calls([mock.call(img)] * 4) - reg_cam.assert_called_once_with("0") + reg_cam.assert_called_once_with("0", cap) cam_cmd_sub.assert_called_once_with("0") cap.set.assert_has_calls( diff --git a/tests/frame/test_frame_updater.py b/tests/frame/test_frame_updater.py index 1fe291e..85e39bd 100644 --- a/tests/frame/test_frame_updater.py +++ b/tests/frame/test_frame_updater.py @@ -57,7 +57,7 @@ def test_loop(): ud.loop() - mock_pubcam_thread.assert_called_once_with(0, (-1, -1), True, float("inf")) + mock_pubcam_thread.assert_called_once_with(0, (-1, -1), True, float("inf"), "") mock_frame_sub.assert_called_once_with("0") handler_cmd_sub.assert_called_once_with("0") sub_cam.get.assert_has_calls([mock.call(blocking=True, timeout=1.0)] * 3) diff --git a/tests/window/test_subscriber_windows.py b/tests/window/test_subscriber_windows.py index 827da4f..fd98030 100644 --- a/tests/window/test_subscriber_windows.py +++ b/tests/window/test_subscriber_windows.py @@ -495,8 +495,12 @@ def test_display(): fup.assert_has_calls( [ - mock.call(0, fps_limit=float("inf"), request_size=(50, 50)), - mock.call(1, fps_limit=float("inf"), request_size=(50, 50)), + mock.call( + 0, force_backend="", fps_limit=float("inf"), request_size=(50, 50) + ), + mock.call( + 1, force_backend="", fps_limit=float("inf"), request_size=(50, 50) + ), ] ) assert fup_inst.start.call_count == 2 @@ -541,10 +545,18 @@ def test_display_callbacks(): fup.assert_has_calls( [ mock.call( - 0, callbacks=[cb], fps_limit=float("inf"), request_size=(-1, -1) + 0, + callbacks=[cb], + force_backend="", + fps_limit=float("inf"), + request_size=(-1, -1), ), mock.call( - 1, callbacks=[cb], fps_limit=float("inf"), request_size=(-1, -1) + 1, + callbacks=[cb], + force_backend="", + fps_limit=float("inf"), + request_size=(-1, -1), ), ] ) @@ -557,8 +569,20 @@ def test_display_callbacks(): fup.assert_has_calls( [ - mock.call(0, callbacks=[cb, cb2], fps_limit=60, request_size=(-1, -1)), - mock.call(1, callbacks=[cb, cb2], fps_limit=60, request_size=(-1, -1)), + mock.call( + 0, + callbacks=[cb, cb2], + force_backend="", + fps_limit=60, + request_size=(-1, -1), + ), + mock.call( + 1, + callbacks=[cb, cb2], + force_backend="", + fps_limit=60, + request_size=(-1, -1), + ), ] ) @@ -579,16 +603,25 @@ def test_display_callbacks_dict(): fup.assert_has_calls( [ mock.call( - 0, callbacks=[cb1], fps_limit=float("inf"), request_size=(-1, -1) - ), - mock.call( - 1, - callbacks=[cb1, cb2], + 0, + callbacks=[cb1], + force_backend="", fps_limit=float("inf"), request_size=(-1, -1), ), mock.call( - 2, callbacks=[cb3], fps_limit=float("inf"), request_size=(-1, -1) + 1, + callbacks=[cb1, cb2], + force_backend="", + fps_limit=float("inf"), + request_size=(-1, -1), + ), + mock.call( + 2, + callbacks=[cb3], + force_backend="", + fps_limit=float("inf"), + request_size=(-1, -1), ), ] ) diff --git a/tox.ini b/tox.ini index bf25cbd..3f8c29f 100644 --- a/tox.ini +++ b/tox.ini @@ -10,39 +10,39 @@ python = 3.7: py37, mypy, test-docs, black, pydocstyle [testenv] -whitelist_externals = poetry +whitelist_externals = coverage description = run the tests with pytest under {basepython} -commands = poetry run coverage run --source=displayarray -m pytest tests - poetry run coverage report - poetry run coverage erase +commands = coverage run --source=displayarray -m pytest tests + coverage report + coverage erase [testenv:docgen] -whitelist_externals = poetry +whitelist_externals = sphinx-build description = generating documentation -commands = poetry run sphinx-build -b dirhtml docs/docsrc docs +commands = sphinx-build -b dirhtml docs/docsrc docs [testenv:test-docs] -whitelist_externals = poetry +whitelist_externals = sphinx-build cmd description = generating documentation -commands = poetry run sphinx-build -b dirhtml docs/docsrc docs_test -n -T - #rm -rf docs_test - cmd /c RMDIR /Q/S docs_test +commands = sphinx-build -b dirhtml docs/docsrc docs_test -n -T + rm -rf docs_test + #cmd /c RMDIR /Q/S docs_test [testenv:mypy] -whitelist_externals = poetry +whitelist_externals = mypy description = enforce typing -commands = poetry run mypy displayarray +commands = mypy displayarray [testenv:black] -whitelist_externals = poetry +whitelist_externals = black description = enforce code style -commands = poetry run black displayarray --check +commands = black displayarray --check [pydocstyle] ignore = D105, D212, D203, D202 [testenv:pydocstyle] -whitelist_externals = poetry +whitelist_externals = pydocstyle description = enforce documentation style -commands = poetry run pydocstyle displayarray +commands = pydocstyle displayarray