From d789de9f5dd89fbdaeaaf9c83aed3a752e1bb916 Mon Sep 17 00:00:00 2001 From: Konboi Date: Thu, 19 Jun 2025 09:58:40 +0900 Subject: [PATCH 01/22] Groovy lang works on JVM but we haven't supported it as jvm_test_pattern so, fixed the regexp to support groovy --- launchable/utils/file_name_pattern.py | 4 ++-- tests/utils/test_file_name_pattern.py | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/launchable/utils/file_name_pattern.py b/launchable/utils/file_name_pattern.py index e5dd67980..33bbd4166 100644 --- a/launchable/utils/file_name_pattern.py +++ b/launchable/utils/file_name_pattern.py @@ -1,4 +1,4 @@ import re -# find *Test, *Tests, *TestCase + .java, .scala, .kt -jvm_test_pattern = re.compile(r'^.*Test(?:Case|s)?\.(?:java|scala|kt)$') +# find *Test, *Tests, *TestCase, *Spec + .java, .scala, .kt, .groovy +jvm_test_pattern = re.compile(r'^.*(?:Test(?:Case|s)?|Spec)\.(?:java|scala|kt|groovy)$') diff --git a/tests/utils/test_file_name_pattern.py b/tests/utils/test_file_name_pattern.py index 86cdacb77..5fcf62677 100644 --- a/tests/utils/test_file_name_pattern.py +++ b/tests/utils/test_file_name_pattern.py @@ -8,7 +8,9 @@ def test_jvm_file_name(self): file_names = [ 'LaunchableTest.java', 'LaunchableTests.java', - 'LaunchableTestCase.java' + 'LaunchableTestCase.java', + 'LaunchableTest.groovy', + 'LaunchableSpec.groovy', ] for file_name in file_names: self.assertTrue(jvm_test_pattern.match(file_name)) From 099cc686010e6a56a5950143b8730704ea7638d2 Mon Sep 17 00:00:00 2001 From: ninjinkun Date: Wed, 18 Jun 2025 16:28:28 +0900 Subject: [PATCH 02/22] feature: migrate from `pipenv` to `uv` --- .github/workflows/python-package.yml | 65 ++-- .github/workflows/python-publish.yml | 26 +- .python-version | 2 +- Pipfile | 45 --- README.md | 72 +++- pyproject.toml | 60 +++ setup.cfg | 14 +- uv.lock | 538 +++++++++++++++++++++++++++ 8 files changed, 692 insertions(+), 130 deletions(-) delete mode 100644 Pipfile create mode 100644 uv.lock diff --git a/.github/workflows/python-package.yml b/.github/workflows/python-package.yml index aee24985c..993d08217 100644 --- a/.github/workflows/python-package.yml +++ b/.github/workflows/python-package.yml @@ -11,7 +11,6 @@ on: - 'WORKSPACE' - 'src/**' pull_request: - branches: [ main ] paths-ignore: - 'WORKSPACE' - 'src/**' @@ -34,63 +33,41 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - # Python 3.6 is not supported on Ubuntu 22.04. os: [ubuntu-22.04, windows-latest] - python-version: [3.7, 3.8, 3.9, "3.10", "3.11", "3.12"] - include: - - os: windows-latest - python-version: 3.6 steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - uses: actions/checkout@v4 with: fetch-depth: 0 - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v5 + + - name: Install uv + uses: astral-sh/setup-uv@v3 with: - python-version: ${{ matrix.python-version }} + enable-cache: true + cache-dependency-glob: "uv.lock" + - name: Set up JDK 1.8 uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4.7.1 with: java-version: 8 - distribution: 'temurin' - - name: Install specific dependencies in 3.6 - if: matrix.python-version == '3.6' - uses: nick-fields/retry@ce71cc2ab81d554ebbe88c79ab5975992d79ba08 # v3.0.2 - with: - max_attempts: 3 - timeout_minutes: 5 - retry_on: error - command: | - python -m pip install --upgrade pip - pip install pipenv==2021.11.5 - pipenv install --dev --python ${{ matrix.python-version }} + distribution: 'temurin' + - name: Install dependencies - if: matrix.python-version != '3.6' - uses: nick-fields/retry@ce71cc2ab81d554ebbe88c79ab5975992d79ba08 # v3.0.2 - with: - max_attempts: 3 - timeout_minutes: 5 - retry_on: error - command: | - python -m pip install --upgrade pip - pip install pipenv - pipenv install --dev --python ${{ matrix.python-version }} + run: uv sync --dev - name: Build run: | - pipenv run pip list - pipenv run build - pipenv run install + uv pip list + uv run poe build + - name: Type check - run: pipenv run type + run: uv run poe type + - name: Lint with flake8 - run: | - # stop the build if there are Python syntax errors or undefined names - pipenv run lint + run: uv run poe lint - name: Pull request validation run: | - # Install Launchable CLI from this repos's code - pip3 install . > /dev/null + # Install Launchable CLI from this repo's code as a global tool + uv tool install . set -x @@ -99,7 +76,7 @@ jobs: # Tell Launchable about the build you are producing and testing launchable record build --name ${GITHUB_RUN_ID} - launchable record session --build ${GITHUB_RUN_ID} --flavor os=${{ matrix.os }} --flavor python=${{ matrix.python-version }} > session.txt + launchable record session --build ${GITHUB_RUN_ID} --flavor os=${{ matrix.os }} --flavor python=3.13 > session.txt # Find 25% of the relevant tests to run for this change find tests -name test_*.py | grep -v tests/data | launchable subset --target 25% --session $(cat session.txt) --rest launchable-remainder.txt file > subset.txt @@ -112,8 +89,8 @@ jobs: trap record EXIT # Test subset of tests - pipenv run test-xml $(tr '\r\n' '\n' < subset.txt) + uv run poe test-xml $(tr '\r\n' '\n' < subset.txt) # Test rest of tests - pipenv run test-xml $(tr '\r\n' '\n' < launchable-remainder.txt) + uv run poe test-xml $(tr '\r\n' '\n' < launchable-remainder.txt) shell: bash diff --git a/.github/workflows/python-publish.yml b/.github/workflows/python-publish.yml index 82d80b589..ffe23603a 100644 --- a/.github/workflows/python-publish.yml +++ b/.github/workflows/python-publish.yml @@ -38,26 +38,14 @@ jobs: - uses: actions/checkout@v4 with: fetch-depth: 0 + - name: Install uv + uses: astral-sh/setup-uv@v3 + - name: Set up Python - uses: actions/setup-python@v5 - with: - python-version: '3.x' - # build and publish package using GitHub Actions workflow - # https://packaging.python.org/en/latest/guides/publishing-package-distribution-releases-using-github-actions-ci-cd-workflows/ - - name: Install pypa/build - run: >- - python -m - pip install - build - --user - - name: Build a binary wheel and a source tarball - run: >- - python -m - build - --sdist - --wheel - --outdir dist/ - . + run: uv python install 3.13 + + - name: Build package + run: uv build # actual publish - name: Publish to PyPI uses: pypa/gh-action-pypi-publish@76f52bc884231f62b9a034ebfe128415bbaabdfc # v1.12.4 diff --git a/.python-version b/.python-version index cd337510b..24ee5b1be 100644 --- a/.python-version +++ b/.python-version @@ -1 +1 @@ -3.6.15 +3.13 diff --git a/Pipfile b/Pipfile deleted file mode 100644 index 1490547d6..000000000 --- a/Pipfile +++ /dev/null @@ -1,45 +0,0 @@ -[[source]] -name = "pypi" -url = "https://pypi.org/simple" -verify_ssl = true - -[requires] -python_version = "3.6" - -[dev-packages] -flake8 = "*" -setuptools = ">=30.3.0" -setuptools-scm = "*" -wheel = "*" -# The last flake8 version that supports Python 3.6 specifies "pycodestyle >= -# 2.9.0, < 2.10.0". ref: https://github.com/PyCQA/flake8/pull/1633 -# The latest autopep8 specifies "pycodestyle >= 2.10.0". This conflict cannot be resolved. Pin the version to resolve this. -autopep8 = "<=1.7.0" -importlib-metadata = "<7.2" -isort = "*" -more_itertools = "<10.4" -mypy = "<1.16.0" -pre-commit = "*" -responses = "*" -types-click = "*" -types-pkg_resources = "0.1.3" -types-python-dateutil = "*" -types-requests = "*" -types-tabulate = "*" -lxml = "<=5.2.2" -unittest-xml-reporting = "*" -# newer virtualenv creates a conflict with importlib-metadata. This is the latest version that seems to avoid that -virtualenv = "==20.16.2" - -[packages] -launchable = {editable = true, path = "."} - -[scripts] -build = "python setup.py sdist bdist_wheel" -format = "/bin/bash -c 'isort -l 130 --balanced launchable/*.py tests/*.py && autopep8 --in-place --recursive --aggressive --experimental --max-line-length=130 --verbose launchable/ tests/'" -install = "pip install -U ." -lint = "flake8 --count --ignore=C901,E741,F401 --show-source --max-line-length=130 --statistics launchable/ tests/" -lint-warn = "flake8 --count --exit-zero --max-complexity=15 --max-line-length=130 --statistics launchable/ tests/" -test = "python -m unittest" -test-xml = "python -m test-runner" -type = "mypy launchable tests" diff --git a/README.md b/README.md index 2079ae423..dde315415 100644 --- a/README.md +++ b/README.md @@ -7,27 +7,37 @@ https://www.launchableinc.com/docs/getting-started/. ## Preparation -We recommend Pipenv +We recommend uv for dependency management: ```shell -pip install pipenv==2021.5.29 -pipenv install --dev +# Install uv +curl -LsSf https://astral.sh/uv/install.sh | sh + +# Install dependencies +uv sync --dev ``` In order to automatically format files with autopep8, this repository contains a configuration for [pre-commit](https://pre-commit.com). Install the hook with -`pipenv run pre-commit install`. +`uv run pre-commit install`. ## Load development environment ```shell -pipenv shell +# Activate virtual environment +source .venv/bin/activate +# or use uv run for individual commands +uv run ``` ## Run tests cli ```shell -pipenv run test +# Using poethepoet (recommended) +uv run poe test + +# Direct command +uv run python -m unittest ``` ## Run tests exe_deploy.jar @@ -36,12 +46,58 @@ pipenv run test bazel test ... ``` +## Available Development Tasks + +This project uses [poethepoet](https://poethepoet.natn.io/) for task management. Available tasks: + +```shell +# Show all available tasks +uv run poe --help + +# Run tests +uv run poe test + +# Run tests with XML output +uv run poe test-xml + +# Run linting +uv run poe lint + +# Run type checking +uv run poe type + +# Format code +uv run poe format + +# Build package +uv run poe build + +# Install package locally +uv run poe install +``` + ## Add dependency ```shell -pipenv install --dev some-what-module +# Add runtime dependency +uv add some-package + +# Add development dependency +uv add --dev some-dev-package ``` +## Updating Python Version + +When updating the Python version requirement, update the following files: + +1. **`.python-version`** - Used by pyenv, uv, and local development +2. **`pyproject.toml`** - Update `requires-python = ">=X.Y"` +3. **`setup.cfg`** - Update `python_requires = >=X.Y` +4. **`.github/workflows/python-package.yml`** - Update `python-version: ["X.Y"]` +5. **`.github/workflows/python-publish.yml`** - Update `uv python install X.Y` +6. **`README.md`** - Update prerequisite section +7. **`CLAUDE.md`** - Update development notes + # How to release Create new release on Github, then Github Actions automatically uploads the @@ -59,7 +115,7 @@ You can install the `launchable` command from either source or [pypi](https://py ## Prerequisite -- \>= Python 3.6 +- \>= Python 3.13 - \>= Java 8 ## Install from source diff --git a/pyproject.toml b/pyproject.toml index 3d2e73457..618978f45 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,3 +1,63 @@ +[project] +name = "launchable" +authors = [ + {name = "Launchable, Inc.", email = "info@launchableinc.com"} +] +description = "Launchable CLI" +readme = "README.md" +license = {text = "Apache Software License v2"} +requires-python = ">=3.13" +classifiers = [ + "Programming Language :: Python :: 3", + "License :: OSI Approved :: Apache Software License", + "Operating System :: OS Independent", +] +dependencies = [ + "click>=8.1,<8.2", + "requests>=2.25", + "urllib3>=1.26", + "junitparser>=2.0.0", + "setuptools", + "more-itertools>=7.1.0", + "python-dateutil", + "tabulate", +] +dynamic = ["version"] + +[project.urls] +Homepage = "https://launchableinc.com/" +Repository = "https://github.com/launchableinc/cli" + +[project.scripts] +launchable = "launchable.__main__:main" + +[tool.uv] +dev-dependencies = [ + "flake8", + "autopep8<=1.7.0", + "isort", + "mypy<1.16.0", + "pre-commit", + "responses", + "types-click", + "types-pkg_resources==0.1.3", + "types-python-dateutil", + "types-requests", + "types-tabulate", + "lxml", + "unittest-xml-reporting", + "poethepoet", +] + +[tool.poe.tasks] +build = "python setup.py sdist bdist_wheel" +format = "/bin/bash -c 'isort -l 130 --balanced launchable/*.py tests/*.py && autopep8 --in-place --recursive --aggressive --experimental --max-line-length=130 --verbose launchable/ tests/'" +lint = "flake8 --count --ignore=C901,E741,F401 --show-source --max-line-length=130 --statistics launchable/ tests/" +lint-warn = "flake8 --count --exit-zero --max-complexity=15 --max-line-length=130 --statistics launchable/ tests/" +test = "python -m unittest" +test-xml = "python -m test-runner" +type = "mypy launchable tests" + [build-system] requires = ["setuptools>=45", "wheel", "setuptools_scm"] build-backend = "setuptools.build_meta" diff --git a/setup.cfg b/setup.cfg index b028d942b..a66aeac75 100644 --- a/setup.cfg +++ b/setup.cfg @@ -14,19 +14,7 @@ classifiers = [options] packages = find: -install_requires = - click>=8.0,<8.1;python_version=='3.6' - click>=8.1,<8.2;python_version>'3.6' - requests>=2.25;python_version>='3.6' - urllib3>=1.26 - junitparser>=2.0.0 - setuptools - more_itertools>=7.1.0;python_version>='3.6' - python-dateutil - tabulate -python_requires = >=3.6 -setup_requires = - setuptools-scm +python_requires = >=3.13 [options.entry_points] console_scripts = launchable = launchable.__main__:main diff --git a/uv.lock b/uv.lock new file mode 100644 index 000000000..164060970 --- /dev/null +++ b/uv.lock @@ -0,0 +1,538 @@ +version = 1 +revision = 2 +requires-python = ">=3.13" + +[[package]] +name = "autopep8" +version = "1.7.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pycodestyle" }, + { name = "toml" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/d0/5d/016888824972086a4ee164806520d85ff173e83699907b9cfe119aaefbbc/autopep8-1.7.0.tar.gz", hash = "sha256:ca9b1a83e53a7fad65d731dc7a2a2d50aa48f43850407c59f6a1a306c4201142", size = 117055, upload-time = "2022-08-09T12:55:28.934Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5d/9b/1ed75f8c9086fafe0e9bbb379a70c43b1aa9dff6154ddcfb818f78cb0736/autopep8-1.7.0-py2.py3-none-any.whl", hash = "sha256:6f09e90a2be784317e84dc1add17ebfc7abe3924239957a37e5040e27d812087", size = 45563, upload-time = "2022-08-09T12:55:25.914Z" }, +] + +[[package]] +name = "certifi" +version = "2025.6.15" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/73/f7/f14b46d4bcd21092d7d3ccef689615220d8a08fb25e564b65d20738e672e/certifi-2025.6.15.tar.gz", hash = "sha256:d747aa5a8b9bbbb1bb8c22bb13e22bd1f18e9796defa16bab421f7f7a317323b", size = 158753, upload-time = "2025-06-15T02:45:51.329Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/84/ae/320161bd181fc06471eed047ecce67b693fd7515b16d495d8932db763426/certifi-2025.6.15-py3-none-any.whl", hash = "sha256:2e0c7ce7cb5d8f8634ca55d2ba7e6ec2689a2fd6537d8dec1296a477a4910057", size = 157650, upload-time = "2025-06-15T02:45:49.977Z" }, +] + +[[package]] +name = "cfgv" +version = "3.4.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/11/74/539e56497d9bd1d484fd863dd69cbbfa653cd2aa27abfe35653494d85e94/cfgv-3.4.0.tar.gz", hash = "sha256:e52591d4c5f5dead8e0f673fb16db7949d2cfb3f7da4582893288f0ded8fe560", size = 7114, upload-time = "2023-08-12T20:38:17.776Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c5/55/51844dd50c4fc7a33b653bfaba4c2456f06955289ca770a5dbd5fd267374/cfgv-3.4.0-py2.py3-none-any.whl", hash = "sha256:b7265b1f29fd3316bfcd2b330d63d024f2bfd8bcb8b0272f8e19a504856c48f9", size = 7249, upload-time = "2023-08-12T20:38:16.269Z" }, +] + +[[package]] +name = "charset-normalizer" +version = "3.4.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e4/33/89c2ced2b67d1c2a61c19c6751aa8902d46ce3dacb23600a283619f5a12d/charset_normalizer-3.4.2.tar.gz", hash = "sha256:5baececa9ecba31eff645232d59845c07aa030f0c81ee70184a90d35099a0e63", size = 126367, upload-time = "2025-05-02T08:34:42.01Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ea/12/a93df3366ed32db1d907d7593a94f1fe6293903e3e92967bebd6950ed12c/charset_normalizer-3.4.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:926ca93accd5d36ccdabd803392ddc3e03e6d4cd1cf17deff3b989ab8e9dbcf0", size = 199622, upload-time = "2025-05-02T08:32:56.363Z" }, + { url = "https://files.pythonhosted.org/packages/04/93/bf204e6f344c39d9937d3c13c8cd5bbfc266472e51fc8c07cb7f64fcd2de/charset_normalizer-3.4.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eba9904b0f38a143592d9fc0e19e2df0fa2e41c3c3745554761c5f6447eedabf", size = 143435, upload-time = "2025-05-02T08:32:58.551Z" }, + { url = "https://files.pythonhosted.org/packages/22/2a/ea8a2095b0bafa6c5b5a55ffdc2f924455233ee7b91c69b7edfcc9e02284/charset_normalizer-3.4.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3fddb7e2c84ac87ac3a947cb4e66d143ca5863ef48e4a5ecb83bd48619e4634e", size = 153653, upload-time = "2025-05-02T08:33:00.342Z" }, + { url = "https://files.pythonhosted.org/packages/b6/57/1b090ff183d13cef485dfbe272e2fe57622a76694061353c59da52c9a659/charset_normalizer-3.4.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:98f862da73774290f251b9df8d11161b6cf25b599a66baf087c1ffe340e9bfd1", size = 146231, upload-time = "2025-05-02T08:33:02.081Z" }, + { url = "https://files.pythonhosted.org/packages/e2/28/ffc026b26f441fc67bd21ab7f03b313ab3fe46714a14b516f931abe1a2d8/charset_normalizer-3.4.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c9379d65defcab82d07b2a9dfbfc2e95bc8fe0ebb1b176a3190230a3ef0e07c", size = 148243, upload-time = "2025-05-02T08:33:04.063Z" }, + { url = "https://files.pythonhosted.org/packages/c0/0f/9abe9bd191629c33e69e47c6ef45ef99773320e9ad8e9cb08b8ab4a8d4cb/charset_normalizer-3.4.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e635b87f01ebc977342e2697d05b56632f5f879a4f15955dfe8cef2448b51691", size = 150442, upload-time = "2025-05-02T08:33:06.418Z" }, + { url = "https://files.pythonhosted.org/packages/67/7c/a123bbcedca91d5916c056407f89a7f5e8fdfce12ba825d7d6b9954a1a3c/charset_normalizer-3.4.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:1c95a1e2902a8b722868587c0e1184ad5c55631de5afc0eb96bc4b0d738092c0", size = 145147, upload-time = "2025-05-02T08:33:08.183Z" }, + { url = "https://files.pythonhosted.org/packages/ec/fe/1ac556fa4899d967b83e9893788e86b6af4d83e4726511eaaad035e36595/charset_normalizer-3.4.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:ef8de666d6179b009dce7bcb2ad4c4a779f113f12caf8dc77f0162c29d20490b", size = 153057, upload-time = "2025-05-02T08:33:09.986Z" }, + { url = "https://files.pythonhosted.org/packages/2b/ff/acfc0b0a70b19e3e54febdd5301a98b72fa07635e56f24f60502e954c461/charset_normalizer-3.4.2-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:32fc0341d72e0f73f80acb0a2c94216bd704f4f0bce10aedea38f30502b271ff", size = 156454, upload-time = "2025-05-02T08:33:11.814Z" }, + { url = "https://files.pythonhosted.org/packages/92/08/95b458ce9c740d0645feb0e96cea1f5ec946ea9c580a94adfe0b617f3573/charset_normalizer-3.4.2-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:289200a18fa698949d2b39c671c2cc7a24d44096784e76614899a7ccf2574b7b", size = 154174, upload-time = "2025-05-02T08:33:13.707Z" }, + { url = "https://files.pythonhosted.org/packages/78/be/8392efc43487ac051eee6c36d5fbd63032d78f7728cb37aebcc98191f1ff/charset_normalizer-3.4.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4a476b06fbcf359ad25d34a057b7219281286ae2477cc5ff5e3f70a246971148", size = 149166, upload-time = "2025-05-02T08:33:15.458Z" }, + { url = "https://files.pythonhosted.org/packages/44/96/392abd49b094d30b91d9fbda6a69519e95802250b777841cf3bda8fe136c/charset_normalizer-3.4.2-cp313-cp313-win32.whl", hash = "sha256:aaeeb6a479c7667fbe1099af9617c83aaca22182d6cf8c53966491a0f1b7ffb7", size = 98064, upload-time = "2025-05-02T08:33:17.06Z" }, + { url = "https://files.pythonhosted.org/packages/e9/b0/0200da600134e001d91851ddc797809e2fe0ea72de90e09bec5a2fbdaccb/charset_normalizer-3.4.2-cp313-cp313-win_amd64.whl", hash = "sha256:aa6af9e7d59f9c12b33ae4e9450619cf2488e2bbe9b44030905877f0b2324980", size = 105641, upload-time = "2025-05-02T08:33:18.753Z" }, + { url = "https://files.pythonhosted.org/packages/20/94/c5790835a017658cbfabd07f3bfb549140c3ac458cfc196323996b10095a/charset_normalizer-3.4.2-py3-none-any.whl", hash = "sha256:7f56930ab0abd1c45cd15be65cc741c28b1c9a34876ce8c17a2fa107810c0af0", size = 52626, upload-time = "2025-05-02T08:34:40.053Z" }, +] + +[[package]] +name = "click" +version = "8.1.8" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "colorama", marker = "sys_platform == 'win32'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/b9/2e/0090cbf739cee7d23781ad4b89a9894a41538e4fcf4c31dcdd705b78eb8b/click-8.1.8.tar.gz", hash = "sha256:ed53c9d8990d83c2a27deae68e4ee337473f6330c040a31d4225c9574d16096a", size = 226593, upload-time = "2024-12-21T18:38:44.339Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7e/d4/7ebdbd03970677812aac39c869717059dbb71a4cfc033ca6e5221787892c/click-8.1.8-py3-none-any.whl", hash = "sha256:63c132bbbed01578a06712a2d1f497bb62d9c1c0d329b7903a866228027263b2", size = 98188, upload-time = "2024-12-21T18:38:41.666Z" }, +] + +[[package]] +name = "colorama" +version = "0.4.6" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697, upload-time = "2022-10-25T02:36:22.414Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" }, +] + +[[package]] +name = "distlib" +version = "0.3.9" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/0d/dd/1bec4c5ddb504ca60fc29472f3d27e8d4da1257a854e1d96742f15c1d02d/distlib-0.3.9.tar.gz", hash = "sha256:a60f20dea646b8a33f3e7772f74dc0b2d0772d2837ee1342a00645c81edf9403", size = 613923, upload-time = "2024-10-09T18:35:47.551Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/91/a1/cf2472db20f7ce4a6be1253a81cfdf85ad9c7885ffbed7047fb72c24cf87/distlib-0.3.9-py2.py3-none-any.whl", hash = "sha256:47f8c22fd27c27e25a65601af709b38e4f0a45ea4fc2e710f65755fa8caaaf87", size = 468973, upload-time = "2024-10-09T18:35:44.272Z" }, +] + +[[package]] +name = "filelock" +version = "3.18.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/0a/10/c23352565a6544bdc5353e0b15fc1c563352101f30e24bf500207a54df9a/filelock-3.18.0.tar.gz", hash = "sha256:adbc88eabb99d2fec8c9c1b229b171f18afa655400173ddc653d5d01501fb9f2", size = 18075, upload-time = "2025-03-14T07:11:40.47Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/4d/36/2a115987e2d8c300a974597416d9de88f2444426de9571f4b59b2cca3acc/filelock-3.18.0-py3-none-any.whl", hash = "sha256:c401f4f8377c4464e6db25fff06205fd89bdd83b65eb0488ed1b160f780e21de", size = 16215, upload-time = "2025-03-14T07:11:39.145Z" }, +] + +[[package]] +name = "flake8" +version = "7.2.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "mccabe" }, + { name = "pycodestyle" }, + { name = "pyflakes" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/e7/c4/5842fc9fc94584c455543540af62fd9900faade32511fab650e9891ec225/flake8-7.2.0.tar.gz", hash = "sha256:fa558ae3f6f7dbf2b4f22663e5343b6b6023620461f8d4ff2019ef4b5ee70426", size = 48177, upload-time = "2025-03-29T20:08:39.329Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/83/5c/0627be4c9976d56b1217cb5187b7504e7fd7d3503f8bfd312a04077bd4f7/flake8-7.2.0-py2.py3-none-any.whl", hash = "sha256:93b92ba5bdb60754a6da14fa3b93a9361fd00a59632ada61fd7b130436c40343", size = 57786, upload-time = "2025-03-29T20:08:37.902Z" }, +] + +[[package]] +name = "identify" +version = "2.6.12" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a2/88/d193a27416618628a5eea64e3223acd800b40749a96ffb322a9b55a49ed1/identify-2.6.12.tar.gz", hash = "sha256:d8de45749f1efb108badef65ee8386f0f7bb19a7f26185f74de6367bffbaf0e6", size = 99254, upload-time = "2025-05-23T20:37:53.3Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7a/cd/18f8da995b658420625f7ef13f037be53ae04ec5ad33f9b718240dcfd48c/identify-2.6.12-py2.py3-none-any.whl", hash = "sha256:ad9672d5a72e0d2ff7c5c8809b62dfa60458626352fb0eb7b55e69bdc45334a2", size = 99145, upload-time = "2025-05-23T20:37:51.495Z" }, +] + +[[package]] +name = "idna" +version = "3.10" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f1/70/7703c29685631f5a7590aa73f1f1d3fa9a380e654b86af429e0934a32f7d/idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9", size = 190490, upload-time = "2024-09-15T18:07:39.745Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/76/c6/c88e154df9c4e1a2a66ccf0005a88dfb2650c1dffb6f5ce603dfbd452ce3/idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3", size = 70442, upload-time = "2024-09-15T18:07:37.964Z" }, +] + +[[package]] +name = "isort" +version = "6.0.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/b8/21/1e2a441f74a653a144224d7d21afe8f4169e6c7c20bb13aec3a2dc3815e0/isort-6.0.1.tar.gz", hash = "sha256:1cb5df28dfbc742e490c5e41bad6da41b805b0a8be7bc93cd0fb2a8a890ac450", size = 821955, upload-time = "2025-02-26T21:13:16.955Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c1/11/114d0a5f4dabbdcedc1125dee0888514c3c3b16d3e9facad87ed96fad97c/isort-6.0.1-py3-none-any.whl", hash = "sha256:2dc5d7f65c9678d94c88dfc29161a320eec67328bc97aad576874cb4be1e9615", size = 94186, upload-time = "2025-02-26T21:13:14.911Z" }, +] + +[[package]] +name = "junitparser" +version = "3.2.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/57/88/6a268028a297751ed73be8e291f12aa727caf22adbc218e8dfbafcc974af/junitparser-3.2.0.tar.gz", hash = "sha256:b05e89c27e7b74b3c563a078d6e055d95cf397444f8f689b0ca616ebda0b3c65", size = 20073, upload-time = "2024-09-01T04:07:42.291Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5a/f9/321d566c9f2af81fdb4bb3d5900214116b47be9e26b82219da8b818d9da9/junitparser-3.2.0-py2.py3-none-any.whl", hash = "sha256:e14fdc0a999edfc15889b637390e8ef6ca09a49532416d3bd562857d42d4b96d", size = 13394, upload-time = "2024-09-01T04:07:40.541Z" }, +] + +[[package]] +name = "launchable" +source = { editable = "." } +dependencies = [ + { name = "click" }, + { name = "junitparser" }, + { name = "more-itertools" }, + { name = "python-dateutil" }, + { name = "requests" }, + { name = "setuptools" }, + { name = "tabulate" }, + { name = "urllib3" }, +] + +[package.dev-dependencies] +dev = [ + { name = "autopep8" }, + { name = "flake8" }, + { name = "isort" }, + { name = "lxml" }, + { name = "mypy" }, + { name = "poethepoet" }, + { name = "pre-commit" }, + { name = "responses" }, + { name = "types-click" }, + { name = "types-pkg-resources" }, + { name = "types-python-dateutil" }, + { name = "types-requests" }, + { name = "types-tabulate" }, + { name = "unittest-xml-reporting" }, +] + +[package.metadata] +requires-dist = [ + { name = "click", specifier = ">=8.1,<8.2" }, + { name = "junitparser", specifier = ">=2.0.0" }, + { name = "more-itertools", specifier = ">=7.1.0" }, + { name = "python-dateutil" }, + { name = "requests", specifier = ">=2.25" }, + { name = "setuptools" }, + { name = "tabulate" }, + { name = "urllib3", specifier = ">=1.26" }, +] + +[package.metadata.requires-dev] +dev = [ + { name = "autopep8", specifier = "<=1.7.0" }, + { name = "flake8" }, + { name = "isort" }, + { name = "lxml" }, + { name = "mypy", specifier = "<1.16.0" }, + { name = "poethepoet" }, + { name = "pre-commit" }, + { name = "responses" }, + { name = "types-click" }, + { name = "types-pkg-resources", specifier = "==0.1.3" }, + { name = "types-python-dateutil" }, + { name = "types-requests" }, + { name = "types-tabulate" }, + { name = "unittest-xml-reporting" }, +] + +[[package]] +name = "lxml" +version = "5.4.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/76/3d/14e82fc7c8fb1b7761f7e748fd47e2ec8276d137b6acfe5a4bb73853e08f/lxml-5.4.0.tar.gz", hash = "sha256:d12832e1dbea4be280b22fd0ea7c9b87f0d8fc51ba06e92dc62d52f804f78ebd", size = 3679479, upload-time = "2025-04-23T01:50:29.322Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/87/cb/2ba1e9dd953415f58548506fa5549a7f373ae55e80c61c9041b7fd09a38a/lxml-5.4.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:773e27b62920199c6197130632c18fb7ead3257fce1ffb7d286912e56ddb79e0", size = 8110086, upload-time = "2025-04-23T01:46:52.218Z" }, + { url = "https://files.pythonhosted.org/packages/b5/3e/6602a4dca3ae344e8609914d6ab22e52ce42e3e1638c10967568c5c1450d/lxml-5.4.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:ce9c671845de9699904b1e9df95acfe8dfc183f2310f163cdaa91a3535af95de", size = 4404613, upload-time = "2025-04-23T01:46:55.281Z" }, + { url = "https://files.pythonhosted.org/packages/4c/72/bf00988477d3bb452bef9436e45aeea82bb40cdfb4684b83c967c53909c7/lxml-5.4.0-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9454b8d8200ec99a224df8854786262b1bd6461f4280064c807303c642c05e76", size = 5012008, upload-time = "2025-04-23T01:46:57.817Z" }, + { url = "https://files.pythonhosted.org/packages/92/1f/93e42d93e9e7a44b2d3354c462cd784dbaaf350f7976b5d7c3f85d68d1b1/lxml-5.4.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cccd007d5c95279e529c146d095f1d39ac05139de26c098166c4beb9374b0f4d", size = 4760915, upload-time = "2025-04-23T01:47:00.745Z" }, + { url = "https://files.pythonhosted.org/packages/45/0b/363009390d0b461cf9976a499e83b68f792e4c32ecef092f3f9ef9c4ba54/lxml-5.4.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0fce1294a0497edb034cb416ad3e77ecc89b313cff7adbee5334e4dc0d11f422", size = 5283890, upload-time = "2025-04-23T01:47:04.702Z" }, + { url = "https://files.pythonhosted.org/packages/19/dc/6056c332f9378ab476c88e301e6549a0454dbee8f0ae16847414f0eccb74/lxml-5.4.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:24974f774f3a78ac12b95e3a20ef0931795ff04dbb16db81a90c37f589819551", size = 4812644, upload-time = "2025-04-23T01:47:07.833Z" }, + { url = "https://files.pythonhosted.org/packages/ee/8a/f8c66bbb23ecb9048a46a5ef9b495fd23f7543df642dabeebcb2eeb66592/lxml-5.4.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:497cab4d8254c2a90bf988f162ace2ddbfdd806fce3bda3f581b9d24c852e03c", size = 4921817, upload-time = "2025-04-23T01:47:10.317Z" }, + { url = "https://files.pythonhosted.org/packages/04/57/2e537083c3f381f83d05d9b176f0d838a9e8961f7ed8ddce3f0217179ce3/lxml-5.4.0-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:e794f698ae4c5084414efea0f5cc9f4ac562ec02d66e1484ff822ef97c2cadff", size = 4753916, upload-time = "2025-04-23T01:47:12.823Z" }, + { url = "https://files.pythonhosted.org/packages/d8/80/ea8c4072109a350848f1157ce83ccd9439601274035cd045ac31f47f3417/lxml-5.4.0-cp313-cp313-manylinux_2_28_ppc64le.whl", hash = "sha256:2c62891b1ea3094bb12097822b3d44b93fc6c325f2043c4d2736a8ff09e65f60", size = 5289274, upload-time = "2025-04-23T01:47:15.916Z" }, + { url = "https://files.pythonhosted.org/packages/b3/47/c4be287c48cdc304483457878a3f22999098b9a95f455e3c4bda7ec7fc72/lxml-5.4.0-cp313-cp313-manylinux_2_28_s390x.whl", hash = "sha256:142accb3e4d1edae4b392bd165a9abdee8a3c432a2cca193df995bc3886249c8", size = 4874757, upload-time = "2025-04-23T01:47:19.793Z" }, + { url = "https://files.pythonhosted.org/packages/2f/04/6ef935dc74e729932e39478e44d8cfe6a83550552eaa072b7c05f6f22488/lxml-5.4.0-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:1a42b3a19346e5601d1b8296ff6ef3d76038058f311902edd574461e9c036982", size = 4947028, upload-time = "2025-04-23T01:47:22.401Z" }, + { url = "https://files.pythonhosted.org/packages/cb/f9/c33fc8daa373ef8a7daddb53175289024512b6619bc9de36d77dca3df44b/lxml-5.4.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:4291d3c409a17febf817259cb37bc62cb7eb398bcc95c1356947e2871911ae61", size = 4834487, upload-time = "2025-04-23T01:47:25.513Z" }, + { url = "https://files.pythonhosted.org/packages/8d/30/fc92bb595bcb878311e01b418b57d13900f84c2b94f6eca9e5073ea756e6/lxml-5.4.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:4f5322cf38fe0e21c2d73901abf68e6329dc02a4994e483adbcf92b568a09a54", size = 5381688, upload-time = "2025-04-23T01:47:28.454Z" }, + { url = "https://files.pythonhosted.org/packages/43/d1/3ba7bd978ce28bba8e3da2c2e9d5ae3f8f521ad3f0ca6ea4788d086ba00d/lxml-5.4.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:0be91891bdb06ebe65122aa6bf3fc94489960cf7e03033c6f83a90863b23c58b", size = 5242043, upload-time = "2025-04-23T01:47:31.208Z" }, + { url = "https://files.pythonhosted.org/packages/ee/cd/95fa2201041a610c4d08ddaf31d43b98ecc4b1d74b1e7245b1abdab443cb/lxml-5.4.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:15a665ad90054a3d4f397bc40f73948d48e36e4c09f9bcffc7d90c87410e478a", size = 5021569, upload-time = "2025-04-23T01:47:33.805Z" }, + { url = "https://files.pythonhosted.org/packages/2d/a6/31da006fead660b9512d08d23d31e93ad3477dd47cc42e3285f143443176/lxml-5.4.0-cp313-cp313-win32.whl", hash = "sha256:d5663bc1b471c79f5c833cffbc9b87d7bf13f87e055a5c86c363ccd2348d7e82", size = 3485270, upload-time = "2025-04-23T01:47:36.133Z" }, + { url = "https://files.pythonhosted.org/packages/fc/14/c115516c62a7d2499781d2d3d7215218c0731b2c940753bf9f9b7b73924d/lxml-5.4.0-cp313-cp313-win_amd64.whl", hash = "sha256:bcb7a1096b4b6b24ce1ac24d4942ad98f983cd3810f9711bcd0293f43a9d8b9f", size = 3814606, upload-time = "2025-04-23T01:47:39.028Z" }, +] + +[[package]] +name = "mccabe" +version = "0.7.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e7/ff/0ffefdcac38932a54d2b5eed4e0ba8a408f215002cd178ad1df0f2806ff8/mccabe-0.7.0.tar.gz", hash = "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325", size = 9658, upload-time = "2022-01-24T01:14:51.113Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/27/1a/1f68f9ba0c207934b35b86a8ca3aad8395a3d6dd7921c0686e23853ff5a9/mccabe-0.7.0-py2.py3-none-any.whl", hash = "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e", size = 7350, upload-time = "2022-01-24T01:14:49.62Z" }, +] + +[[package]] +name = "more-itertools" +version = "10.7.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ce/a0/834b0cebabbfc7e311f30b46c8188790a37f89fc8d756660346fe5abfd09/more_itertools-10.7.0.tar.gz", hash = "sha256:9fddd5403be01a94b204faadcff459ec3568cf110265d3c54323e1e866ad29d3", size = 127671, upload-time = "2025-04-22T14:17:41.838Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2b/9f/7ba6f94fc1e9ac3d2b853fdff3035fb2fa5afbed898c4a72b8a020610594/more_itertools-10.7.0-py3-none-any.whl", hash = "sha256:d43980384673cb07d2f7d2d918c616b30c659c089ee23953f601d6609c67510e", size = 65278, upload-time = "2025-04-22T14:17:40.49Z" }, +] + +[[package]] +name = "mypy" +version = "1.15.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "mypy-extensions" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ce/43/d5e49a86afa64bd3839ea0d5b9c7103487007d728e1293f52525d6d5486a/mypy-1.15.0.tar.gz", hash = "sha256:404534629d51d3efea5c800ee7c42b72a6554d6c400e6a79eafe15d11341fd43", size = 3239717, upload-time = "2025-02-05T03:50:34.655Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/6a/9b/fd2e05d6ffff24d912f150b87db9e364fa8282045c875654ce7e32fffa66/mypy-1.15.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:93faf3fdb04768d44bf28693293f3904bbb555d076b781ad2530214ee53e3445", size = 10788592, upload-time = "2025-02-05T03:48:55.789Z" }, + { url = "https://files.pythonhosted.org/packages/74/37/b246d711c28a03ead1fd906bbc7106659aed7c089d55fe40dd58db812628/mypy-1.15.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:811aeccadfb730024c5d3e326b2fbe9249bb7413553f15499a4050f7c30e801d", size = 9753611, upload-time = "2025-02-05T03:48:44.581Z" }, + { url = "https://files.pythonhosted.org/packages/a6/ac/395808a92e10cfdac8003c3de9a2ab6dc7cde6c0d2a4df3df1b815ffd067/mypy-1.15.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:98b7b9b9aedb65fe628c62a6dc57f6d5088ef2dfca37903a7d9ee374d03acca5", size = 11438443, upload-time = "2025-02-05T03:49:25.514Z" }, + { url = "https://files.pythonhosted.org/packages/d2/8b/801aa06445d2de3895f59e476f38f3f8d610ef5d6908245f07d002676cbf/mypy-1.15.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c43a7682e24b4f576d93072216bf56eeff70d9140241f9edec0c104d0c515036", size = 12402541, upload-time = "2025-02-05T03:49:57.623Z" }, + { url = "https://files.pythonhosted.org/packages/c7/67/5a4268782eb77344cc613a4cf23540928e41f018a9a1ec4c6882baf20ab8/mypy-1.15.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:baefc32840a9f00babd83251560e0ae1573e2f9d1b067719479bfb0e987c6357", size = 12494348, upload-time = "2025-02-05T03:48:52.361Z" }, + { url = "https://files.pythonhosted.org/packages/83/3e/57bb447f7bbbfaabf1712d96f9df142624a386d98fb026a761532526057e/mypy-1.15.0-cp313-cp313-win_amd64.whl", hash = "sha256:b9378e2c00146c44793c98b8d5a61039a048e31f429fb0eb546d93f4b000bedf", size = 9373648, upload-time = "2025-02-05T03:49:11.395Z" }, + { url = "https://files.pythonhosted.org/packages/09/4e/a7d65c7322c510de2c409ff3828b03354a7c43f5a8ed458a7a131b41c7b9/mypy-1.15.0-py3-none-any.whl", hash = "sha256:5469affef548bd1895d86d3bf10ce2b44e33d86923c29e4d675b3e323437ea3e", size = 2221777, upload-time = "2025-02-05T03:50:08.348Z" }, +] + +[[package]] +name = "mypy-extensions" +version = "1.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a2/6e/371856a3fb9d31ca8dac321cda606860fa4548858c0cc45d9d1d4ca2628b/mypy_extensions-1.1.0.tar.gz", hash = "sha256:52e68efc3284861e772bbcd66823fde5ae21fd2fdb51c62a211403730b916558", size = 6343, upload-time = "2025-04-22T14:54:24.164Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/79/7b/2c79738432f5c924bef5071f933bcc9efd0473bac3b4aa584a6f7c1c8df8/mypy_extensions-1.1.0-py3-none-any.whl", hash = "sha256:1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505", size = 4963, upload-time = "2025-04-22T14:54:22.983Z" }, +] + +[[package]] +name = "nodeenv" +version = "1.9.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/43/16/fc88b08840de0e0a72a2f9d8c6bae36be573e475a6326ae854bcc549fc45/nodeenv-1.9.1.tar.gz", hash = "sha256:6ec12890a2dab7946721edbfbcd91f3319c6ccc9aec47be7c7e6b7011ee6645f", size = 47437, upload-time = "2024-06-04T18:44:11.171Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d2/1d/1b658dbd2b9fa9c4c9f32accbfc0205d532c8c6194dc0f2a4c0428e7128a/nodeenv-1.9.1-py2.py3-none-any.whl", hash = "sha256:ba11c9782d29c27c70ffbdda2d7415098754709be8a7056d79a737cd901155c9", size = 22314, upload-time = "2024-06-04T18:44:08.352Z" }, +] + +[[package]] +name = "pastel" +version = "0.2.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/76/f1/4594f5e0fcddb6953e5b8fe00da8c317b8b41b547e2b3ae2da7512943c62/pastel-0.2.1.tar.gz", hash = "sha256:e6581ac04e973cac858828c6202c1e1e81fee1dc7de7683f3e1ffe0bfd8a573d", size = 7555, upload-time = "2020-09-16T19:21:12.43Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/aa/18/a8444036c6dd65ba3624c63b734d3ba95ba63ace513078e1580590075d21/pastel-0.2.1-py2.py3-none-any.whl", hash = "sha256:4349225fcdf6c2bb34d483e523475de5bb04a5c10ef711263452cb37d7dd4364", size = 5955, upload-time = "2020-09-16T19:21:11.409Z" }, +] + +[[package]] +name = "platformdirs" +version = "4.3.8" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/fe/8b/3c73abc9c759ecd3f1f7ceff6685840859e8070c4d947c93fae71f6a0bf2/platformdirs-4.3.8.tar.gz", hash = "sha256:3d512d96e16bcb959a814c9f348431070822a6496326a4be0911c40b5a74c2bc", size = 21362, upload-time = "2025-05-07T22:47:42.121Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/fe/39/979e8e21520d4e47a0bbe349e2713c0aac6f3d853d0e5b34d76206c439aa/platformdirs-4.3.8-py3-none-any.whl", hash = "sha256:ff7059bb7eb1179e2685604f4aaf157cfd9535242bd23742eadc3c13542139b4", size = 18567, upload-time = "2025-05-07T22:47:40.376Z" }, +] + +[[package]] +name = "poethepoet" +version = "0.35.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pastel" }, + { name = "pyyaml" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/d6/b1/d4f4361b278fae10f6074675385ce3acf53c647f8e6eeba22c652f8ba985/poethepoet-0.35.0.tar.gz", hash = "sha256:b396ae862d7626e680bbd0985b423acf71634ce93a32d8b5f38340f44f5fbc3e", size = 66006, upload-time = "2025-06-09T12:58:18.849Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/38/08/abc2d7e2400dd8906e3208f9b88ac610f097d7ee0c7a1fa4a157b49a9e86/poethepoet-0.35.0-py3-none-any.whl", hash = "sha256:bed5ae1fd63f179dfa67aabb93fa253d79695c69667c927d8b24ff378799ea75", size = 87164, upload-time = "2025-06-09T12:58:17.084Z" }, +] + +[[package]] +name = "pre-commit" +version = "4.2.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "cfgv" }, + { name = "identify" }, + { name = "nodeenv" }, + { name = "pyyaml" }, + { name = "virtualenv" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/08/39/679ca9b26c7bb2999ff122d50faa301e49af82ca9c066ec061cfbc0c6784/pre_commit-4.2.0.tar.gz", hash = "sha256:601283b9757afd87d40c4c4a9b2b5de9637a8ea02eaff7adc2d0fb4e04841146", size = 193424, upload-time = "2025-03-18T21:35:20.987Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/88/74/a88bf1b1efeae488a0c0b7bdf71429c313722d1fc0f377537fbe554e6180/pre_commit-4.2.0-py2.py3-none-any.whl", hash = "sha256:a009ca7205f1eb497d10b845e52c838a98b6cdd2102a6c8e4540e94ee75c58bd", size = 220707, upload-time = "2025-03-18T21:35:19.343Z" }, +] + +[[package]] +name = "pycodestyle" +version = "2.13.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/04/6e/1f4a62078e4d95d82367f24e685aef3a672abfd27d1a868068fed4ed2254/pycodestyle-2.13.0.tar.gz", hash = "sha256:c8415bf09abe81d9c7f872502a6eee881fbe85d8763dd5b9924bb0a01d67efae", size = 39312, upload-time = "2025-03-29T17:33:30.669Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/07/be/b00116df1bfb3e0bb5b45e29d604799f7b91dd861637e4d448b4e09e6a3e/pycodestyle-2.13.0-py2.py3-none-any.whl", hash = "sha256:35863c5974a271c7a726ed228a14a4f6daf49df369d8c50cd9a6f58a5e143ba9", size = 31424, upload-time = "2025-03-29T17:33:29.405Z" }, +] + +[[package]] +name = "pyflakes" +version = "3.3.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/af/cc/1df338bd7ed1fa7c317081dcf29bf2f01266603b301e6858856d346a12b3/pyflakes-3.3.2.tar.gz", hash = "sha256:6dfd61d87b97fba5dcfaaf781171ac16be16453be6d816147989e7f6e6a9576b", size = 64175, upload-time = "2025-03-31T13:21:20.34Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/15/40/b293a4fa769f3b02ab9e387c707c4cbdc34f073f945de0386107d4e669e6/pyflakes-3.3.2-py2.py3-none-any.whl", hash = "sha256:5039c8339cbb1944045f4ee5466908906180f13cc99cc9949348d10f82a5c32a", size = 63164, upload-time = "2025-03-31T13:21:18.503Z" }, +] + +[[package]] +name = "python-dateutil" +version = "2.9.0.post0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "six" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/66/c0/0c8b6ad9f17a802ee498c46e004a0eb49bc148f2fd230864601a86dcf6db/python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3", size = 342432, upload-time = "2024-03-01T18:36:20.211Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427", size = 229892, upload-time = "2024-03-01T18:36:18.57Z" }, +] + +[[package]] +name = "pyyaml" +version = "6.0.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/54/ed/79a089b6be93607fa5cdaedf301d7dfb23af5f25c398d5ead2525b063e17/pyyaml-6.0.2.tar.gz", hash = "sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e", size = 130631, upload-time = "2024-08-06T20:33:50.674Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ef/e3/3af305b830494fa85d95f6d95ef7fa73f2ee1cc8ef5b495c7c3269fb835f/PyYAML-6.0.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba", size = 181309, upload-time = "2024-08-06T20:32:43.4Z" }, + { url = "https://files.pythonhosted.org/packages/45/9f/3b1c20a0b7a3200524eb0076cc027a970d320bd3a6592873c85c92a08731/PyYAML-6.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1", size = 171679, upload-time = "2024-08-06T20:32:44.801Z" }, + { url = "https://files.pythonhosted.org/packages/7c/9a/337322f27005c33bcb656c655fa78325b730324c78620e8328ae28b64d0c/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133", size = 733428, upload-time = "2024-08-06T20:32:46.432Z" }, + { url = "https://files.pythonhosted.org/packages/a3/69/864fbe19e6c18ea3cc196cbe5d392175b4cf3d5d0ac1403ec3f2d237ebb5/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484", size = 763361, upload-time = "2024-08-06T20:32:51.188Z" }, + { url = "https://files.pythonhosted.org/packages/04/24/b7721e4845c2f162d26f50521b825fb061bc0a5afcf9a386840f23ea19fa/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5", size = 759523, upload-time = "2024-08-06T20:32:53.019Z" }, + { url = "https://files.pythonhosted.org/packages/2b/b2/e3234f59ba06559c6ff63c4e10baea10e5e7df868092bf9ab40e5b9c56b6/PyYAML-6.0.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc", size = 726660, upload-time = "2024-08-06T20:32:54.708Z" }, + { url = "https://files.pythonhosted.org/packages/fe/0f/25911a9f080464c59fab9027482f822b86bf0608957a5fcc6eaac85aa515/PyYAML-6.0.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652", size = 751597, upload-time = "2024-08-06T20:32:56.985Z" }, + { url = "https://files.pythonhosted.org/packages/14/0d/e2c3b43bbce3cf6bd97c840b46088a3031085179e596d4929729d8d68270/PyYAML-6.0.2-cp313-cp313-win32.whl", hash = "sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183", size = 140527, upload-time = "2024-08-06T20:33:03.001Z" }, + { url = "https://files.pythonhosted.org/packages/fa/de/02b54f42487e3d3c6efb3f89428677074ca7bf43aae402517bc7cca949f3/PyYAML-6.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563", size = 156446, upload-time = "2024-08-06T20:33:04.33Z" }, +] + +[[package]] +name = "requests" +version = "2.32.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "certifi" }, + { name = "charset-normalizer" }, + { name = "idna" }, + { name = "urllib3" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/e1/0a/929373653770d8a0d7ea76c37de6e41f11eb07559b103b1c02cafb3f7cf8/requests-2.32.4.tar.gz", hash = "sha256:27d0316682c8a29834d3264820024b62a36942083d52caf2f14c0591336d3422", size = 135258, upload-time = "2025-06-09T16:43:07.34Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7c/e4/56027c4a6b4ae70ca9de302488c5ca95ad4a39e190093d6c1a8ace08341b/requests-2.32.4-py3-none-any.whl", hash = "sha256:27babd3cda2a6d50b30443204ee89830707d396671944c998b5975b031ac2b2c", size = 64847, upload-time = "2025-06-09T16:43:05.728Z" }, +] + +[[package]] +name = "responses" +version = "0.25.7" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pyyaml" }, + { name = "requests" }, + { name = "urllib3" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/81/7e/2345ac3299bd62bd7163216702bbc88976c099cfceba5b889f2a457727a1/responses-0.25.7.tar.gz", hash = "sha256:8ebae11405d7a5df79ab6fd54277f6f2bc29b2d002d0dd2d5c632594d1ddcedb", size = 79203, upload-time = "2025-03-11T15:36:16.624Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e4/fc/1d20b64fa90e81e4fa0a34c9b0240a6cfb1326b7e06d18a5432a9917c316/responses-0.25.7-py3-none-any.whl", hash = "sha256:92ca17416c90fe6b35921f52179bff29332076bb32694c0df02dcac2c6bc043c", size = 34732, upload-time = "2025-03-11T15:36:14.589Z" }, +] + +[[package]] +name = "setuptools" +version = "80.9.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/18/5d/3bf57dcd21979b887f014ea83c24ae194cfcd12b9e0fda66b957c69d1fca/setuptools-80.9.0.tar.gz", hash = "sha256:f36b47402ecde768dbfafc46e8e4207b4360c654f1f3bb84475f0a28628fb19c", size = 1319958, upload-time = "2025-05-27T00:56:51.443Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a3/dc/17031897dae0efacfea57dfd3a82fdd2a2aeb58e0ff71b77b87e44edc772/setuptools-80.9.0-py3-none-any.whl", hash = "sha256:062d34222ad13e0cc312a4c02d73f059e86a4acbfbdea8f8f76b28c99f306922", size = 1201486, upload-time = "2025-05-27T00:56:49.664Z" }, +] + +[[package]] +name = "six" +version = "1.17.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/94/e7/b2c673351809dca68a0e064b6af791aa332cf192da575fd474ed7d6f16a2/six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81", size = 34031, upload-time = "2024-12-04T17:35:28.174Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274", size = 11050, upload-time = "2024-12-04T17:35:26.475Z" }, +] + +[[package]] +name = "tabulate" +version = "0.9.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ec/fe/802052aecb21e3797b8f7902564ab6ea0d60ff8ca23952079064155d1ae1/tabulate-0.9.0.tar.gz", hash = "sha256:0095b12bf5966de529c0feb1fa08671671b3368eec77d7ef7ab114be2c068b3c", size = 81090, upload-time = "2022-10-06T17:21:48.54Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/40/44/4a5f08c96eb108af5cb50b41f76142f0afa346dfa99d5296fe7202a11854/tabulate-0.9.0-py3-none-any.whl", hash = "sha256:024ca478df22e9340661486f85298cff5f6dcdba14f3813e8830015b9ed1948f", size = 35252, upload-time = "2022-10-06T17:21:44.262Z" }, +] + +[[package]] +name = "toml" +version = "0.10.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/be/ba/1f744cdc819428fc6b5084ec34d9b30660f6f9daaf70eead706e3203ec3c/toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f", size = 22253, upload-time = "2020-11-01T01:40:22.204Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/44/6f/7120676b6d73228c96e17f1f794d8ab046fc910d781c8d151120c3f1569e/toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b", size = 16588, upload-time = "2020-11-01T01:40:20.672Z" }, +] + +[[package]] +name = "types-click" +version = "7.1.8" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/00/ff/0e6a56108d45c80c61cdd4743312d0304d8192482aea4cce96c554aaa90d/types-click-7.1.8.tar.gz", hash = "sha256:b6604968be6401dc516311ca50708a0a28baa7a0cb840efd7412f0dbbff4e092", size = 10015, upload-time = "2021-11-23T12:28:01.701Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ee/ad/607454a5f991c5b3e14693a7113926758f889138371058a5f72f567fa131/types_click-7.1.8-py3-none-any.whl", hash = "sha256:8cb030a669e2e927461be9827375f83c16b8178c365852c060a34e24871e7e81", size = 12929, upload-time = "2021-11-23T12:27:59.493Z" }, +] + +[[package]] +name = "types-pkg-resources" +version = "0.1.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a4/5c/5e04590a4b9749a33a6b8b93784270a65f8ebdec55a0b7742bb30e2075bb/types-pkg_resources-0.1.3.tar.gz", hash = "sha256:834a9b8d3dbea343562fd99d5d3359a726f6bf9d3733bccd2b4f3096fbab9dae", size = 4204, upload-time = "2021-06-17T15:01:28.046Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e9/97/a24ffd614ac2962dabbd599afbed00adf6464604a53b96b5f48301518a5f/types_pkg_resources-0.1.3-py2.py3-none-any.whl", hash = "sha256:0cb9972cee992249f93fff1a491bf2dc3ce674e5a1926e27d4f0866f7d9b6d9c", size = 4810, upload-time = "2021-06-17T15:01:26.789Z" }, +] + +[[package]] +name = "types-python-dateutil" +version = "2.9.0.20250516" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ef/88/d65ed807393285204ab6e2801e5d11fbbea811adcaa979a2ed3b67a5ef41/types_python_dateutil-2.9.0.20250516.tar.gz", hash = "sha256:13e80d6c9c47df23ad773d54b2826bd52dbbb41be87c3f339381c1700ad21ee5", size = 13943, upload-time = "2025-05-16T03:06:58.385Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c5/3f/b0e8db149896005adc938a1e7f371d6d7e9eca4053a29b108978ed15e0c2/types_python_dateutil-2.9.0.20250516-py3-none-any.whl", hash = "sha256:2b2b3f57f9c6a61fba26a9c0ffb9ea5681c9b83e69cd897c6b5f668d9c0cab93", size = 14356, upload-time = "2025-05-16T03:06:57.249Z" }, +] + +[[package]] +name = "types-requests" +version = "2.32.4.20250611" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "urllib3" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/6d/7f/73b3a04a53b0fd2a911d4ec517940ecd6600630b559e4505cc7b68beb5a0/types_requests-2.32.4.20250611.tar.gz", hash = "sha256:741c8777ed6425830bf51e54d6abe245f79b4dcb9019f1622b773463946bf826", size = 23118, upload-time = "2025-06-11T03:11:41.272Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3d/ea/0be9258c5a4fa1ba2300111aa5a0767ee6d18eb3fd20e91616c12082284d/types_requests-2.32.4.20250611-py3-none-any.whl", hash = "sha256:ad2fe5d3b0cb3c2c902c8815a70e7fb2302c4b8c1f77bdcd738192cdb3878072", size = 20643, upload-time = "2025-06-11T03:11:40.186Z" }, +] + +[[package]] +name = "types-tabulate" +version = "0.9.0.20241207" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/3f/43/16030404a327e4ff8c692f2273854019ed36718667b2993609dc37d14dd4/types_tabulate-0.9.0.20241207.tar.gz", hash = "sha256:ac1ac174750c0a385dfd248edc6279fa328aaf4ea317915ab879a2ec47833230", size = 8195, upload-time = "2024-12-07T02:54:42.554Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5e/86/a9ebfd509cbe74471106dffed320e208c72537f9aeb0a55eaa6b1b5e4d17/types_tabulate-0.9.0.20241207-py3-none-any.whl", hash = "sha256:b8dad1343c2a8ba5861c5441370c3e35908edd234ff036d4298708a1d4cf8a85", size = 8307, upload-time = "2024-12-07T02:54:41.031Z" }, +] + +[[package]] +name = "typing-extensions" +version = "4.14.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d1/bc/51647cd02527e87d05cb083ccc402f93e441606ff1f01739a62c8ad09ba5/typing_extensions-4.14.0.tar.gz", hash = "sha256:8676b788e32f02ab42d9e7c61324048ae4c6d844a399eebace3d4979d75ceef4", size = 107423, upload-time = "2025-06-02T14:52:11.399Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/69/e0/552843e0d356fbb5256d21449fa957fa4eff3bbc135a74a691ee70c7c5da/typing_extensions-4.14.0-py3-none-any.whl", hash = "sha256:a1514509136dd0b477638fc68d6a91497af5076466ad0fa6c338e44e359944af", size = 43839, upload-time = "2025-06-02T14:52:10.026Z" }, +] + +[[package]] +name = "unittest-xml-reporting" +version = "3.2.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "lxml" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ed/40/3bf1afc96e93c7322520981ac4593cbb29daa21b48d32746f05ab5563dca/unittest-xml-reporting-3.2.0.tar.gz", hash = "sha256:edd8d3170b40c3a81b8cf910f46c6a304ae2847ec01036d02e9c0f9b85762d28", size = 18002, upload-time = "2022-01-20T19:09:55.76Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/39/88/f6e9b87428584a3c62cac768185c438ca6d561367a5d267b293259d76075/unittest_xml_reporting-3.2.0-py2.py3-none-any.whl", hash = "sha256:f3d7402e5b3ac72a5ee3149278339db1a8f932ee405f48bcb9c681372f2717d5", size = 20936, upload-time = "2022-01-20T19:09:53.824Z" }, +] + +[[package]] +name = "urllib3" +version = "2.5.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/15/22/9ee70a2574a4f4599c47dd506532914ce044817c7752a79b6a51286319bc/urllib3-2.5.0.tar.gz", hash = "sha256:3fc47733c7e419d4bc3f6b3dc2b4f890bb743906a30d56ba4a5bfa4bbff92760", size = 393185, upload-time = "2025-06-18T14:07:41.644Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a7/c2/fe1e52489ae3122415c51f387e221dd0773709bad6c6cdaa599e8a2c5185/urllib3-2.5.0-py3-none-any.whl", hash = "sha256:e6b01673c0fa6a13e374b50871808eb3bf7046c4b125b216f6bf1cc604cff0dc", size = 129795, upload-time = "2025-06-18T14:07:40.39Z" }, +] + +[[package]] +name = "virtualenv" +version = "20.31.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "distlib" }, + { name = "filelock" }, + { name = "platformdirs" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/56/2c/444f465fb2c65f40c3a104fd0c495184c4f2336d65baf398e3c75d72ea94/virtualenv-20.31.2.tar.gz", hash = "sha256:e10c0a9d02835e592521be48b332b6caee6887f332c111aa79a09b9e79efc2af", size = 6076316, upload-time = "2025-05-08T17:58:23.811Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f3/40/b1c265d4b2b62b58576588510fc4d1fe60a86319c8de99fd8e9fec617d2c/virtualenv-20.31.2-py3-none-any.whl", hash = "sha256:36efd0d9650ee985f0cad72065001e66d49a6f24eb44d98980f630686243cf11", size = 6057982, upload-time = "2025-05-08T17:58:21.15Z" }, +] From 771c19a1974f68541084c0c2d602c79be140df4d Mon Sep 17 00:00:00 2001 From: ninjinkun Date: Thu, 19 Jun 2025 11:44:08 +0900 Subject: [PATCH 03/22] refactor: rename GA files --- .../workflows/{python-publish.yml => publish.yml} | 9 +++------ .github/workflows/{python-package.yml => test.yml} | 13 ++++++------- 2 files changed, 9 insertions(+), 13 deletions(-) rename .github/workflows/{python-publish.yml => publish.yml} (92%) rename .github/workflows/{python-package.yml => test.yml} (87%) diff --git a/.github/workflows/python-publish.yml b/.github/workflows/publish.yml similarity index 92% rename from .github/workflows/python-publish.yml rename to .github/workflows/publish.yml index ffe23603a..513bee5d2 100644 --- a/.github/workflows/python-publish.yml +++ b/.github/workflows/publish.yml @@ -1,7 +1,7 @@ -# This workflows will upload a Python Package -# For more information see: https://github.com/marketplace/actions/pypi-publish +# Publish workflow for the Launchable CLI +# Builds and publishes packages to PyPI and Docker Hub -name: Upload Python Package +name: Publish on: workflow_dispatch: @@ -41,9 +41,6 @@ jobs: - name: Install uv uses: astral-sh/setup-uv@v3 - - name: Set up Python - run: uv python install 3.13 - - name: Build package run: uv build # actual publish diff --git a/.github/workflows/python-package.yml b/.github/workflows/test.yml similarity index 87% rename from .github/workflows/python-package.yml rename to .github/workflows/test.yml index 993d08217..1eb6ec5d5 100644 --- a/.github/workflows/python-package.yml +++ b/.github/workflows/test.yml @@ -1,7 +1,7 @@ -# This workflow will install Python dependencies, run tests and lint with a variety of Python versions -# For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions +# Test workflow for the Launchable CLI +# Runs tests, linting, type checking, and build verification -name: Python package +name: Test on: workflow_dispatch: @@ -54,10 +54,9 @@ jobs: - name: Install dependencies run: uv sync --dev - - name: Build - run: | - uv pip list - uv run poe build + + - name: Test package build + run: uv build - name: Type check run: uv run poe type From 6353ba62ef5c7bc9305986496172ca97cb9df0ac Mon Sep 17 00:00:00 2001 From: ninjinkun Date: Thu, 19 Jun 2025 11:46:14 +0900 Subject: [PATCH 04/22] refactor: use uv publish --- .github/workflows/publish.yml | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 513bee5d2..22b0f1b80 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -43,12 +43,8 @@ jobs: - name: Build package run: uv build - # actual publish - name: Publish to PyPI - uses: pypa/gh-action-pypi-publish@76f52bc884231f62b9a034ebfe128415bbaabdfc # v1.12.4 - with: - user: __token__ - password: ${{ secrets.PYPI_API_TOKEN }} + run: uv publish --token ${{ secrets.PYPI_API_TOKEN }} - name: Actions for Discord uses: Ilshidur/action-discord@0.3.2 env: From 790d3c2d61cebd021fc50632c434046cc3366af1 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 19 Jun 2025 02:49:58 +0000 Subject: [PATCH 05/22] [tagpr] prepare for the next release From 8a83f5422f3bdd7b0d1f9dbc57380691a45f48be Mon Sep 17 00:00:00 2001 From: Satoshi Asano Date: Thu, 19 Jun 2025 11:58:40 +0900 Subject: [PATCH 06/22] Update pyproject.toml Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- pyproject.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 618978f45..b631bc9e7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -17,7 +17,6 @@ dependencies = [ "requests>=2.25", "urllib3>=1.26", "junitparser>=2.0.0", - "setuptools", "more-itertools>=7.1.0", "python-dateutil", "tabulate", From 3534cae63ec81c4c5b6f617ef25492046be4c318 Mon Sep 17 00:00:00 2001 From: ninjinkun Date: Thu, 19 Jun 2025 12:03:38 +0900 Subject: [PATCH 07/22] refactor: remove an unused option --- pyproject.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index b631bc9e7..46743b7e8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -49,7 +49,6 @@ dev-dependencies = [ ] [tool.poe.tasks] -build = "python setup.py sdist bdist_wheel" format = "/bin/bash -c 'isort -l 130 --balanced launchable/*.py tests/*.py && autopep8 --in-place --recursive --aggressive --experimental --max-line-length=130 --verbose launchable/ tests/'" lint = "flake8 --count --ignore=C901,E741,F401 --show-source --max-line-length=130 --statistics launchable/ tests/" lint-warn = "flake8 --count --exit-zero --max-complexity=15 --max-line-length=130 --statistics launchable/ tests/" From 3ffe950865caddda659687050b80376e7da7927a Mon Sep 17 00:00:00 2001 From: ninjinkun Date: Thu, 19 Jun 2025 12:12:21 +0900 Subject: [PATCH 08/22] refactor: update dependencies --- launchable/version.py | 8 ++++---- pyproject.toml | 8 ++++---- uv.lock | 19 ++++--------------- 3 files changed, 12 insertions(+), 23 deletions(-) diff --git a/launchable/version.py b/launchable/version.py index 61506020f..7920e033e 100644 --- a/launchable/version.py +++ b/launchable/version.py @@ -1,7 +1,7 @@ -from pkg_resources import DistributionNotFound, get_distribution +from importlib.metadata import PackageNotFoundError, version try: - __version__ = get_distribution("launchable").version -except DistributionNotFound: + __version__ = version("launchable") +except PackageNotFoundError: # package is not installed - pass + __version__ = "unknown" diff --git a/pyproject.toml b/pyproject.toml index 46743b7e8..bfc4313c3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -13,7 +13,7 @@ classifiers = [ "Operating System :: OS Independent", ] dependencies = [ - "click>=8.1,<8.2", + "click>=8.1", "requests>=2.25", "urllib3>=1.26", "junitparser>=2.0.0", @@ -33,13 +33,13 @@ launchable = "launchable.__main__:main" [tool.uv] dev-dependencies = [ "flake8", - "autopep8<=1.7.0", + "autopep8", "isort", - "mypy<1.16.0", + "mypy", "pre-commit", "responses", "types-click", - "types-pkg_resources==0.1.3", + "types-pkg_resources", "types-python-dateutil", "types-requests", "types-tabulate", diff --git a/uv.lock b/uv.lock index 164060970..3a2bb2840 100644 --- a/uv.lock +++ b/uv.lock @@ -153,7 +153,6 @@ dependencies = [ { name = "more-itertools" }, { name = "python-dateutil" }, { name = "requests" }, - { name = "setuptools" }, { name = "tabulate" }, { name = "urllib3" }, ] @@ -178,28 +177,27 @@ dev = [ [package.metadata] requires-dist = [ - { name = "click", specifier = ">=8.1,<8.2" }, + { name = "click", specifier = ">=8.1" }, { name = "junitparser", specifier = ">=2.0.0" }, { name = "more-itertools", specifier = ">=7.1.0" }, { name = "python-dateutil" }, { name = "requests", specifier = ">=2.25" }, - { name = "setuptools" }, { name = "tabulate" }, { name = "urllib3", specifier = ">=1.26" }, ] [package.metadata.requires-dev] dev = [ - { name = "autopep8", specifier = "<=1.7.0" }, + { name = "autopep8" }, { name = "flake8" }, { name = "isort" }, { name = "lxml" }, - { name = "mypy", specifier = "<1.16.0" }, + { name = "mypy" }, { name = "poethepoet" }, { name = "pre-commit" }, { name = "responses" }, { name = "types-click" }, - { name = "types-pkg-resources", specifier = "==0.1.3" }, + { name = "types-pkg-resources" }, { name = "types-python-dateutil" }, { name = "types-requests" }, { name = "types-tabulate" }, @@ -409,15 +407,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/e4/fc/1d20b64fa90e81e4fa0a34c9b0240a6cfb1326b7e06d18a5432a9917c316/responses-0.25.7-py3-none-any.whl", hash = "sha256:92ca17416c90fe6b35921f52179bff29332076bb32694c0df02dcac2c6bc043c", size = 34732, upload-time = "2025-03-11T15:36:14.589Z" }, ] -[[package]] -name = "setuptools" -version = "80.9.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/18/5d/3bf57dcd21979b887f014ea83c24ae194cfcd12b9e0fda66b957c69d1fca/setuptools-80.9.0.tar.gz", hash = "sha256:f36b47402ecde768dbfafc46e8e4207b4360c654f1f3bb84475f0a28628fb19c", size = 1319958, upload-time = "2025-05-27T00:56:51.443Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/a3/dc/17031897dae0efacfea57dfd3a82fdd2a2aeb58e0ff71b77b87e44edc772/setuptools-80.9.0-py3-none-any.whl", hash = "sha256:062d34222ad13e0cc312a4c02d73f059e86a4acbfbdea8f8f76b28c99f306922", size = 1201486, upload-time = "2025-05-27T00:56:49.664Z" }, -] - [[package]] name = "six" version = "1.17.0" From 76e8312ebbcb5833b964b4af62a5195397eb9b12 Mon Sep 17 00:00:00 2001 From: Konboi Date: Thu, 19 Jun 2025 14:24:13 +0900 Subject: [PATCH 09/22] support groovy file in the maven profile --- launchable/test_runners/maven.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/launchable/test_runners/maven.py b/launchable/test_runners/maven.py index e152b2a85..deb87ccf5 100644 --- a/launchable/test_runners/maven.py +++ b/launchable/test_runners/maven.py @@ -22,6 +22,7 @@ # file enumeration and class file enumeration '**/Test*.*', '**/*Test.*', + '**/*Spec.*', '**/*Tests.*', '**/*TestCase.*' ]] @@ -33,7 +34,7 @@ def is_file(f: str) -> bool: - if not (f.endswith('.java') or f.endswith(".scala") or f.endswith(".kt") or f.endswith(".class")): + if not (f.endswith('.java') or f.endswith(".scala") or f.endswith(".kt") or f.endswith(".class") or f.endswith(".groovy")): return False for p in excludes: if p.fullmatch(f): From 921a92c5778eac5fd8f117032768ddf56dc4a9c6 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 19 Jun 2025 07:21:37 +0000 Subject: [PATCH 10/22] [tagpr] prepare for the next release From b13dd73f038cf6a10dd448782f7fcbaccf22bb5b Mon Sep 17 00:00:00 2001 From: Konboi Date: Mon, 23 Jun 2025 18:05:44 +0900 Subject: [PATCH 11/22] install latest version --- setup.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.cfg b/setup.cfg index b028d942b..fb438442e 100644 --- a/setup.cfg +++ b/setup.cfg @@ -19,7 +19,7 @@ install_requires = click>=8.1,<8.2;python_version>'3.6' requests>=2.25;python_version>='3.6' urllib3>=1.26 - junitparser>=2.0.0 + junitparser>=4.0.0 setuptools more_itertools>=7.1.0;python_version>='3.6' python-dateutil From a1ec8e63f72417da672ebd0fb219a2acb220ce36 Mon Sep 17 00:00:00 2001 From: Konboi Date: Mon, 23 Jun 2025 18:09:03 +0900 Subject: [PATCH 12/22] from junitparser v4.0.0 returns JUnitXml instead of testsuite --- launchable/test_runners/robot.py | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/launchable/test_runners/robot.py b/launchable/test_runners/robot.py index 3b3bf926c..81f7f6efc 100644 --- a/launchable/test_runners/robot.py +++ b/launchable/test_runners/robot.py @@ -80,13 +80,14 @@ def record_tests(client, reports): @launchable.subset def subset(client, reports): for r in reports: - suite = JUnitXml.fromfile(r, parse_func) - - for case in suite: - cls_name = case._elem.attrib.get("classname") - name = case._elem.attrib.get('name') - if cls_name != '' and name != '': - client.test_path([{'type': 'class', 'name': cls_name}, {'type': 'testcase', 'name': name}]) + xml = JUnitXml.fromfile(r, parse_func) + + for suite in xml: + for case in suite: + cls_name = case._elem.attrib.get("classname") + name = case._elem.attrib.get('name') + if cls_name != '' and name != '': + client.test_path([{'type': 'class', 'name': cls_name}, {'type': 'testcase', 'name': name}]) client.formatter = robot_formatter client.separator = " " From 70042cf23a0314d0b2fc4a58f9e96cb5bb12b52a Mon Sep 17 00:00:00 2001 From: Naoto Ono Date: Fri, 13 Jun 2025 10:59:54 +0900 Subject: [PATCH 13/22] [LCHIB-612] Add a workaround for handling timezone abbreviations in dateutil --- launchable/commands/record/case_event.py | 6 ++++-- launchable/utils/common_tz.py | 12 ++++++++++++ 2 files changed, 16 insertions(+), 2 deletions(-) create mode 100644 launchable/utils/common_tz.py diff --git a/launchable/commands/record/case_event.py b/launchable/commands/record/case_event.py index 823ad51df..4664e8e4a 100644 --- a/launchable/commands/record/case_event.py +++ b/launchable/commands/record/case_event.py @@ -4,7 +4,9 @@ import dateutil.parser from dateutil.tz import tzlocal -from junitparser import Error, Failure, IntAttr, Skipped, TestCase, TestSuite # type: ignore +from junitparser import Error, Failure, IntAttr, Skipped, TestCase, TestSuite + +from launchable.utils.common_tz import COMMON_TIMEZONES # type: ignore from ...testpath import FilePathNormalizer, TestPath @@ -157,7 +159,7 @@ def _timestamp(ts: Optional[str] = None): if ts is None: return datetime.datetime.now(datetime.timezone.utc).isoformat() try: - date = dateutil.parser.parse(ts) + date = dateutil.parser.parse(timestr=ts, tzinfos=COMMON_TIMEZONES) if date.tzinfo is None: return date.replace(tzinfo=tzlocal()).isoformat() return date.isoformat() diff --git a/launchable/utils/common_tz.py b/launchable/utils/common_tz.py new file mode 100644 index 000000000..4984d1438 --- /dev/null +++ b/launchable/utils/common_tz.py @@ -0,0 +1,12 @@ +from dateutil.tz import gettz + +# The dateutil library does not recognize timezone abbreviations (like "PDT" or "JST") by default. +# To handle these, we manually map common abbreviations to their corresponding timezones. +# See: https://github.com/dateutil/dateutil/issues/932 +COMMON_TIMEZONES = { + "UTC": gettz("UTC"), + # https://time.now/timezones/pdt/ + "PDT": gettz("America/Los_Angeles"), + # https://time.now/timezones/jst/ + "JST": gettz("Asia/Tokyo"), +} From 842f2353127c4de33f6c6466cca97d40260e07fa Mon Sep 17 00:00:00 2001 From: Naoto Ono Date: Mon, 23 Jun 2025 11:22:07 +0900 Subject: [PATCH 14/22] Add new tests for checking the behavior --- tests/commands/record/test_case_event.py | 35 ++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 tests/commands/record/test_case_event.py diff --git a/tests/commands/record/test_case_event.py b/tests/commands/record/test_case_event.py new file mode 100644 index 000000000..873ca1879 --- /dev/null +++ b/tests/commands/record/test_case_event.py @@ -0,0 +1,35 @@ + +import unittest +from io import StringIO +from unittest import mock + +from launchable.commands.record.case_event import CaseEvent + +UNKNOWN_TIMEZONE_WARNING = "UnknownTimezoneWarning" + + +class TestCaseEventTimestamp(unittest.TestCase): + def test_timestamp_with_known_abbreviation(self): + # Use a known abbreviation from COMMON_TIMEZONES + ts = "2024-06-23T12:34:56.789 PDT" # PDT is in COMMON_TIMEZONES + with mock.patch('sys.stderr', new=StringIO()) as stderr: + result = CaseEvent.create( + test_path=[], duration_secs=1.0, status=CaseEvent.TEST_PASSED, timestamp=ts + ) + # Should parse to ISO format with correct offset + self.assertTrue(result["createdAt"].startswith("2024-06-23T12:34:56.789")) + self.assertIn("-07:00", result["createdAt"]) + # Should NOT output a warning to stderr + self.assertNotIn(UNKNOWN_TIMEZONE_WARNING, stderr.getvalue()) + + def test_timestamp_with_unknown_abbreviation(self): + # Use an unknown abbreviation + ts = "2024-06-23T12:34:56.789 XYZ" # XYZ is not in COMMON_TIMEZONES + with mock.patch('sys.stderr', new=StringIO()) as stderr: + result = CaseEvent.create( + test_path=[], duration_secs=1.0, status=CaseEvent.TEST_PASSED, timestamp=ts + ) + # Should output a warning to stderr + self.assertIn(UNKNOWN_TIMEZONE_WARNING, stderr.getvalue()) + # The createdAt may still start with the input timestamp, but should not have a timezone offset + self.assertTrue(result["createdAt"].startswith("2024-06-23T12:34:56.789")) From bc99065c8d722a6e544e49c04a575ca3234e1cd3 Mon Sep 17 00:00:00 2001 From: Naoto Ono Date: Wed, 25 Jun 2025 11:03:06 +0900 Subject: [PATCH 15/22] Use assertEqual instead of assertTrue and assertIn --- tests/commands/record/test_case_event.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/commands/record/test_case_event.py b/tests/commands/record/test_case_event.py index 873ca1879..4246e635f 100644 --- a/tests/commands/record/test_case_event.py +++ b/tests/commands/record/test_case_event.py @@ -17,8 +17,7 @@ def test_timestamp_with_known_abbreviation(self): test_path=[], duration_secs=1.0, status=CaseEvent.TEST_PASSED, timestamp=ts ) # Should parse to ISO format with correct offset - self.assertTrue(result["createdAt"].startswith("2024-06-23T12:34:56.789")) - self.assertIn("-07:00", result["createdAt"]) + self.assertEqual(result["createdAt"], "2024-06-23T12:34:56.789000-07:00") # Should NOT output a warning to stderr self.assertNotIn(UNKNOWN_TIMEZONE_WARNING, stderr.getvalue()) From 7fc8428a6b3ba99a9a9b74b2ea58f942d6d9c051 Mon Sep 17 00:00:00 2001 From: Naoto Ono Date: Wed, 25 Jun 2025 11:07:33 +0900 Subject: [PATCH 16/22] Add comment --- tests/commands/record/test_case_event.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/commands/record/test_case_event.py b/tests/commands/record/test_case_event.py index 4246e635f..3af311ddd 100644 --- a/tests/commands/record/test_case_event.py +++ b/tests/commands/record/test_case_event.py @@ -1,4 +1,3 @@ - import unittest from io import StringIO from unittest import mock @@ -31,4 +30,8 @@ def test_timestamp_with_unknown_abbreviation(self): # Should output a warning to stderr self.assertIn(UNKNOWN_TIMEZONE_WARNING, stderr.getvalue()) # The createdAt may still start with the input timestamp, but should not have a timezone offset + # We check that the prefix matches the input timestamp because + # `dateutil.parser` will use the system's default timezone if it + # encounters an unknown timezone abbreviation (e.g., 'XYZ'), resulting in + # a timestamp like '2024-06-23T12:34:56.789000+09:00'. self.assertTrue(result["createdAt"].startswith("2024-06-23T12:34:56.789")) From 120a19adbc3bdb91cbb652e83ec9d567db606340 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 25 Jun 2025 02:17:35 +0000 Subject: [PATCH 17/22] [tagpr] prepare for the next release From 742fbae03eeef8bbd3e4a8314b9a4086b034a158 Mon Sep 17 00:00:00 2001 From: ninjinkun Date: Wed, 25 Jun 2025 11:29:50 +0900 Subject: [PATCH 18/22] fix: specify the uv commit hash --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 1eb6ec5d5..7d310ece6 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -41,7 +41,7 @@ jobs: fetch-depth: 0 - name: Install uv - uses: astral-sh/setup-uv@v3 + uses: astral-sh/setup-uv@caf0cab7a618c569241d31dcd442f54681755d39 # v3 with: enable-cache: true cache-dependency-glob: "uv.lock" From 5b56f0dd3969f82b344f8795dcd0fc797998c78c Mon Sep 17 00:00:00 2001 From: ninjinkun Date: Wed, 25 Jun 2025 11:49:18 +0900 Subject: [PATCH 19/22] refactor: use .python-version --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 7d310ece6..27e3a8e4e 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -75,7 +75,7 @@ jobs: # Tell Launchable about the build you are producing and testing launchable record build --name ${GITHUB_RUN_ID} - launchable record session --build ${GITHUB_RUN_ID} --flavor os=${{ matrix.os }} --flavor python=3.13 > session.txt + launchable record session --build ${GITHUB_RUN_ID} --flavor os=${{ matrix.os }} --flavor python=$(cat .python-version) > session.txt # Find 25% of the relevant tests to run for this change find tests -name test_*.py | grep -v tests/data | launchable subset --target 25% --session $(cat session.txt) --rest launchable-remainder.txt file > subset.txt From cbc377e537286372e71510db87db71c7c5e227c3 Mon Sep 17 00:00:00 2001 From: ninjinkun Date: Wed, 25 Jun 2025 12:02:20 +0900 Subject: [PATCH 20/22] feature: update e2e.yml --- .github/workflows/e2e.yml | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index aa43036fa..d00a7027c 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -2,7 +2,7 @@ name: e2e on: push: - branches: [main] + branches: [main, smart-tests] # smart-tests branch temporarily added for Smart Tests CLI development workflow_dispatch: @@ -16,30 +16,26 @@ env: jobs: tests: runs-on: ubuntu-22.04 - strategy: - matrix: - python-version: [3.7, 3.8, 3.9, "3.10"] steps: - - uses: actions/checkout@v4 - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 with: repository: launchableinc/examples path: examples - name: Set up JDK 1.8 - uses: actions/setup-java@v4 + uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4 with: java-version: 8 distribution: 'temurin' - - uses: actions/setup-go@v5 + - uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5 with: go-version: 1.24 - - uses: actions/setup-python@v5 + - name: Install uv + uses: astral-sh/setup-uv@caf0cab7a618c569241d31dcd442f54681755d39 # v3 with: - python-version: ${{ matrix.python-version }} + enable-cache: true - name: Install dependencies - run: | - python -m pip install --upgrade pip - pip install . + run: uv sync --dev && uv pip install . # bazel - name: Install Bazelisk run: | From 5ed3ad38df7ae371cfad747c3bf4d11b10dfb3b2 Mon Sep 17 00:00:00 2001 From: Satoshi Asano Date: Thu, 26 Jun 2025 10:25:28 +0900 Subject: [PATCH 21/22] Update .github/workflows/e2e.yml Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .github/workflows/e2e.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index d00a7027c..1e867f78f 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -17,7 +17,6 @@ jobs: tests: runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 with: repository: launchableinc/examples From 49f547e44995fa50706027999b346e935dcf021b Mon Sep 17 00:00:00 2001 From: ninjinkun Date: Fri, 27 Jun 2025 09:32:18 +0900 Subject: [PATCH 22/22] refactor: use safer PyPI token variable name MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change PYPI_API_TOKEN to SMART_TESTS_PYPI_API_TOKEN to prevent accidental publishing during development on feature branches. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- .github/workflows/publish.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 22b0f1b80..52c6a7673 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -44,7 +44,7 @@ jobs: - name: Build package run: uv build - name: Publish to PyPI - run: uv publish --token ${{ secrets.PYPI_API_TOKEN }} + run: uv publish --token ${{ secrets.SMART_TESTS_PYPI_API_TOKEN }} - name: Actions for Discord uses: Ilshidur/action-discord@0.3.2 env: