From 03d3ac3a65608223caf54afe29b1031cf9f2460e Mon Sep 17 00:00:00 2001 From: Onuralp SEZER Date: Wed, 13 Sep 2023 23:34:43 +0300 Subject: [PATCH] =?UTF-8?q?feat:=20=E2=9C=A8=20bring=20pre-commit=20from?= =?UTF-8?q?=20supervision?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Onuralp SEZER --- .github/workflows/publish.yml | 4 +- .github/workflows/test.yml | 4 +- .pre-commit-config.yaml | 80 +++++++++++++++ CHANGELOG.md | 2 +- CITATION.cff | 2 +- CONTRIBUTING.md | 2 +- Dockerfile.dev | 2 +- Makefile | 6 +- docs/core/dataset.md | 2 +- docs/core/model.md | 2 +- docs/core/project.md | 2 +- docs/core/version.md | 2 +- docs/core/workspace.md | 2 +- docs/models/classification.md | 2 +- docs/models/instance-segmentation.md | 2 +- docs/models/object-detection.md | 2 +- docs/models/semantic-segmentation.md | 2 +- docs/styles.css | 2 +- mkdocs.yml | 2 +- pyproject.toml | 108 ++++++++++++++++++++- requirements.txt | 2 +- roboflow/__init__.py | 4 +- roboflow/config.py | 6 +- roboflow/core/version.py | 11 +-- roboflow/models/object_detection.py | 4 +- setup.py | 5 +- tests/helpers.py | 4 +- tests/models/test_instance_segmentation.py | 4 +- tests/models/test_object_detection.py | 25 ++--- tests/models/test_semantic_segmentation.py | 3 +- tests/test_queries.py | 4 +- tests/test_version.py | 101 ++++++++++++++----- tests/util/dummy_module/__init__.py | 2 +- tests/util/test_versions.py | 11 +-- 34 files changed, 328 insertions(+), 90 deletions(-) create mode 100644 .pre-commit-config.yaml diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 17e1fc2f..9ca6e19d 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -24,9 +24,9 @@ jobs: python -m pip install --upgrade pip pip install ".[dev]" - name: ๐Ÿš€ Publish to PyPi - env: + env: PYPI_USERNAME: ${{ secrets.PYPI_USERNAME }} PYPI_PASSWORD: ${{ secrets.PYPI_PASSWORD }} PYPI_TEST_PASSWORD: ${{ secrets.PYPI_TEST_PASSWORD }} run: | - make publish -e PYPI_USERNAME=$PYPI_USERNAME -e PYPI_PASSWORD=$PYPI_PASSWORD -e PYPI_TEST_PASSWORD=$PYPI_TEST_PASSWORD \ No newline at end of file + make publish -e PYPI_USERNAME=$PYPI_USERNAME -e PYPI_PASSWORD=$PYPI_PASSWORD -e PYPI_TEST_PASSWORD=$PYPI_TEST_PASSWORD diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index a7d6b64b..024b762a 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -31,8 +31,8 @@ jobs: run: | make check_code_quality - name: ๐Ÿงช Test - env: + env: ROBOFLOW_API_KEY: ${{ secrets.ROBOFLOW_API_KEY }} PROJECT_NAME: ${{ secrets.PROJECT_NAME }} PROJECT_VERSION: ${{ secrets.PROJECT_VERSION }} - run: "python -m unittest" \ No newline at end of file + run: "python -m unittest" diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 00000000..d8442e94 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,80 @@ + +ci: + autofix_prs: true + autoupdate_schedule: weekly + autofix_commit_msg: "fix(pre_commit): ๐ŸŽจ auto format pre-commit hooks" + autoupdate_commit_msg: "chore(pre_commit): โฌ† pre_commit autoupdate" + +repos: + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.4.0 + hooks: + - id: end-of-file-fixer + - id: trailing-whitespace + - id: check-yaml + - id: check-docstring-first + - id: check-executables-have-shebangs + - id: check-toml + - id: check-case-conflict + - id: check-added-large-files + args: ['--maxkb=2048'] + exclude: ^logo/ + - id: detect-private-key + - id: forbid-new-submodules + - id: pretty-format-json + args: ['--autofix', '--no-sort-keys', '--indent=4'] + - id: end-of-file-fixer + - id: mixed-line-ending + + # - repo: https://github.com/asottile/pyupgrade + # rev: v3.9.0 + # hooks: + # - id: pyupgrade + # name: Upgrade code + # args: [--py38-plus] + + - repo: https://github.com/PyCQA/isort + rev: 5.12.0 + hooks: + - id: isort + name: Sort imports + + - repo: https://github.com/PyCQA/flake8 + rev: 6.1.0 + hooks: + - id: flake8 + name: Flake8 Checks + entry: flake8 + additional_dependencies: [Flake8-pyproject] + + + - repo: https://github.com/PyCQA/bandit + rev: '1.7.5' + hooks: + - id: bandit + args: ["-c", "pyproject.toml"] + additional_dependencies: ["bandit[toml]"] + + - repo: https://github.com/pycqa/isort + rev: 5.12.0 + hooks: + - id: isort + name: isort (python) + - id: isort + name: isort (cython) + types: [cython] + - id: isort + name: isort (pyi) + types: [pyi] + + + - repo: https://github.com/psf/black + rev: 23.9.1 + hooks: + - id: black + + - repo: https://github.com/astral-sh/ruff-pre-commit + rev: v0.0.288 + hooks: + - id: ruff + args: [--fix, --exit-non-zero-on-fix] diff --git a/CHANGELOG.md b/CHANGELOG.md index ed975513..48403b2b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,4 +4,4 @@ All notable changes to this project will be documented in this file. ## 1.1.5 -[stub] \ No newline at end of file +[stub] diff --git a/CITATION.cff b/CITATION.cff index a4e91209..97e5c259 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -17,4 +17,4 @@ abstract: >- keywords: - computer vision - image processing -license: MIT \ No newline at end of file +license: MIT diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 5ac84b08..3027fa65 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -37,4 +37,4 @@ make style make check_code_quality ``` -**Note** These tests will be run automatically when you commit thanks to git hooks. \ No newline at end of file +**Note** These tests will be run automatically when you commit thanks to git hooks. diff --git a/Dockerfile.dev b/Dockerfile.dev index 28611d6b..428ea7e8 100644 --- a/Dockerfile.dev +++ b/Dockerfile.dev @@ -4,4 +4,4 @@ RUN apt-get update && apt-get install make && rm -rf /var/lib/apt/lists/* WORKDIR /workspace COPY . . RUN pip install -e ".[dev]" -ENTRYPOINT [ "/bin/bash" ] \ No newline at end of file +ENTRYPOINT [ "/bin/bash" ] diff --git a/Makefile b/Makefile index f3867f93..8b6fdd12 100644 --- a/Makefile +++ b/Makefile @@ -12,10 +12,10 @@ check_code_quality: isort --check-only --profile black $(check_dirs) # stop the build if there are Python syntax errors or undefined names flake8 $(check_dirs) --count --select=E9,F63,F7,F82 --show-source --statistics - # exit-zero treats all errors as warnings. E203 for black, E501 for docstring, W503 for line breaks before logical operators + # exit-zero treats all errors as warnings. E203 for black, E501 for docstring, W503 for line breaks before logical operators flake8 $(check_dirs) --count --max-line-length=88 --exit-zero --ignore=D --extend-ignore=E203,E501,W503 --statistics - + publish: python setup.py sdist bdist_wheel twine check dist/* - twine upload dist/* -u ${PYPI_USERNAME} -p ${PYPI_PASSWORD} --verbose + twine upload dist/* -u ${PYPI_USERNAME} -p ${PYPI_PASSWORD} --verbose diff --git a/docs/core/dataset.md b/docs/core/dataset.md index 76e5a5a4..31447afc 100644 --- a/docs/core/dataset.md +++ b/docs/core/dataset.md @@ -1 +1 @@ -:::roboflow.core.dataset \ No newline at end of file +:::roboflow.core.dataset diff --git a/docs/core/model.md b/docs/core/model.md index 99aa706c..7e3c5f06 100644 --- a/docs/core/model.md +++ b/docs/core/model.md @@ -1 +1 @@ -:::roboflow.core.model \ No newline at end of file +:::roboflow.core.model diff --git a/docs/core/project.md b/docs/core/project.md index bc0568b2..7b2e6d68 100644 --- a/docs/core/project.md +++ b/docs/core/project.md @@ -1 +1 @@ -:::roboflow.core.project \ No newline at end of file +:::roboflow.core.project diff --git a/docs/core/version.md b/docs/core/version.md index cccb7760..cb669ad1 100644 --- a/docs/core/version.md +++ b/docs/core/version.md @@ -1 +1 @@ -:::roboflow.core.version \ No newline at end of file +:::roboflow.core.version diff --git a/docs/core/workspace.md b/docs/core/workspace.md index 2c4bdc46..62706ac5 100644 --- a/docs/core/workspace.md +++ b/docs/core/workspace.md @@ -1 +1 @@ -:::roboflow.core.workspace \ No newline at end of file +:::roboflow.core.workspace diff --git a/docs/models/classification.md b/docs/models/classification.md index e3ba5dcc..f4607654 100644 --- a/docs/models/classification.md +++ b/docs/models/classification.md @@ -1 +1 @@ -:::roboflow.models.classification \ No newline at end of file +:::roboflow.models.classification diff --git a/docs/models/instance-segmentation.md b/docs/models/instance-segmentation.md index 1bb9fd0f..fbc4db82 100644 --- a/docs/models/instance-segmentation.md +++ b/docs/models/instance-segmentation.md @@ -1 +1 @@ -:::roboflow.models.instance_segmentation \ No newline at end of file +:::roboflow.models.instance_segmentation diff --git a/docs/models/object-detection.md b/docs/models/object-detection.md index 35fff501..ce3542ba 100644 --- a/docs/models/object-detection.md +++ b/docs/models/object-detection.md @@ -1 +1 @@ -:::roboflow.models.object_detection \ No newline at end of file +:::roboflow.models.object_detection diff --git a/docs/models/semantic-segmentation.md b/docs/models/semantic-segmentation.md index 4a1b4b1b..15c47cd4 100644 --- a/docs/models/semantic-segmentation.md +++ b/docs/models/semantic-segmentation.md @@ -1 +1 @@ -:::roboflow.models.semantic_segmentation \ No newline at end of file +:::roboflow.models.semantic_segmentation diff --git a/docs/styles.css b/docs/styles.css index f062358a..477cae34 100644 --- a/docs/styles.css +++ b/docs/styles.css @@ -1,3 +1,3 @@ :root { --md-primary-fg-color:#8315F9; -} \ No newline at end of file +} diff --git a/mkdocs.yml b/mkdocs.yml index b3f21c1d..e6b4a5df 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -62,4 +62,4 @@ markdown_extensions: - pymdownx.tabbed: alternate_style: true - toc: - permalink: true \ No newline at end of file + permalink: true diff --git a/pyproject.toml b/pyproject.toml index d59cf725..4d4231d6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -3,4 +3,110 @@ requires = [ "setuptools>=57", "wheel" ] -build-backend = "setuptools.build_meta" \ No newline at end of file +build-backend = "setuptools.build_meta" + + + +[tool.flake8] +exclude = ".venv" +max-complexity = 10 +max-line-length = 88 +extend-ignore = """ + W503, + E203, + E701, + C901, +""" +per-file-ignores = """ + __init__.py: F401 +""" + +[tool.isort] +line_length = 88 +profile = "black" + +[tool.bandit] +target = ["test", "supervision"] +tests = ["B201", "B301"] + +[tool.autoflake] +check = true +imports = ["cv2", "supervision"] + + +[tool.black] +target-version = ["py38"] +line-length = 88 +include = '\.pyi?$' +exclude = ''' +/( + \.git + | \.hg + | \.mypy_cache + | \.tox + | \.venv + | _build + | buck-out + | build + | dist + | docs +)/ +''' + +[tool.ruff] +target-version = "py38" +# Enable pycodestyle (`E`) and Pyflakes (`F`) codes by default. +select = ["E", "F"] +ignore = [] + +# Allow autofix for all enabled rules (when `--fix`) is provided. +fixable = ["A", "B", "C", "D", "E", "F", "G", "I", "N", "Q", "S", "T", "W", "ANN", "ARG", "BLE", "COM", "DJ", "DTZ", "EM", "ERA", "EXE", "FBT", "ICN", "INP", "ISC", "NPY", "PD", "PGH", "PIE", "PL", "PT", "PTH", "PYI", "RET", "RSE", "RUF", "SIM", "SLF", "TCH", "TID", "TRY", "UP", "YTT"] +unfixable = [] + +# Exclude a variety of commonly ignored directories. +exclude = [ + ".bzr", + ".direnv", + ".eggs", + ".git", + ".git-rewrite", + ".hg", + ".mypy_cache", + ".nox", + ".pants.d", + ".pytype", + ".ruff_cache", + ".svn", + ".tox", + ".venv", + "__pypackages__", + "_build", + "buck-out", + "build", + "dist", + "node_modules", + "venv", + "yarn-error.log", + "yarn.lock", + "docs", +] + +# Same as Black. +line-length = 88 + +# Allow unused variables when underscore-prefixed. +dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$" + +[tool.ruff.flake8-quotes] +inline-quotes = "double" +multiline-quotes = "double" +docstring-quotes = "double" + +[tool.ruff.pydocstyle] +convention = "google" + +[tool.ruff.per-file-ignores] +"__init__.py" = ["E402","F401"] + +[tool.ruff.pylint] +max-args = 20 diff --git a/requirements.txt b/requirements.txt index ef2e9243..cc53da13 100644 --- a/requirements.txt +++ b/requirements.txt @@ -16,4 +16,4 @@ supervision urllib3>=1.26.6 tqdm>=4.41.0 PyYAML>=5.3.1 -requests_toolbelt \ No newline at end of file +requests_toolbelt diff --git a/roboflow/__init__.py b/roboflow/__init__.py index 29cb08a5..d9d59d7d 100644 --- a/roboflow/__init__.py +++ b/roboflow/__init__.py @@ -168,7 +168,7 @@ def initialize_roboflow(the_workspace=None): "To use this method, you must first login - run roboflow.login()" ) else: - if the_workspace == None: + if the_workspace is None: active_workspace = Roboflow().workspace() else: active_workspace = Roboflow().workspace(the_workspace) @@ -242,7 +242,7 @@ def __init__( notebook="undefined", ): self.api_key = api_key - if self.api_key == None: + if self.api_key is None: self.api_key = load_roboflow_api_key() self.model_format = model_format diff --git a/roboflow/config.py b/roboflow/config.py index 1b7f6dbe..54aa01bc 100644 --- a/roboflow/config.py +++ b/roboflow/config.py @@ -34,7 +34,7 @@ def get_conditional_configuration_variable(key, default): else: config = {} - if os.getenv(key) != None: + if os.getenv(key) is not None: return os.getenv(key) elif key in config.keys(): return config[key] @@ -86,7 +86,7 @@ def load_roboflow_api_key(): RF_WORKSPACES = get_conditional_configuration_variable("workspaces", default={}) # DEFAULT_WORKSPACE = get_conditional_configuration_variable("default_workspace", default=None) - if RF_WORKSPACE == None: + if RF_WORKSPACE is None: RF_API_KEY = None else: RF_API_KEY = None @@ -95,7 +95,7 @@ def load_roboflow_api_key(): if workspace["url"] == RF_WORKSPACE: RF_API_KEY = workspace["apiKey"] # ENV API_KEY OVERRIDE - if os.getenv("RF_API_KEY") != None: + if os.getenv("RF_API_KEY") is not None: RF_API_KEY = os.getenv("RF_API_KEY") return RF_API_KEY diff --git a/roboflow/core/version.py b/roboflow/core/version.py index 85d09cbe..55ac8455 100644 --- a/roboflow/core/version.py +++ b/roboflow/core/version.py @@ -140,7 +140,7 @@ def __check_if_generating(self): response = requests.get(url, params={"api_key": self.__api_key}) response.raise_for_status() - if response.json()["version"]["progress"] == None: + if response.json()["version"]["progress"] is None: progress = 0.0 else: progress = float(response.json()["version"]["progress"]) @@ -199,7 +199,7 @@ def download(self, model_format=None, location=None, overwrite: bool = True): print_warn_for_wrong_dependencies_versions( [("ultralytics", "==", "8.0.134")] ) - except ImportError as e: + except ImportError: print( "[WARNING] we noticed you are downloading a `yolov8` datasets but you don't have `ultralytics` installed. Roboflow `.deploy` supports only models trained with `ultralytics==8.0.134`, to intall it `pip install ultralytics==8.0.134`." ) @@ -354,7 +354,6 @@ def train(self, speed=None, checkpoint=None, plot_in_notebook=False) -> bool: status = "training" if plot_in_notebook: - import collections from IPython.display import clear_output from matplotlib import pyplot as plt @@ -484,7 +483,7 @@ def deploy(self, model_type: str, model_path: str) -> None: import torch import ultralytics - except ImportError as e: + except ImportError: raise ( "The ultralytics python package is required to deploy yolov8 models. Please install it with `pip install ultralytics`" ) @@ -496,7 +495,7 @@ def deploy(self, model_type: str, model_path: str) -> None: elif "yolov5" in model_type or "yolov7" in model_type: try: import torch - except ImportError as e: + except ImportError: raise ( "The torch python package is required to deploy yolov5 models. Please install it with `pip install torch`" ) @@ -602,7 +601,7 @@ def deploy(self, model_type: str, model_path: str) -> None: try: if res.status_code == 429: raise RuntimeError( - f"This version already has a trained model. Please generate and train a new version in order to upload model to Roboflow." + "This version already has a trained model. Please generate and train a new version in order to upload model to Roboflow." ) else: res.raise_for_status() diff --git a/roboflow/models/object_detection.py b/roboflow/models/object_detection.py index 26c05b23..cfbffbfb 100644 --- a/roboflow/models/object_detection.py +++ b/roboflow/models/object_detection.py @@ -169,7 +169,7 @@ def predict( ) # Check if image exists at specified path or URL or is an array - if hasattr(image_path, "__len__") == True: + if hasattr(image_path, "__len__") is True: pass else: self.__exception_check(image_path_check=image_path) @@ -401,7 +401,7 @@ def plot_one_box( def view(button): while True: if stopButton is not None: - if stopButton.value == True: + if stopButton.value is True: break else: if cv2.waitKey(1) & 0xFF == ord("q"): # quit when 'q' is pressed diff --git a/setup.py b/setup.py index f9902077..a8aece9d 100644 --- a/setup.py +++ b/setup.py @@ -1,6 +1,7 @@ +import re + import setuptools from setuptools import find_packages -import re with open("./roboflow/__init__.py", "r") as f: content = f.read() @@ -11,7 +12,7 @@ long_description = fh.read() with open("requirements.txt", "r") as fh: - install_requires = fh.read().split('\n') + install_requires = fh.read().split("\n") setuptools.setup( name="roboflow", diff --git a/tests/helpers.py b/tests/helpers.py index a084bbd3..888c9842 100644 --- a/tests/helpers.py +++ b/tests/helpers.py @@ -12,7 +12,7 @@ def get_version( **kwargs, ): version_data = { - "id": f"test-workspace/test-project/2", + "id": "test-workspace/test-project/2", "name": "augmented-416x416", "created": 1663104679.539, "images": 240, @@ -47,5 +47,5 @@ def get_version( local=None, workspace=workspace_name, project=project_name, - public=public + public=public, ) diff --git a/tests/models/test_instance_segmentation.py b/tests/models/test_instance_segmentation.py index 752a2059..32ccd24a 100644 --- a/tests/models/test_instance_segmentation.py +++ b/tests/models/test_instance_segmentation.py @@ -1,13 +1,12 @@ import unittest -from requests.exceptions import HTTPError import responses +from requests.exceptions import HTTPError from roboflow.config import INSTANCE_SEGMENTATION_URL from roboflow.models.instance_segmentation import InstanceSegmentationModel from roboflow.util.prediction import PredictionGroup - MOCK_RESPONSE = { "predictions": [ { @@ -42,7 +41,6 @@ class TestInstanceSegmentation(unittest.TestCase): - api_key = "my-api-key" workspace = "roboflow" dataset_id = "test-123" diff --git a/tests/models/test_object_detection.py b/tests/models/test_object_detection.py index e4e922e8..faa0f68f 100644 --- a/tests/models/test_object_detection.py +++ b/tests/models/test_object_detection.py @@ -1,15 +1,14 @@ import unittest -from requests.exceptions import HTTPError +import numpy as np import responses +from PIL import UnidentifiedImageError +from requests.exceptions import HTTPError from roboflow.config import OBJECT_DETECTION_URL from roboflow.models.object_detection import ObjectDetectionModel from roboflow.util.prediction import PredictionGroup -from PIL import UnidentifiedImageError -import numpy as np - MOCK_RESPONSE = { "predictions": [ { @@ -26,7 +25,6 @@ class TestObjectDetection(unittest.TestCase): - api_key = "my-api-key" workspace = "roboflow" dataset_id = "test-123" @@ -90,7 +88,7 @@ def test_predict_with_local_image_request(self): @responses.activate def test_predict_with_a_numpy_array_request(self): - np_array = np.ones((100,100,1), dtype=np.uint8) + np_array = np.ones((100, 100, 1), dtype=np.uint8) instance = ObjectDetectionModel( self.api_key, self.version_id, version=self.version ) @@ -105,7 +103,7 @@ def test_predict_with_a_numpy_array_request(self): self.assertRegex(request.url, rf"^{self.api_url}") self.assertDictEqual(request.params, self._default_params) self.assertIsNotNone(request.body) - + def test_predict_with_local_wrong_image_request(self): image_path = "tests/images/not_an_image.txt" instance = ObjectDetectionModel( @@ -113,7 +111,6 @@ def test_predict_with_local_wrong_image_request(self): ) self.assertRaises(UnidentifiedImageError, instance.predict, image_path) - @responses.activate def test_predict_with_hosted_image_request(self): image_path = "https://example.com/racoon.JPG" @@ -121,7 +118,9 @@ def test_predict_with_hosted_image_request(self): **self._default_params, "image": image_path, } - instance = ObjectDetectionModel(self.api_key, self.version_id, version=self.version) + instance = ObjectDetectionModel( + self.api_key, self.version_id, version=self.version + ) # Mock the library validating that the URL is valid before sending to the API responses.add(responses.POST, self.api_url, json=MOCK_RESPONSE) @@ -140,7 +139,9 @@ def test_predict_with_confidence_request(self): confidence = "100" image_path = "tests/images/rabbit.JPG" expected_params = {**self._default_params, "confidence": confidence} - instance = ObjectDetectionModel(self.api_key, self.version_id, version=self.version) + instance = ObjectDetectionModel( + self.api_key, self.version_id, version=self.version + ) responses.add(responses.POST, self.api_url, json=MOCK_RESPONSE) @@ -158,7 +159,9 @@ def test_predict_with_non_200_response_raises_http_error(self): image_path = "tests/images/rabbit.JPG" responses.add(responses.POST, self.api_url, status=403) - instance = ObjectDetectionModel(self.api_key, self.version_id, version=self.version) + instance = ObjectDetectionModel( + self.api_key, self.version_id, version=self.version + ) with self.assertRaises(HTTPError): instance.predict(image_path) diff --git a/tests/models/test_semantic_segmentation.py b/tests/models/test_semantic_segmentation.py index 08e58672..927e8f21 100644 --- a/tests/models/test_semantic_segmentation.py +++ b/tests/models/test_semantic_segmentation.py @@ -1,13 +1,12 @@ import unittest -from requests.exceptions import HTTPError import responses +from requests.exceptions import HTTPError from roboflow.config import SEMANTIC_SEGMENTATION_URL from roboflow.models.semantic_segmentation import SemanticSegmentationModel from roboflow.util.prediction import PredictionGroup - MOCK_RESPONSE = { "segmentation_mask": "iVBORw0KGgoAAAANSUhEUgAAAgAAAAIACAAAAADRE4smAAACjElEQVR4nO3bzXKbMBiGUanT+79ldVHXwSmmFmJGfcU5i8SZbDR8DzL4pxQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgKXUOnsFTGX+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMuosxewklpKm72GXj9mLyBf/etBEgGMqqVGTv5BADcngEF151GSn7MXkO116HFXgMUOMCZ//gK4TuT8BTCkvfyKJICbE8CQ9vyRSgBDMm/9tgQwLHoDWCDhaWopj+nXkpuBHeBT9dtL/t9OndQzSQCf2j/Fa8mdfSlFAD3a3l+H20IAAXzszbN83fw3b/4COO9PEIFT3xDAeW2zJ6TeBHg7eEjLvgUsxQ4wrGXPXwDDoscvgHE1+ypQAGfU/U8CJpaQuObpvt4FeBy/9vIoigD6fR2z9nwZaPtyUBQB9Ds6ZnEFuAa4OQF0O9w043ZUAdxcXLGT/eN4xV0C2AH6LDd/AVwpcP4CuFDi/AVwocjrKQF0iTzJDwmgz3IFCKDTagUI4OYEcJ3IzUEAnSIv9Q/4VHCXd+NvsWGkrnum9xUE8hTQL3LQ7wjghJUKEMBlMrMQwBm7s868nMpc9X/iefB+fzc8cgtwGzjg8XWAyMFzOZspAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwil+AQDJrnsYcnwAAAABJRU5ErkJggg==", "class_map": {"0": "background", "1": "object"}, diff --git a/tests/test_queries.py b/tests/test_queries.py index b5cfb401..f93f1c00 100644 --- a/tests/test_queries.py +++ b/tests/test_queries.py @@ -1,5 +1,3 @@ -import os -import unittest from _datetime import datetime @@ -8,7 +6,7 @@ from roboflow.models.classification import ClassificationModel from roboflow.models.object_detection import ObjectDetectionModel -from . import RoboflowTest, ordered, PROJECT_NAME +from . import PROJECT_NAME, RoboflowTest, ordered class TestQueries(RoboflowTest): diff --git a/tests/test_version.py b/tests/test_version.py index 42087296..270ff8ff 100644 --- a/tests/test_version.py +++ b/tests/test_version.py @@ -1,13 +1,14 @@ import os +import unittest +from unittest.mock import patch import requests import responses -import unittest -from unittest.mock import patch -from .helpers import get_version from roboflow.core.version import Version +from .helpers import get_version + class TestDownload(unittest.TestCase): def setUp(self): @@ -19,12 +20,18 @@ def setUp(self): version_number="4", ) - self.generating_url = "https://api.roboflow.com/Test Workspace Name/Test Dataset/4" - + self.generating_url = ( + "https://api.roboflow.com/Test Workspace Name/Test Dataset/4" + ) + @responses.activate def test_download_raises_exception_on_bad_request(self): responses.add(responses.GET, self.api_url, status=404, json={"error": "Broken"}) - responses.add(responses.GET, self.generating_url, json={"version": {"generating": False, "progress": 1.0}}) + responses.add( + responses.GET, + self.generating_url, + json={"version": {"generating": False, "progress": 1.0}}, + ) with self.assertRaises(RuntimeError): self.version.download("coco") @@ -32,7 +39,11 @@ def test_download_raises_exception_on_bad_request(self): @responses.activate def test_download_raises_exception_on_api_failure(self): responses.add(responses.GET, self.api_url, status=500) - responses.add(responses.GET, self.generating_url, json={"version": {"generating": False, "progress": 1.0}}) + responses.add( + responses.GET, + self.generating_url, + json={"version": {"generating": False, "progress": 1.0}}, + ) with self.assertRaises(requests.exceptions.HTTPError): self.version.download("coco") @@ -41,8 +52,12 @@ def test_download_raises_exception_on_api_failure(self): @patch.object(Version, "_Version__extract_zip") @patch.object(Version, "_Version__reformat_yaml") def test_download_returns_dataset(self, *_): - responses.add(responses.GET, self.api_url, json={"export": { "link": None }}) - responses.add(responses.GET, self.generating_url, json={"version": {"generating": False, "progress": 1.0}}) + responses.add(responses.GET, self.api_url, json={"export": {"link": None}}) + responses.add( + responses.GET, + self.generating_url, + json={"version": {"generating": False, "progress": 1.0}}, + ) dataset = self.version.download("coco", location="/my-spot") self.assertEqual(dataset.name, self.version.name) self.assertEqual(dataset.version, self.version.version) @@ -53,33 +68,57 @@ def test_download_returns_dataset(self, *_): class TestExport(unittest.TestCase): def setUp(self): super(TestExport, self).setUp() - self.api_url = "https://api.roboflow.com/test-workspace/test-project/4/test-format" - self.version = get_version(project_name="Test Dataset", id="test-workspace/test-project/2", version_number="4") + self.api_url = ( + "https://api.roboflow.com/test-workspace/test-project/4/test-format" + ) + self.version = get_version( + project_name="Test Dataset", + id="test-workspace/test-project/2", + version_number="4", + ) - self.generating_url = "https://api.roboflow.com/Test Workspace Name/Test Dataset/4" + self.generating_url = ( + "https://api.roboflow.com/Test Workspace Name/Test Dataset/4" + ) @responses.activate def test_export_returns_true_on_api_success(self): responses.add(responses.GET, self.api_url, status=200) - responses.add(responses.GET, self.generating_url, json={"version": {"generating": False, "progress": 1.0}}) + responses.add( + responses.GET, + self.generating_url, + json={"version": {"generating": False, "progress": 1.0}}, + ) export = self.version.export("test-format") request = responses.calls[0].request self.assertTrue(export) self.assertEqual(request.method, "GET") - self.assertDictEqual(request.params, {'nocache': 'true', "api_key": "test-api-key" }) + self.assertDictEqual( + request.params, {"nocache": "true", "api_key": "test-api-key"} + ) @responses.activate def test_export_raises_error_on_bad_request(self): - responses.add(responses.GET, self.api_url, status=400, json={ "error": "BROKEN!!"}) - responses.add(responses.GET, self.generating_url, json={"version": {"generating": False, "progress": 1.0}}) + responses.add( + responses.GET, self.api_url, status=400, json={"error": "BROKEN!!"} + ) + responses.add( + responses.GET, + self.generating_url, + json={"version": {"generating": False, "progress": 1.0}}, + ) with self.assertRaises(RuntimeError): self.version.export("test-format") @responses.activate def test_export_raises_error_on_api_failure(self): responses.add(responses.GET, self.api_url, status=500) - responses.add(responses.GET, self.generating_url, json={"version": {"generating": False, "progress": 1.0}}) + responses.add( + responses.GET, + self.generating_url, + json={"version": {"generating": False, "progress": 1.0}}, + ) with self.assertRaises(requests.exceptions.HTTPError): self.version.export("test-format") @@ -96,17 +135,27 @@ def setUp(self, *_): # This is a weird python thing to get access to the private function for testing. self.get_download_location = self.version._Version__get_download_location - self.generating_url = "https://api.roboflow.com/Test Workspace Name/Test Dataset/4" + self.generating_url = ( + "https://api.roboflow.com/Test Workspace Name/Test Dataset/4" + ) @responses.activate def test_get_download_location_with_env_variable(self, *_): - responses.add(responses.GET, self.generating_url, json={"version": {"generating": False, "progress": 1.0}}) - with patch.dict(os.environ, { "DATASET_DIRECTORY": "/my/exports"}, clear=True): + responses.add( + responses.GET, + self.generating_url, + json={"version": {"generating": False, "progress": 1.0}}, + ) + with patch.dict(os.environ, {"DATASET_DIRECTORY": "/my/exports"}, clear=True): self.assertEqual(self.get_download_location(), "/my/exports/Test-Dataset-3") @responses.activate def test_get_download_location_without_env_variable(self, *_): - responses.add(responses.GET, self.generating_url, json={"version": {"generating": False, "progress": 1.0}}) + responses.add( + responses.GET, + self.generating_url, + json={"version": {"generating": False, "progress": 1.0}}, + ) self.assertEqual(self.get_download_location(), "Test-Dataset-3") @@ -121,11 +170,17 @@ def setUp(self): # This is a weird python thing to get access to the private function for testing. self.get_download_url = self.version._Version__get_download_url - self.generating_url = "https://api.roboflow.com/Test Workspace Name/Test Dataset/4" + self.generating_url = ( + "https://api.roboflow.com/Test Workspace Name/Test Dataset/4" + ) @responses.activate def test_get_download_url(self): - responses.add(responses.GET, self.generating_url, json={"version": {"generating": False, "progress": 1.0}}) + responses.add( + responses.GET, + self.generating_url, + json={"version": {"generating": False, "progress": 1.0}}, + ) url = self.get_download_url("yolo1337") self.assertEqual( url, "https://api.roboflow.com/test-workspace/test-project/3/yolo1337" diff --git a/tests/util/dummy_module/__init__.py b/tests/util/dummy_module/__init__.py index f2b3589f..493f7415 100644 --- a/tests/util/dummy_module/__init__.py +++ b/tests/util/dummy_module/__init__.py @@ -1 +1 @@ -__version__ = "0.3.0" \ No newline at end of file +__version__ = "0.3.0" diff --git a/tests/util/test_versions.py b/tests/util/test_versions.py index 2ca98c5d..89250d75 100644 --- a/tests/util/test_versions.py +++ b/tests/util/test_versions.py @@ -1,9 +1,10 @@ +import unittest from importlib import import_module + from roboflow.util.versions import get_wrong_dependencies_versions -import unittest -class TestVersions(unittest.TestCase): +class TestVersions(unittest.TestCase): def test_wrong_dependencies_versions(self): module_path = "tests.util.dummy_module" module_version = import_module(module_path).__version__ @@ -13,14 +14,12 @@ def test_wrong_dependencies_versions(self): ("tests.util.dummy_module", "<=", "1.0.0"), ("tests.util.dummy_module", ">=", "0.1.0"), ("tests.util.dummy_module", ">=", "0.6.0"), - ("tests.util.dummy_module", ">=", "0.1.34") - - + ("tests.util.dummy_module", ">=", "0.1.34"), ] # true if dep is correc expected_results = [True, False, True, True, False, True] - for (test, expected_result) in zip(tests, expected_results): + for test, expected_result in zip(tests, expected_results): wrong_dependencies_versions = get_wrong_dependencies_versions([test]) is_correct_dep = len(wrong_dependencies_versions) == 0 self.assertEqual(is_correct_dep, expected_result)