Skip to content

Commit f6d348c

Browse files
ad-mclaude
andauthored
Add type hints and modernize code style with ruff/mypy (#130)
* Add ruff, mypy, and prek-based CI linting - Add .pre-commit-config.yaml with ruff (lint + format) and mypy hooks - Add ruff and mypy tool configuration to pyproject.toml - Add prek-action lint job to GitHub Actions workflow - Replace Docker-based flake8/black lint targets with ruff in Makefile - Add lint/typecheck environments to tox.ini - Fix type annotations: properly type Job class attributes, BaseTask.type, on_check callback parameter, and __exit__ return type - Fix ruff issues: remove unused Union import, sort imports, remove unicode literals, use f-strings, add stacklevel to warnings.warn - Exclude examples/ from ruff (documentation scripts with intentional patterns) https://claude.ai/code/session_01NzfYD4hhH5nqhu8mgnMXPt * Scope mypy pre-commit hook to python_anticaptcha package only The hook was checking all files (tests, examples, docs) which have untyped functions. Restrict to the package directory only. https://claude.ai/code/session_01NzfYD4hhH5nqhu8mgnMXPt * Fix mypy error from reused response variable in createTaskSmee Rename second assignment to create_response to avoid type conflict with the Response object from the initial HEAD request. https://claude.ai/code/session_01NzfYD4hhH5nqhu8mgnMXPt --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent 20252da commit f6d348c

27 files changed

Lines changed: 284 additions & 211 deletions

.github/workflows/pythonpackage.yml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,18 @@ name: Python package
33
on: [push]
44

55
jobs:
6+
lint:
7+
runs-on: ubuntu-latest
8+
steps:
9+
- uses: actions/checkout@v4
10+
11+
- name: Set up Python
12+
uses: actions/setup-python@v5
13+
with:
14+
python-version: '3.12'
15+
16+
- uses: j178/prek-action@v1
17+
618
test:
719
runs-on: ubuntu-latest
820

.pre-commit-config.yaml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
repos:
2+
- repo: https://github.com/astral-sh/ruff-pre-commit
3+
rev: v0.9.10
4+
hooks:
5+
- id: ruff
6+
args: [--fix]
7+
- id: ruff-format
8+
9+
- repo: https://github.com/pre-commit/mirrors-mypy
10+
rev: v1.15.0
11+
hooks:
12+
- id: mypy
13+
additional_dependencies: [types-requests>=2.31]
14+
files: ^python_anticaptcha/
15+
pass_filenames: false
16+
args: [python_anticaptcha]

Makefile

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
CHROMEDRIVER_VERSION=99.0.4844.17
22
CHROMEDRIVER_DIR=${PWD}/chromedriver
33

4-
.PHONY: lint fmt build docs install test test_e2e chromedriver
4+
.PHONY: lint fmt typecheck build docs install test test_e2e chromedriver
55

66
build:
77
python -m build
@@ -34,11 +34,15 @@ clean:
3434
rm -r build chromedriver
3535

3636
lint:
37-
docker run --rm -v /$$(pwd):/apps alpine/flake8 ./
38-
docker run --rm -v /$$(pwd):/data cytopia/black --check ./
37+
ruff check .
38+
ruff format --check .
3939

4040
fmt:
41-
docker run --rm -v /$$(pwd):/data cytopia/black ./
41+
ruff check --fix .
42+
ruff format .
43+
44+
typecheck:
45+
mypy python_anticaptcha
4246

4347
docs:
4448
sphinx-build -W docs /dev/shm/sphinx

docs/conf.py

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
# -*- coding: utf-8 -*-
21
#
32
# Configuration file for the Sphinx documentation builder.
43
#
@@ -20,13 +19,13 @@
2019

2120
# -- Project information -----------------------------------------------------
2221

23-
project = u"python-anticaptcha"
24-
copyright = u"2018-2026, Adam Dobrawy"
25-
author = u"Adam Dobrawy"
22+
project = "python-anticaptcha"
23+
copyright = "2018-2026, Adam Dobrawy"
24+
author = "Adam Dobrawy"
2625

2726
# Version is managed by setuptools-scm; leave empty for Sphinx
28-
version = u""
29-
release = u""
27+
version = ""
28+
release = ""
3029

3130

3231
# -- General configuration ---------------------------------------------------
@@ -69,7 +68,7 @@
6968
# List of patterns, relative to source directory, that match files and
7069
# directories to ignore when looking for source files.
7170
# This pattern also affects html_static_path and html_extra_path .
72-
exclude_patterns = [u"_build", "Thumbs.db", ".DS_Store"]
71+
exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"]
7372

7473
# The name of the Pygments (syntax highlighting) style to use.
7574
pygments_style = "sphinx"
@@ -143,8 +142,8 @@
143142
(
144143
master_doc,
145144
"python-anticaptcha.tex",
146-
u"python-anticaptcha Documentation",
147-
u"Adam Dobrawy",
145+
"python-anticaptcha Documentation",
146+
"Adam Dobrawy",
148147
"manual",
149148
),
150149
]
@@ -154,9 +153,7 @@
154153

