Skip to content

Commit 8a69f09

Browse files
authored
Merge pull request #17 from eggplants/test
Add workflows for testing / linting
2 parents 0c26048 + 51f7694 commit 8a69f09

File tree

12 files changed

+270
-25
lines changed

12 files changed

+270
-25
lines changed

.github/dependabot.yml

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
version: 2
2+
updates:
3+
- package-ecosystem: pip
4+
directory: /
5+
schedule:
6+
interval: monthly
7+
groups:
8+
dependencies:
9+
dependency-type: production
10+
dev-dependencies:
11+
dependency-type: development
12+
- package-ecosystem: github-actions
13+
directory: /
14+
schedule:
15+
interval: monthly

.github/workflows/lint.yaml

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
name: Lint
2+
3+
on:
4+
push:
5+
branches:
6+
- master
7+
pull_request:
8+
workflow_dispatch:
9+
10+
jobs:
11+
test:
12+
runs-on: ubuntu-latest
13+
strategy:
14+
fail-fast: true
15+
steps:
16+
- uses: actions/checkout@v4
17+
- uses: actions/setup-python@v5
18+
with:
19+
python-version: 3.x
20+
- uses: pre-commit/[email protected]
21+
- uses: pre-commit-ci/[email protected]
22+
if: always()
23+
with:
24+
msg: Apply code formatting with pre-commit

.github/workflows/publish.yaml

+3-3
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ name: Release Package
55
# secrets.TESTPYPI_API_TOKEN (See: https://test.pypi.org/help/#apitoken)
66

77
on:
8-
schedule:
9-
- cron: '0 0 * * *'
8+
# schedule:
9+
# - cron: 0 0 * * *
1010
workflow_dispatch:
1111

1212
jobs:
@@ -27,4 +27,4 @@ jobs:
2727
poetry config pypi-token.testpypi '${{ secrets.TESTPYPI_API_TOKEN }}'
2828
poetry config pypi-token.pypi '${{ secrets.PYPI_API_TOKEN }}'
2929
- name: Publish package
30-
run: python publish.py
30+
run: poetry run task publish

.github/workflows/test.yaml

+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
name: Test
2+
3+
on:
4+
push:
5+
branches:
6+
- master
7+
pull_request:
8+
workflow_dispatch:
9+
10+
jobs:
11+
test:
12+
runs-on: ${{ matrix.os }}
13+
strategy:
14+
fail-fast: false
15+
matrix:
16+
os:
17+
- ubuntu-latest
18+
- windows-latest
19+
- macos-latest
20+
python-version:
21+
- '3.9'
22+
- '3.13'
23+
steps:
24+
- uses: actions/checkout@v4
25+
- uses: actions/setup-java@v4
26+
with:
27+
distribution: temurin
28+
java-version: '21'
29+
- name: Install poetry
30+
run: pipx install poetry
31+
- uses: actions/setup-python@v5
32+
with:
33+
python-version: ${{ matrix.python-version }}
34+
cache: poetry
35+
- name: Setup
36+
shell: bash
37+
run: |
38+
poetry install --no-interaction
39+
export DOWNLOAD_LATEST_ONLY=1
40+
poetry run task publish
41+
- name: Test
42+
run: |
43+
poetry run task test

DEVELOPMENT.md

+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
# How to develop
2+
3+
## Requirement
4+
5+
- `python>=3.9`
6+
- `java`
7+
8+
## Setup
9+
10+
```bash
11+
pip install pipx
12+
pipx install poetry
13+
14+
poetry install
15+
poetry run pre-commit install
16+
```
17+
18+
## Activate virtual environment (venv) for development
19+
20+
```bash
21+
poetry shell
22+
```
23+
24+
## Lint
25+
26+
```bash
27+
# in venv:
28+
task lint
29+
```
30+
31+
## Fetch latest jar file
32+
33+
```bash
34+
# in venv:
35+
task download-latest-jar
36+
```
37+
38+
## Run tests for all unpublished versions without publishing
39+
40+
```bash
41+
# in venv:
42+
task test-unpublished-versions
43+
```
44+
45+
## Publish all unpublished versuibs to PyPI (for CI)
46+
47+
```bash
48+
# in venv:
49+
task publish
50+
```

