diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ea87b39..f492739 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -22,3 +22,16 @@ jobs: cache: pip - run: python -m pip install -e ".[dev]" - run: pytest + + lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0 + - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0 + with: + python-version: "3.12" + cache: pip + # The dev extra pins ruff, so CI and contributors run the same version. + - run: python -m pip install -e ".[dev]" + - run: ruff check . + - run: ruff format --check . diff --git a/millionsend/_client.py b/millionsend/_client.py index a11c132..61f7e26 100644 --- a/millionsend/_client.py +++ b/millionsend/_client.py @@ -169,7 +169,12 @@ def request( try: resp = requests.request( - method, url, headers=headers, data=data, params=query, timeout=_config("timeout") or DEFAULT_TIMEOUT + method, + url, + headers=headers, + data=data, + params=query, + timeout=_config("timeout") or DEFAULT_TIMEOUT, ) except requests.exceptions.RequestException as exc: raise MillionSendError( diff --git a/millionsend/contacts.py b/millionsend/contacts.py index 9685d94..a9e755a 100644 --- a/millionsend/contacts.py +++ b/millionsend/contacts.py @@ -33,9 +33,7 @@ def list( ``params`` is resend-python's pagination dict, forwarded as the query. """ - return request( - "GET", f"/contacts/{_key(contact_id or id, email)}/topics", query=list_query(params) - ) + return request("GET", f"/contacts/{_key(contact_id or id, email)}/topics", query=list_query(params)) @classmethod def update(cls, params: Dict[str, Any]) -> Any: @@ -84,9 +82,7 @@ def create( ) @classmethod - def get( - cls, params: List[Union[str, Dict[str, Any]]], include: Optional[List[str]] = None - ) -> Any: + def get(cls, params: List[Union[str, Dict[str, Any]]], include: Optional[List[str]] = None) -> Any: """POST /contacts/batch/get — 1..1000 contacts by ``{"id": ...}`` or ``{"email": ...}`` (a bare string is an id), returned in request order. diff --git a/pyproject.toml b/pyproject.toml index 905a3a1..251dc2c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -18,10 +18,26 @@ Homepage = "https://github.com/MillionSend/millionsend-python" Repository = "https://github.com/MillionSend/millionsend-python" [project.optional-dependencies] -dev = ["pytest>=7"] +dev = ["pytest>=7", "ruff==0.16.9"] [tool.hatch.build.targets.wheel] packages = ["millionsend"] [tool.pytest.ini_options] testpaths = ["tests"] + +[tool.ruff] +target-version = "py39" +line-length = 110 +# The README's Python samples keep their hand-aligned comments. +extend-exclude = ["*.md"] + +[tool.ruff.lint] +ignore = [ + # Public signatures keep typing.Optional/Dict/List; rewriting the annotations changes them. + "FA100", + "UP006", + "UP035", + # __all__ is grouped by purpose (config, resources, errors), not alphabetized. + "RUF022", +] diff --git a/tests/conftest.py b/tests/conftest.py index 21d6fd3..a3dff3b 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -5,7 +5,7 @@ import pytest import millionsend -import millionsend._client as _client +from millionsend import _client class FakeResponse: diff --git a/tests/test_client.py b/tests/test_client.py index 6f16e6f..f0f9cc1 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -4,12 +4,12 @@ import requests import millionsend -import millionsend._client as _client from millionsend import ( MillionSendError, MissingApiKeyError, NotFoundError, ValidationError, + _client, ) diff --git a/tests/test_resources.py b/tests/test_resources.py index 17730b5..9d5e5b4 100644 --- a/tests/test_resources.py +++ b/tests/test_resources.py @@ -292,9 +292,7 @@ def test_contacts_topics_list(http): def test_contacts_topics_update_bare_array(http): http.body = {"id": "c1"} - millionsend.Contacts.Topics.update( - {"id": "c1", "topics": [{"id": "t1", "subscription": "opt_out"}]} - ) + millionsend.Contacts.Topics.update({"id": "c1", "topics": [{"id": "t1", "subscription": "opt_out"}]}) assert http.calls[0]["method"] == "PATCH" assert http.calls[0]["path"] == "/contacts/c1/topics" assert http.calls[0]["body"] == [{"id": "t1", "subscription": "opt_out"}]