Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 16 additions & 18 deletions .github/workflows/pythontest.yml
Original file line number Diff line number Diff line change
@@ -1,27 +1,29 @@
name: Python testing

on: [push, pull_request]
on:
push:
branches:
- main
pull_request:
create:

jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v6
- name: Install uv
uses: astral-sh/setup-uv@v7
with:
python-version: "3.13"
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install ".[dev]"
run: uv sync --extra dev
- name: lint with ruff
run: |
ruff format tdclient --diff --exit-non-zero-on-fix
ruff check tdclient
uv run ruff format tdclient --diff --exit-non-zero-on-fix
uv run ruff check tdclient
- name: Run pyright
run: |
pyright tdclient
run: uv run pyright tdclient

test:
runs-on: ${{ matrix.os }}
Expand All @@ -33,19 +35,15 @@ jobs:

steps:
- uses: actions/checkout@v5
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v6
- name: Install uv
uses: astral-sh/setup-uv@v7
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install ".[dev]"
pip install -r requirements.txt -r test-requirements.txt
pip install -U coveralls pyyaml
run: uv sync --extra test
- name: Run test
run: |
coverage run --source=tdclient -m pytest tdclient/test
uv run coverage run --source=tdclient -m pytest tdclient/test

#
# Disable coverage submission to avoid
Expand Down
10 changes: 5 additions & 5 deletions .python-version
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
3.8.1
3.7.6
3.6.10
3.5.9
pypy2.7-7.1.0
3.10.19
3.11.14
3.12.12
3.13.9
3.14.0
2 changes: 0 additions & 2 deletions MANIFEST.in

This file was deleted.

38 changes: 31 additions & 7 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -301,34 +301,58 @@ Development
Running tests
^^^^^^^^^^^^^

Run tests.
Install the project dependencies with `uv <https://docs.astral.sh/uv/>`_ (runtime
and test extras) and execute pytest via ``uv run``.

.. code-block:: sh

$ pytest tdclient
$ uv sync --extra test
$ uv run pytest tdclient/test

To run the coverage suite locally, use:

.. code-block:: sh

$ uv run coverage run --source=tdclient -m pytest tdclient/test
$ uv run coverage report

Linting and type checking
^^^^^^^^^^^^^^^^^^^^^^^^^

Install the development extras and invoke ``ruff`` and ``pyright`` using
``uv run``.

.. code-block:: sh

$ uv sync --extra dev
$ uv run ruff format tdclient --diff --exit-non-zero-on-fix
$ uv run ruff check tdclient
$ uv run pyright tdclient

Running tests (tox)
^^^^^^^^^^^^^^^^^^^

You can run tests against all supported Python versions. I'd recommend you to install `pyenv <https://github.com/yyuu/pyenv>`_ to manage Pythons.
You can run tests against all supported Python versions with ``tox``. I'd
recommend you to install `pyenv <https://github.com/yyuu/pyenv>`_ to manage
additional interpreters.

.. code-block:: sh

$ pyenv shell system
$ for version in $(cat .python-version); do [ -d "$(pyenv root)/versions/${version}" ] || pyenv install "${version}"; done
$ pyenv shell --unset

Install `tox <https://pypi.python.org/pypi/tox>`_.
Install the development extras (which include ``tox``) with ``uv``.

.. code-block:: sh

$ pip install tox
$ uv sync --extra dev

Then, run ``tox``.
Then, run ``tox`` via ``uv``.

.. code-block:: sh

$ tox
$ uv run tox

Release
^^^^^^^
Expand Down
17 changes: 15 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,21 @@ dependencies = [
]

[project.optional-dependencies]
dev = ["ruff", "pyright"]
docs = ["sphinx", "sphinx_rtd_theme"]
dev = [
"ruff",
"pyright",
"tox>=4",
]
docs = [
"sphinx",
"sphinx_rtd_theme",
]
test = [
"coverage[toml]",
"pytest>=8.3",
"coveralls>=1.1,<5.0",
"pyyaml",
]

[tool.setuptools]
packages = ["tdclient"]
Expand Down
3 changes: 0 additions & 3 deletions requirements.txt

This file was deleted.

6 changes: 0 additions & 6 deletions tdclient/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -541,12 +541,6 @@ def send_request(
method, url, fields=fields, headers=headers, **kwargs
)

if urllib3.util.IS_PYOPENSSL and isinstance(body, bytearray):
# workaround for https://github.com/pyca/pyopenssl/issues/621
body = memoryview(body)
if urllib3.util.IS_PYOPENSSL and isinstance(body, array):
# workaround for https://github.com/pyca/pyopenssl/issues/621
body = body.tobytes()
return self.http.urlopen(method, url, body=body, headers=headers, **kwargs)

def raise_error(
Expand Down
2 changes: 1 addition & 1 deletion tdclient/bulk_import_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ def raise_error(
) -> None: ...
def checked_json(self, body: bytes, required: list[str]) -> dict[str, Any]: ...
def _prepare_file(
self, file: FileLike, format: str, **kwargs: Any
self, file_like: FileLike, fmt: str, **kwargs: Any
) -> IO[bytes]: ...

def create_bulk_import(
Expand Down
2 changes: 1 addition & 1 deletion tdclient/import_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ def raise_error(
) -> None: ...
def checked_json(self, body: bytes, required: list[str]) -> dict[str, Any]: ...
def _prepare_file(
self, file: FileLike, format: str, **kwargs: Any
self, file_like: FileLike, fmt: str, **kwargs: Any
) -> IO[bytes]: ...

def import_data(
Expand Down
25 changes: 5 additions & 20 deletions tdclient/test/api_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -305,10 +305,7 @@ def test_post_bytearray_success():
args, kwargs = td.http.urlopen.call_args
assert args == ("POST", "https://api.treasuredata.com/foo")
assert kwargs["body"] == bytes_or_stream
if urllib3.util.IS_PYOPENSSL:
assert isinstance(kwargs["body"], memoryview)
else:
assert isinstance(kwargs["body"], bytearray)
assert isinstance(kwargs["body"], bytearray)
assert sorted(kwargs["headers"].keys()) == [
"authorization",
"date",
Expand Down Expand Up @@ -404,10 +401,7 @@ def test_put_bytes_success():
with td.put("/foo", bytes_or_stream, 12) as response:
args, kwargs = td.http.urlopen.call_args
assert args == ("PUT", "https://api.treasuredata.com/foo")
if urllib3.util.IS_PYOPENSSL:
assert kwargs["body"] == b"request body"
else:
assert kwargs["body"] == array(str("b"), bytes_or_stream)
assert kwargs["body"] == array(str("b"), bytes_or_stream)
assert sorted(kwargs["headers"].keys()) == [
"authorization",
"content-length",
Expand All @@ -431,10 +425,7 @@ def test_put_bytes_unicode_success():
with td.put("/hoge", bytes_or_stream, 12) as response:
args, kwargs = td.http.urlopen.call_args
assert args == ("PUT", "https://api.treasuredata.com/hoge")
if urllib3.util.IS_PYOPENSSL:
assert kwargs["body"] == "リクエストボディー".encode("utf-8")
else:
assert kwargs["body"] == array(str("b"), bytes_or_stream)
assert kwargs["body"] == array(str("b"), bytes_or_stream)
assert sorted(kwargs["headers"].keys()) == [
"authorization",
"content-length",
Expand Down Expand Up @@ -510,10 +501,7 @@ def test_put_file_without_fileno_success():
with td.put("/foo", bytes_or_stream, 12) as response:
args, kwargs = td.http.urlopen.call_args
assert args == ("PUT", "https://api.treasuredata.com/foo")
if urllib3.util.IS_PYOPENSSL:
assert kwargs["body"] == b"request body"
else:
assert kwargs["body"] == array(str("b"), bytes_or_stream.getvalue())
assert kwargs["body"] == array(str("b"), bytes_or_stream.getvalue())
assert sorted(kwargs["headers"].keys()) == [
"authorization",
"content-length",
Expand All @@ -537,10 +525,7 @@ def test_put_file_without_fileno_unicode_success():
with td.put("/hoge", bytes_or_stream, 12) as response:
args, kwargs = td.http.urlopen.call_args
assert args == ("PUT", "https://api.treasuredata.com/hoge")
if urllib3.util.IS_PYOPENSSL:
assert kwargs["body"] == "リクエストボディー".encode("utf-8")
else:
assert kwargs["body"] == array(str("b"), bytes_or_stream.getvalue())
assert kwargs["body"] == array(str("b"), bytes_or_stream.getvalue())
assert sorted(kwargs["headers"].keys()) == [
"authorization",
"content-length",
Expand Down
3 changes: 0 additions & 3 deletions test-requirements.txt

This file was deleted.

31 changes: 19 additions & 12 deletions tox.ini
Original file line number Diff line number Diff line change
@@ -1,17 +1,12 @@
[tox]
envlist = py{38,39,310,311,312,py}-{pyopenssl,no_pyopenssl},format
requires = tox-uv
envlist = py{310,311,312,313,314,py},format,typecheck

[testenv]
deps=-r{toxinidir}/test-requirements.txt
pyopenssl: pyopenssl
deps=
.[test]
commands=pytest

[testenv:py38]
basepython=python3.9

[testenv:py39]
basepython=python3.9

[testenv:py310]
basepython=python3.10

Expand All @@ -21,14 +16,26 @@ basepython=python3.11
[testenv:py312]
basepython=python3.12

[testenv:py313]
basepython=python3.13

[testenv:py314]
basepython=python3.14

[testenv:pypy]
basepython=pypy

[testenv:format]
basepython=python3.8
basepython=python3.10
deps=
-e.[dev]
-r{toxinidir}/test-requirements.txt
.[dev]
commands =
ruff format --check tdclient
ruff check tdclient

[testenv:typecheck]
basepython=python3.10
deps=
.[dev]
commands=
pyright tdclient
Loading