README.md

+4
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@
44
<https://img.shields.io/badge/Slack-Join%20the%20chat%20room-orange>
55
)](
66
<https://join.slack.com/t/openapi-generator/shared_invite/zt-12jxxd7p2-XUeQM~4pzsU9x~eGLQqX2g>
7+
) [![PyPI version](
8+
<https://badge.fury.io/py/openapi-generator-cli.svg>
9+
)](
10+
<https://badge.fury.io/py/openapi-generator-cli>
711
) [![Code style: black](
812
<https://img.shields.io/badge/code%20style-black-000000.svg>
913
)](

openapi_generator_cli/__init__.py

+18-3
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
"""A Python wrapper for the OpenAPI Generator CLI."""
2+
13
from __future__ import annotations
24

35
import importlib.resources
@@ -6,7 +8,19 @@
68
import sys
79

810

9-
def run(args: list[str] | None = None) -> None:
11+
def run(args: list[str] | None = None) -> subprocess.CompletedProcess[bytes]:
12+
"""Run the OpenAPI Generator CLI with the given arguments.
13+
14+
Args:
15+
args (list[str], optional):
16+
The list of arguments to pass to the Open
17+
API Generator CLI. If not provided, the CLI will
18+
be run without any arguments.
19+
20+
Returns:
21+
subprocess.CompletedProcess[bytes]: The result of running the OpenAPI Generator CLI.
22+
23+
"""
1024
arguments = ["java"]
1125

1226
java_opts = os.getenv("JAVA_OPTS")
@@ -18,13 +32,14 @@ def run(args: list[str] | None = None) -> None:
1832
jar_path = importlib.resources.files("openapi_generator_cli") / "openapi-generator.jar"
1933
arguments.append(str(jar_path))
2034

21-
if args and type(args) == list:
35+
if args and isinstance(args, list):
2236
arguments.extend(args)
2337

24-
subprocess.call(arguments) # noqa: S603
38+
return subprocess.run(arguments, check=False) # noqa: S603
2539

2640

2741
def cli() -> None:
42+
"""Run the OpenAPI Generator CLI with the arguments provided on the command line."""
2843
args = []
2944
if len(sys.argv) > 1:
3045
args = sys.argv[1:]

poetry.lock

+16-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

publish.py

+41-17
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
from __future__ import annotations
22

33
import json
4+
import os
45
import shutil
56
import subprocess
67
from pathlib import Path
78
from typing import TYPE_CHECKING
89
from urllib.request import urlopen
910

11+
from natsort import natsorted
12+
1013
if TYPE_CHECKING:
1114
from collections.abc import KeysView
1215

@@ -18,22 +21,18 @@ def download_openapi_generator_jar(version: str) -> None:
1821
MVN_BASE_URL
1922
+ "/remotecontent?filepath=org/openapitools/openapi-generator-cli/"
2023
+ version
21-
+ "/openapi-generator-cli-"
22-
+ version
23-
+ ".jar"
24+
+ f"/openapi-generator-cli-{version}.jar"
2425
)
2526

2627
Path("openapi-generator.jar").unlink(missing_ok=True)
2728

28-
print(download_url)
29+
print(f"[{version}] URL: {download_url!r}")
2930
response = urlopen(download_url) # noqa: S310
3031

3132
if response.status != 200: # noqa: PLR2004
3233
msg = f"{response.status}: {download_url}"
3334
raise RuntimeError(msg)
3435

35-
print("Downloading complete")
36-
3736
with Path("openapi_generator_cli/openapi-generator.jar").open("wb") as openapi_generator_jar:
3837
openapi_generator_jar.write(response.read())
3938
openapi_generator_jar.close()
@@ -78,18 +77,43 @@ def get_published_vesions() -> KeysView[str]:
7877
return published_releases.keys()
7978