155154
# One entry per manual page. List of tuples
156155
# (source start file, name, description, authors, manual section).
157-
man_pages = [
158-
(master_doc, "python-anticaptcha", u"python-anticaptcha Documentation", [author], 1)
159-
]
156+
man_pages = [(master_doc, "python-anticaptcha", "python-anticaptcha Documentation", [author], 1)]
160157

161158

162159
# -- Options for Texinfo output ----------------------------------------------
@@ -168,7 +165,7 @@
168165
(
169166
master_doc,
170167
"python-anticaptcha",
171-
u"python-anticaptcha Documentation",
168+
"python-anticaptcha Documentation",
172169
author,
173170
"python-anticaptcha",
174171
"One line description of project.",

examples/antigate.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
1+
import json
12
from os import environ
2-
from re import TEMPLATE
33

44
from python_anticaptcha import AnticaptchaClient
5-
from python_anticaptcha.tasks import AntiGateTask, AntiGateTaskProxyless
6-
import json
5+
from python_anticaptcha.tasks import AntiGateTaskProxyless
76

87
api_key = environ["KEY"]
98

examples/app_stat.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
from os import environ
22
from pprint import pprint
3-
from python_anticaptcha import AnticaptchaClient, ImageToTextTask
43
from sys import argv
54

5+
from python_anticaptcha import AnticaptchaClient
6+
67
api_key = environ["KEY"]
78

89
soft_id = argv[1]

examples/balance.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from os import environ
22
from pprint import pprint
3-
from python_anticaptcha import AnticaptchaClient, ImageToTextTask
4-
from sys import argv
3+
4+
from python_anticaptcha import AnticaptchaClient
55

66
api_key = environ["KEY"]
77

examples/funcaptcha_request.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1-
from six.moves.urllib import parse
2-
import requests
3-
from os import environ
41
import re
2+
from os import environ
3+
4+
import requests
5+
from six.moves.urllib import parse
56

67
from python_anticaptcha import AnticaptchaClient, FunCaptchaTask
78

@@ -50,7 +51,7 @@ def get_token(form_html):
5051

5152
def form_submit(token):
5253
return requests.post(
53-
url="{}/verify".format(url),
54+
url=f"{url}/verify",
5455
data={"name": "xx", "fc-token": token},
5556
proxies={
5657
"http": proxy_url,

examples/funcaptcha_selenium.py

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,10 @@
1-
from six.moves.urllib.parse import quote
2-
from six.moves.urllib import parse
3-
4-
import requests
5-
from os import environ
61
import re
2+
from os import environ
73
from random import choice
4+
85
from selenium.webdriver.common.by import By
9-
from selenium.webdriver.support.ui import WebDriverWait
10-
from selenium.webdriver.support import expected_conditions as EC
6+
from six.moves.urllib import parse
7+
from six.moves.urllib.parse import quote
118

129
from python_anticaptcha import AnticaptchaClient, FunCaptchaTask
1310

examples/funcaptcha_selenium_callback.py

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
1+
import gzip
2+
import os
13
import re
24
import time
3-
from six.moves.urllib.parse import quote
4-
import os
55
from os import environ
6-
import gzip
76

8-
from python_anticaptcha import AnticaptchaClient, FunCaptchaProxylessTask
97
from selenium.webdriver.common.by import By
8+
from six.moves.urllib.parse import quote
9+
10+
from python_anticaptcha import AnticaptchaClient, FunCaptchaProxylessTask
1011

1112
api_key = environ["KEY"]
1213
site_key_pattern = 'public_key: "(.+?)",'
@@ -47,7 +48,7 @@ def form_submit(driver, token):
4748
)
4849
time.sleep(1)
4950
# as example call callback - not required in that example
50-
driver.execute_script("ArkoseEnforcement.funcaptchaCallback[0]('{}')".format(token))
51+
driver.execute_script(f"ArkoseEnforcement.funcaptchaCallback[0]('{token}')")
5152
driver.find_element(By.ID, "submit-btn").click()
5253
time.sleep(1)
5354

@@ -62,9 +63,9 @@ def get_sitekey(driver):
6263
def custom(req, req_body, res, res_body):
6364
if not req.path:
6465
return
65-
if not "arkoselabs" in req.path:
66+
if "arkoselabs" not in req.path:
6667
return
67-
if not res.headers.get("Content-Type", None) in [
68+
if res.headers.get("Content-Type", None) not in [
6869
"text/javascript",
6970
"application/javascript",
7071
]:

0 commit comments

Comments
 (0)