Skip to content

Commit 09eb72d

Browse files
committed
chore: add pyright
1 parent 9c361e3 commit 09eb72d

19 files changed

+92
-92
lines changed

.dockerignore

+19
Original file line numberDiff line numberDiff line change
@@ -1 +1,20 @@
1+
# Python cache files
2+
__pycache__
3+
*.pyc
4+
5+
# IDE settings
6+
.vscode/
7+
8+
# Version control
9+
.git/
10+
11+
# Distribution / packaging
12+
build/
13+
dist/
14+
*.egg-info/
15+
16+
# Virtual environments
17+
.venv
18+
19+
# Testing
120
/tests/manual/data

.github/workflows/test.yml

+2-4
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,8 @@ jobs:
2727
run: |
2828
python -m pip install --upgrade pip
2929
pip install ".[dev]"
30-
- name: 🧹 Lint
30+
- name: 🧹 Check code quality
3131
run: |
3232
make check_code_quality
33-
- name: Check types with mypy
34-
run: mypy .
35-
- name: 🧪 Test
33+
- name: 🧪 Run tests
3634
run: "python -m unittest"

Makefile

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
.PHONY: style check_code_quality
1+
.PHONY: style check_code_quality publish
22

33
export PYTHONPATH = .
44
check_dirs := roboflow
@@ -10,6 +10,7 @@ style:
1010
check_code_quality:
1111
ruff format $(check_dirs) --check
1212
ruff check $(check_dirs)
13+
pyright $(check_dirs)
1314

1415
publish:
1516
python setup.py sdist bdist_wheel

pyproject.toml

+9-23
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,7 @@ target-version = "py38"
1111
line-length = 120
1212