8079

81-
def publish() -> None:
82-
latest_version = get_available_versions()[0]
83-
published_versions = get_published_vesions()
80+
def download_latest_jar_for_test() -> None:
81+
latest_version = natsorted(get_available_versions())[-1]
82+
print(f"[{latest_version}] Downloading...")
83+
download_openapi_generator_jar(latest_version)
84+
print(f"[{latest_version}] Downloaded!")
85+
86+
87+
def publish(*, dryrun: bool = False) -> None:
88+
pytest_path = shutil.which("pytest")
89+
poetry_path = shutil.which("poetry")
90+
91+
unpublished_versions = natsorted(set(get_available_versions()) - set(get_published_vesions()))
92+
93+
for publishing_version in unpublished_versions:
94+
print(f"[{publishing_version}] Downloading...")
95+
download_openapi_generator_jar(publishing_version)
96+
97+
print(f"[{publishing_version}] Testing...")
98+
subprocess.check_call([pytest_path])
99+
100+
if dryrun:
101+
continue
102+
103+
print(f"[{publishing_version}] Building...")
104+
subprocess.check_call([poetry_path, "build", "-v"])
105+
106+
print(f"[{publishing_version}] Publishing to TestPyPI...")
107+
subprocess.check_call([poetry_path, "publish", "-r", "testpypi", "-v"])
108+
109+
print(f"[{publishing_version}] Publishing to PyPI...")
110+
subprocess.check_call([poetry_path, "publish", "-v"])
84111

85-
if latest_version not in published_versions:
86-
print("Publishing version " + latest_version)
87-
download_openapi_generator_jar(latest_version)
88-
poetry_path = shutil.which("poetry")
89-
subprocess.check_call([poetry_path, "build"]) # noqa: S603
90-
subprocess.check_call([poetry_path, "publish", "-r", "testpypi"]) # noqa: S603
91-
subprocess.check_call([poetry_path, "publish"]) # noqa: S603
112+
print(f"[{publishing_version}] Published!")
92113

93114

94115
if __name__ == "__main__":
95-
publish()
116+
if os.getenv("DOWNLOAD_LATEST_ONLY") == "1":
117+
download_latest_jar_for_test()
118+
else:
119+
publish(dryrun=os.getenv("DRYRUN") == "1")

pyproject.toml

+12-1
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ mypy = ">=0.991,<1.14"
4444
pre-commit = ">=2.20,<4.0"
4545
taskipy = "^1.10.3"
4646
pytest = ">=7.2.2,<9.0.0"
47+
natsort = "^8.4.0"
4748

4849
[tool.poetry.scripts]
4950
openapi-generator-cli = "openapi_generator_cli:cli"
@@ -61,11 +62,18 @@ lint.select = [
6162
"ALL",
6263
]
6364
lint.ignore = [
64-
"D",
65+
"D211", # No blank lines allowed before class docstring
66+
"D213", # Multi-line docstring summary should start at the second line
6567
]
6668
lint.per-file-ignores."publish.py" = [
69+
"D",
70+
"S603", # `subprocess` call: check for execution of untrusted input
6771
"T201", # `print` found
6872
]
73+
lint.per-file-ignores."tests/*" = [
74+
"D",
75+
"S101", # Use of `assert` detected
76+
]
6977

7078
[tool.mypy]
7179
pretty = true
@@ -74,6 +82,9 @@ show_error_codes = true
7482
strict = true
7583

7684
[tool.taskipy.tasks]
85+
download-latest-jar = "DOWNLOAD_LATEST_ONLY=1 task publish"
7786
test = "pytest"
87+
test-unpublished-versions = "DRYRUN=1 task publish"
7888
lint = "pre-commit run -a"
89+
publish = "python publish.py"
7990
profile = "python -m cProfile"

tests/__init__.py

Whitespace-only changes.

0 commit comments

Comments
 (0)