1313
[tool.ruff.lint]
14-
select = [
15-
"ALL",
16-
]
14+
select = ["ALL"]
1715
ignore = [
1816
"A",
1917
"ANN",
@@ -94,23 +92,11 @@ convention = "google"
9492
# Preserve types, even if a file imports `from __future__ import annotations`.
9593
keep-runtime-typing = true
9694

97-
[tool.mypy]
98-
python_version = "3.8"
99-
exclude = ["^build/"]
100-
101-
[[tool.mypy.overrides]]
102-
module = [
103-
"_datetime.*",
104-
"filetype.*",
105-
# IPython is an optional dependency
106-
"IPython.display.*",
107-
# ipywidgets is an optional dependency
108-
"ipywidgets.*",
109-
# matplotlib typing is not available for Python 3.8
110-
# remove this when we stop supporting Python 3.8
111-
"matplotlib.*",
112-
"requests_toolbelt.*",
113-
"torch.*",
114-
"ultralytics.*",
115-
]
116-
ignore_missing_imports = true
95+
[tool.pyright]
96+
pythonVersion = "3.8"
97+
exclude = ["build", ".venv", "venv*", "docs", "Tests"]
98+
venvPath = "."
99+
venv = ".venv"
100+
reportMissingImports = false
101+
reportUnboundVariable = false
102+
reportIncompatibleMethodOverride = false

roboflow/__init__.py

+7-14
Original file line numberDiff line numberDiff line change
@@ -59,20 +59,13 @@ def check_key(api_key, model, notebook, num_retries=0):
5959
return "onboarding"
6060

6161

62-
def auth(api_key):
63-
r = check_key(api_key)
64-
w = r["workspace"]
65-
66-
return Roboflow(api_key, w)
67-
68-
6962
def login(workspace=None, force=False):
7063
os_name = os.name
7164

7265
if os_name == "nt":
73-
default_path = os.path.join(os.getenv("USERPROFILE"), "roboflow/config.json")
66+
default_path = os.path.join(os.getenv("USERPROFILE", ""), "roboflow/config.json")
7467
else:
75-
default_path = os.path.join(os.getenv("HOME"), ".config/roboflow/config.json")
68+
default_path = os.path.join(os.getenv("HOME", ""), ".config/roboflow/config.json")
7669

7770
# default configuration location
7871
conf_location = os.getenv(
@@ -143,7 +136,7 @@ def initialize_roboflow(the_workspace=None):
143136

144137
conf_location = os.getenv(
145138
"ROBOFLOW_CONFIG_DIR",
146-
default=os.getenv("HOME") + "/.config/roboflow/config.json",
139+
default=os.getenv("HOME", "") + "/.config/roboflow/config.json",
147140
)
148141

149142
if not os.path.isfile(conf_location):
@@ -176,7 +169,7 @@ def load_model(model_url):
176169
project = path_parts[2]
177170
version = int(path_parts[-1])
178171
else:
179-
raise ("Model URL must be from either app.roboflow.com or universe.roboflow.com")
172+
raise ValueError("Model URL must be from either app.roboflow.com or universe.roboflow.com")
180173

181174
project = operate_workspace.project(project)
182175
version = project.version(version)
@@ -204,7 +197,7 @@ def download_dataset(dataset_url, model_format, location=None):
204197
version = int(path_parts[-1])
205198
the_workspace = path_parts[1]
206199
else:
207-
raise ("Model URL must be from either app.roboflow.com or universe.roboflow.com")
200+
raise ValueError("Model URL must be from either app.roboflow.com or universe.roboflow.com")
208201
operate_workspace = initialize_roboflow(the_workspace=the_workspace)
209202

210203
project = operate_workspace.project(project)
@@ -239,7 +232,7 @@ def auth(self):
239232
self.universe = True
240233
return self
241234
else:
242-
w = r["workspace"]
235+
w = r["workspace"] # type: ignore[arg-type]
243236
self.current_workspace = w
244237
return self
245238

@@ -282,7 +275,7 @@ def project(self, project_name, the_workspace=None):
282275

283276
dataset_info = dataset_info.json()["project"]
284277

285-
return Project(self.api_key, dataset_info)
278+
return Project(self.api_key or "", dataset_info)
286279

287280
def __str__(self):
288281
"""to string function"""

roboflow/adapters/rfapi.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import json
22
import os
3-
import urllib
43
from typing import Optional
4+
from urllib import parse
55

66
import requests
77
from requests_toolbelt.multipart.encoder import MultipartEncoder
@@ -164,7 +164,7 @@ def _upload_url(api_key, project_url, **kwargs):
164164
url = f"{API_URL}/dataset/{project_url}/upload?api_key={api_key}"
165165

166166
if kwargs:
167-
querystring = urllib.parse.urlencode(kwargs, doseq=True)
167+
querystring = parse.urlencode(kwargs, doseq=True)
168168
url += f"&{querystring}"
169169

170170
return url

roboflow/config.py

+8-6
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
import json
22
import os
3+
from typing import Any
34

45

5-
def get_conditional_configuration_variable(key, default):
6+
def get_conditional_configuration_variable(key, default) -> Any:
67
"""Retrieves the configuration variable conditionally.
78
##1. check if variable is in environment
89
##2. check if variable is in config file
@@ -17,9 +18,9 @@ def get_conditional_configuration_variable(key, default):
1718
os_name = os.name
1819

1920
if os_name == "nt":
20-
default_path = os.path.join(os.getenv("USERPROFILE"), "roboflow/config.json")
21+
default_path = os.path.join(os.getenv("USERPROFILE", ""), "roboflow/config.json")
2122
else:
22-
default_path = os.path.join(os.getenv("HOME"), ".config/roboflow/config.json")
23+
default_path = os.path.join(os.getenv("HOME", ""), ".config/roboflow/config.json")
2324

2425
# default configuration location
2526
conf_location = os.getenv(
@@ -34,9 +35,10 @@ def get_conditional_configuration_variable(key, default):
3435
else:
3536
config = {}
3637

37-
if os.getenv(key) is not None:
38-
return os.getenv(key)
39-
elif key in config.keys():
38+
env_value = os.getenv(key)
39+
if env_value is not None:
40+
return env_value
41+
elif key in config:
4042
return config[key]
4143
else:
4244
return default

roboflow/core/project.py

+10-10
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,7 @@ def generate_version(self, settings):
230230
try:
231231
r_json = r.json()
232232
except Exception:
233-
raise "Error when requesting to generate a new version for project."
233+
raise RuntimeError("Error when requesting to generate a new version for project.")
234234

235235
# if the generation succeeds, return the version that is being generated
236236
if r.status_code == 200:
@@ -256,7 +256,7 @@ def train(
256256
speed=None,
257257
checkpoint=None,
258258
plot_in_notebook=False,
259-
) -> bool:
259+
):
260260
"""
261261
Ask the Roboflow API to train a previously exported version's dataset.
262262
@@ -503,7 +503,7 @@ def single_upload(
503503
sequence_size=sequence_size,
504504
**kwargs,
505505
)
506-
image_id = uploaded_image["id"]
506+
image_id = uploaded_image["id"] # type: ignore[index]
507507
upload_retry_attempts = retry.retries
508508
except BaseException as e:
509509
uploaded_image = {"error": e}
@@ -518,10 +518,10 @@ def single_upload(
518518
uploaded_annotation = rfapi.save_annotation(
519519
self.__api_key,
520520
project_url,
521-
annotation_name,
522-
annotation_str,
521+
annotation_name, # type: ignore[type-var]
522+
annotation_str, # type: ignore[type-var]
523523
image_id,
524-
job_name=batch_name,
524+
job_name=batch_name, # type: ignore[type-var]
525525
is_prediction=is_prediction,
526526
annotation_labelmap=annotation_labelmap,
527527
overwrite=annotation_overwrite,
@@ -543,10 +543,10 @@ def _annotation_params(self, annotation_path):
543543
if isinstance(annotation_path, dict) and annotation_path.get("rawText"):
544544
annotation_name = annotation_path["name"]
545545
annotation_string = annotation_path["rawText"]
546-
elif os.path.exists(annotation_path):
547-
with open(annotation_path):
548-
annotation_string = open(annotation_path).read()
549-
annotation_name = os.path.basename(annotation_path)
546+
elif os.path.exists(annotation_path): # type: ignore[arg-type]
547+
with open(annotation_path): # type: ignore[arg-type]
548+
annotation_string = open(annotation_path).read() # type: ignore[arg-type]
549+
annotation_name = os.path.basename(annotation_path) # type: ignore[arg-type]
550550
elif self.type == "classification":
551551
print(f"-> using {annotation_path} as classname for classification project")
552552
annotation_string = annotation_path

roboflow/core/version.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -766,7 +766,7 @@ def bar_progress(current, total, width=80):
766766

767767
# write the zip file to the desired location
768768
with open(location + "/roboflow.zip", "wb") as f:
769-
total_length = int(response.headers.get("content-length"))
769+
total_length = int(response.headers.get("content-length")) # type: ignore[arg-type]
770770
desc = None if TQDM_DISABLE else f"Downloading Dataset Version Zip in {location} to {format}:"
771771
for chunk in tqdm(
772772
response.iter_content(chunk_size=1024),

roboflow/core/workspace.py

+6-6
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import json
44
import os
55
import sys
6-
from typing import List
6+
from typing import Any, List
77

88
import numpy as np
99
import requests
@@ -179,7 +179,7 @@ def two_stage(
179179
print(self.project(first_stage_model_name))
180180

181181
# perform first inference
182-
predictions = stage_one_model.predict(image)
182+
predictions = stage_one_model.predict(image) # type: ignore[attribute-error]
183183

184184
if stage_one_project.type == "object-detection" and stage_two_project == "classification":
185185
# interact with each detected object from stage one inference results
@@ -199,7 +199,7 @@ def two_stage(
199199
croppedImg.save("./temp.png")
200200

201201
# capture results of second stage inference from cropped image
202-
results.append(stage_two_model.predict("./temp.png")[0])
202+
results.append(stage_two_model.predict("./temp.png")[0]) # type: ignore[attribute-error]
203203

204204
# delete the written image artifact
205205
try:
@@ -244,7 +244,7 @@ def two_stage_ocr(
244244
stage_one_model = stage_one_project.version(first_stage_model_version).model
245245

246246
# perform first inference
247-
predictions = stage_one_model.predict(image)
247+
predictions = stage_one_model.predict(image) # type: ignore[attribute-error]
248248

249249
# interact with each detected object from stage one inference results
250250
if stage_one_project.type == "object-detection":
@@ -391,7 +391,7 @@ def active_learning(
391391
upload_destination: str = "",
392392
conditionals: dict = {},
393393
use_localhost: bool = False,
394-
) -> str:
394+
) -> Any:
395395
"""perform inference on each image in directory and upload based on conditions
396396
@params:
397397
raw_data_location: (str) = folder of frames to be processed
@@ -470,7 +470,7 @@ def active_learning(
470470
print(image2 + " --> similarity too high to --> " + image1)
471471
continue # skip this image if too similar or counter hits limit
472472

473-
predictions = inference_model.predict(image).json()["predictions"]
473+
predictions = inference_model.predict(image).json()["predictions"] # type: ignore[attribute-error]
474474
# collect all predictions to return to user at end
475475
prediction_results.append({"image": image, "predictions": predictions})
476476

roboflow/models/classification.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
import io
33
import json
44
import os
5-
import urllib
65
from typing import Optional
6+
from urllib import parse
77

88
import requests
99
from PIL import Image
@@ -106,7 +106,7 @@ def predict(self, image_path, hosted=False):
106106
)
107107
else:
108108
# Create API URL for hosted image (slightly different)
109-
self.api_url += "&image=" + urllib.parse.quote_plus(image_path)
109+
self.api_url += "&image=" + parse.quote_plus(image_path)
110110
# POST to the API
111111
resp = requests.post(self.api_url)
112112
img_dims = {"width": "0", "height": "0"}

roboflow/models/inference.py

+4-5
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
import json
33
import os
44
import time
5-
import urllib
65
from typing import Optional, Tuple
6+
from urllib import parse
77
from urllib.parse import urljoin
88

99
import requests
@@ -72,7 +72,7 @@ def __get_image_params(self, image_path):
7272
"""
7373
validate_image_path(image_path)
7474

75-
hosted_image = urllib.parse.urlparse(image_path).scheme in ("http", "https")
75+
hosted_image = parse.urlparse(image_path).scheme in ("http", "https")
7676

7777
if hosted_image:
7878
image_dims = {"width": "Undefined", "height": "Undefined"}
@@ -121,8 +121,7 @@ def predict(self, image_path, prediction_type=None, **kwargs):
121121
params["api_key"] = self.__api_key
122122

123123
params.update(**kwargs)
124-
125-
url = f"{self.api_url}?{urllib.parse.urlencode(params)}"
124+
url = f"{self.api_url}?{parse.urlencode(params)}" # type: ignore[attr-defined]
126125
response = requests.post(url, **request_kwargs)
127126
response.raise_for_status()
128127

@@ -390,7 +389,7 @@ def download(self, format="pt", location="."):
390389

391390
# write the zip file to the desired location
392391
with open(location + "/weights.pt", "wb") as f:
393-
total_length = int(response.headers.get("content-length"))
392+
total_length = int(response.headers.get("content-length")) # type: ignore[arg-type]
394393
for chunk in tqdm(
395394
response.iter_content(chunk_size=1024),
396395
desc=f"Downloading weights to {location}/weights.pt",

0 commit comments

Comments
 (0)