Skip to content

Commit 1f11018

Browse files
authored
Appropriate formatting for __init__ file. (#544)
* Appropriate formatting for __init__ file. REALLY run the pre-commits in the unit tests. * Add dependencies for CI testing. * Limit python versions. * Pass CI python version * Use a python range. * Give up on black on 3.13. * Better CI cleanliness
1 parent 97e4458 commit 1f11018

File tree

7 files changed

+79
-124
lines changed

7 files changed

+79
-124
lines changed

.github/workflows/ci.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,5 @@ jobs:
2727
pip install -e .[dev]
2828
- name: Run unit tests with pytest / pytest-copie
2929
run: |
30-
python -m pytest
30+
git config --global init.defaultBranch main
31+
python -m pytest --python_version ${{ matrix.python-version }}

.github/workflows/smoke-test.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,8 @@ jobs:
3838
pip list
3939
- name: Run unit tests with pytest / pytest-copie
4040
run: |
41-
python -m pytest
41+
git config --global init.defaultBranch main
42+
python -m pytest --python_version ${{ matrix.python-version }}
4243
- name: Send status to Slack app
4344
if: ${{ failure() && github.event_name != 'workflow_dispatch' }}
4445
id: slack

pyproject.toml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,20 @@ dev = [
3232
"pylint", # test pylint in unit tests
3333
"pytest-copie", # Used to create hydrated copier projects for testing
3434
"tox", # Used to run tests in multiple environments
35+
## Dependencies that are needed to test hydrated projects:
36+
"ipykernel",
37+
"ipython",
38+
"jupyter",
39+
"jupytext",
40+
"mypy",
41+
"nbconvert",
42+
"nbsphinx",
43+
"pre-commit",
44+
"ruff",
45+
"sphinx",
46+
"sphinx-autoapi",
47+
"sphinx-copybutton",
48+
"sphinx-rtd-theme",
3549
]
3650

3751
[build-system]

python-project-template/.pre-commit-config.yaml.jinja

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ repos:
139139
{%- endif %}
140140
]
141141
{%- endif %}
142-
{%- if include_notebooks %}
142+
{%- if include_docs and include_notebooks %}
143143
# Make sure Sphinx can build the documentation while explicitly omitting
144144
# notebooks from the docs, so users don't have to wait through the execution
145145
# of each notebook or each commit. By default, these will be checked in the
Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
1-
from ._version import __version__
21
{% if create_example_module -%}
2+
from ._version import __version__
33
from .example_module import greetings, meaning
44

5-
__all__ = ["greetings", "meaning"]
5+
__all__ = ["greetings", "meaning", "__version__"]
6+
{% else -%}
7+
from ._version import __version__
8+
9+
__all__ = ["__version__"]
610
{% endif -%}

tests/conftest.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import pytest
2+
3+
PYTHON_VERSIONS = ["3.9", "3.10", "3.11", "3.12", "3.13"]
4+
5+
6+
def pytest_addoption(parser):
7+
parser.addoption("--python_version", action="store", default="3.12", choices=PYTHON_VERSIONS)
8+
9+
10+
@pytest.fixture(scope="session", name="python_version")
11+
def python_version(request):
12+
yield request.config.getoption("--python_version")
13+
14+
15+
@pytest.fixture
16+
def default_answers(python_version):
17+
return {"python_versions": [python_version]}

tests/test_package_creation.py

Lines changed: 37 additions & 119 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
"""Verify package creation using `pytest-copie`"""
22

3+
import os
34
import subprocess
45

56
import pytest
67

8+
os.environ["SKIP"] = "no-commit-to-branch"
9+
710

811
def create_project_with_basic_checks(copie, extra_answers, package_name="example_package"):
912
"""Create the project using copier. Perform a handful of basic checks on the created directory."""
@@ -24,12 +27,6 @@ def create_project_with_basic_checks(copie, extra_answers, package_name="example
2427
)
2528
assert build_results.returncode == 0
2629

27-
# pyproject_toml_is_valid
28-
precommit_results = subprocess.run(
29-
["pre-commit", "run", "validate-pyproject"], cwd=result.project_dir, check=False
30-
)
31-
assert precommit_results.returncode == 0
32-
3330
# directory_structure_is_correct
3431
assert (result.project_dir / f"src/{package_name}").is_dir() and (
3532
result.project_dir / f"tests/{package_name}"
@@ -54,92 +51,28 @@ def create_project_with_basic_checks(copie, extra_answers, package_name="example
5451
print("Required file not generated:", file)
5552
assert all_found
5653

57-
# black_runs_successfully for src and tests
58-
black_results = subprocess.run(
59-
["python", "-m", "black", "--check", "--verbose", result.project_dir],
60-
cwd=result.project_dir,
61-
check=False,
62-
)
63-
assert black_results.returncode == 0
64-
65-
return result
66-
67-
68-
def pylint_runs_successfully(result):
69-
"""Test to ensure that the pylint linter runs successfully on the project"""
70-
# run pylint to ensure that the hydrated files are linted correctly
71-
pylint_src_results = subprocess.run(
72-
[
73-
"python",
74-
"-m",
75-
"pylint",
76-
"--recursive=y",
77-
"--rcfile=./src/.pylintrc",
78-
(result.project_dir / "src"),
79-
],
80-
cwd=result.project_dir,
81-
check=False,
82-
)
83-
84-
pylint_test_results = subprocess.run(
85-
[
86-
"python",
87-
"-m",
88-
"pylint",
89-
"--recursive=y",
90-
"--rcfile=./tests/.pylintrc",
91-
(result.project_dir / "tests"),
92-
],
93-
cwd=result.project_dir,
94-
check=False,
95-
)
96-
97-
return pylint_src_results.returncode == 0 and pylint_test_results.returncode == 0
98-
99-
100-
def docs_build_successfully(result):
101-
"""Test that we can build the doc tree.
102-
103-
!!! NOTE - This doesn't currently work because we need to `pip install` the hydrated
104-
project before running the tests. And we don't have a way to create a temporary
105-
virtual environment for the project.
106-
"""
107-
108-
required_files = [
109-
".readthedocs.yml",
110-
]
111-
all_found = True
112-
for file in required_files:
113-
if not (result.project_dir / file).is_file():
114-
all_found = False
115-
print("Required file not generated:", file)
116-
return all_found
117-
118-
# sphinx_results = subprocess.run(
119-
# ["make", "html"],
120-
# cwd=(result.project_dir / "docs"),
121-
# )
122-
123-
# return sphinx_results.returncode == 0
54+
## Initialize local git repository and add ALL new files to it.
55+
git_results = subprocess.run(["git", "init", "."], cwd=result.project_dir, check=False)
56+
assert git_results.returncode == 0
57+
git_results = subprocess.run(["git", "add", "."], cwd=result.project_dir, check=False)
58+
assert git_results.returncode == 0
12459

60+
## This will run ALL of the relevant pre-commits (excludes only "no-commit-to-branch,check-added-large-files")
61+
precommit_results = subprocess.run(["pre-commit", "run", "-a"], cwd=result.project_dir, check=False)
62+
assert precommit_results.returncode == 0
12563

126-
def github_workflows_are_valid(result):
127-
"""Test to ensure that the GitHub workflows are valid"""
128-
workflows_results = subprocess.run(
129-
["pre-commit", "run", "check-github-workflows"], cwd=result.project_dir, check=False
130-
)
131-
return workflows_results.returncode == 0
64+
return result
13265

13366

134-
def test_all_defaults(copie):
67+
def test_all_defaults(copie, default_answers):
13568
"""Test that the default values are used when no arguments are given.
13669
Ensure that the project is created and that the basic files exist.
13770
"""
138-
# run copier to hydrate a temporary project
139-
result = create_project_with_basic_checks(copie, {})
71+
result = create_project_with_basic_checks(copie, default_answers)
14072

14173
# uses ruff instead of (black/isort/pylint)
142-
assert not pylint_runs_successfully(result)
74+
assert not (result.project_dir / "src/.pylintrc").is_file()
75+
assert not (result.project_dir / "tests/.pylintrc").is_file()
14376

14477
# check to see if the README file was hydrated with copier answers.
14578
found_line = False
@@ -151,19 +84,19 @@ def test_all_defaults(copie):
15184
assert found_line
15285

15386

154-
def test_use_black_and_no_example_modules(copie):
87+
def test_use_black_and_no_example_modules(copie, default_answers):
15588
"""We want to provide non-default arguments for the linter and example modules
15689
copier questions and ensure that the pyproject.toml file is created with Black
15790
and that no example modules are created.
15891
"""
159-
160-
# provide a dictionary of the non-default answers to use
161-
extra_answers = {
92+
extra_answers = default_answers | {
16293
"enforce_style": ["black", "pylint", "isort"],
16394
"create_example_module": False,
16495
}
16596
result = create_project_with_basic_checks(copie, extra_answers)
166-
assert pylint_runs_successfully(result)
97+
98+
assert (result.project_dir / "src/.pylintrc").is_file()
99+
assert (result.project_dir / "tests/.pylintrc").is_file()
167100

168101
# make sure that the files that were not requested were not created
169102
assert not (result.project_dir / "src/example_package/example_module.py").is_file()
@@ -191,12 +124,10 @@ def test_use_black_and_no_example_modules(copie):
191124
["black", "pylint", "isort", "ruff_lint", "ruff_format"],
192125
],
193126
)
194-
def test_code_style_combinations(copie, enforce_style):
127+
def test_code_style_combinations(copie, enforce_style, default_answers):
195128
"""Test that various combinations of code style enforcement will
196129
still result in a valid project being created."""
197-
198-
# provide a dictionary of the non-default answers to use
199-
extra_answers = {
130+
extra_answers = default_answers | {
200131
"enforce_style": enforce_style,
201132
}
202133
result = create_project_with_basic_checks(copie, extra_answers)
@@ -211,16 +142,13 @@ def test_code_style_combinations(copie, enforce_style):
211142
["email", "slack"],
212143
],
213144
)
214-
def test_smoke_test_notification(copie, notification):
145+
def test_smoke_test_notification(copie, notification, default_answers):
215146
"""Confirm we can generate a "smoke_test.yaml" file, with all
216147
notification mechanisms selected."""
217-
218-
# provide a dictionary of the non-default answers to use
219-
extra_answers = {
148+
extra_answers = default_answers | {
220149
"failure_notification": notification,
221150
}
222151

223-
# run copier to hydrate a temporary project
224152
result = create_project_with_basic_checks(copie, extra_answers)
225153

226154

@@ -234,13 +162,10 @@ def test_smoke_test_notification(copie, notification):
234162
["none"],
235163
],
236164
)
237-
def test_license(copie, license):
165+
def test_license(copie, license, default_answers):
238166
"""Confirm we get a valid project for different license options."""
167+
extra_answers = default_answers | {"license": license}
239168

240-
# provide a dictionary of the non-default answers to use
241-
extra_answers = {"license": license}
242-
243-
# run copier to hydrate a temporary project
244169
result = create_project_with_basic_checks(copie, extra_answers)
245170

246171

@@ -257,13 +182,11 @@ def test_license(copie, license):
257182
},
258183
],
259184
)
260-
def test_doc_combinations(copie, doc_answers):
185+
def test_doc_combinations(copie, doc_answers, default_answers):
261186
"""Confirm the docs directory is well-formed, when including docs."""
187+
extra_answers = default_answers | doc_answers
188+
result = create_project_with_basic_checks(copie, extra_answers)
262189

263-
# run copier to hydrate a temporary project
264-
result = create_project_with_basic_checks(copie, doc_answers)
265-
266-
assert docs_build_successfully(result)
267190
assert (result.project_dir / "docs").is_dir()
268191

269192

@@ -280,35 +203,30 @@ def test_doc_combinations(copie, doc_answers):
280203
},
281204
],
282205
)
283-
def test_doc_combinations_no_docs(copie, doc_answers):
206+
def test_doc_combinations_no_docs(copie, doc_answers, default_answers):
284207
"""Confirm there is no 'docs' directory, if not including docs."""
208+
extra_answers = default_answers | doc_answers
285209

286-
# run copier to hydrate a temporary project
287-
result = create_project_with_basic_checks(copie, doc_answers)
210+
result = create_project_with_basic_checks(copie, extra_answers)
288211

289212
assert not (result.project_dir / "docs").is_dir()
290213

291214

292215
@pytest.mark.parametrize("test_lowest_version", ["none", "direct", "all"])
293-
def test_test_lowest_version(copie, test_lowest_version):
216+
def test_test_lowest_version(copie, test_lowest_version, default_answers):
294217
"""Confirm we can generate a "testing_and_coverage.yaml" file, with all
295218
test_lowest_version mechanisms selected."""
296-
297-
# provide a dictionary of the non-default answers to use
298-
extra_answers = {
219+
extra_answers = default_answers | {
299220
"test_lowest_version": test_lowest_version,
300221
}
301222

302-
# run copier to hydrate a temporary project
303223
result = create_project_with_basic_checks(copie, extra_answers)
304224

305225

306-
def test_github_workflows_schema(copie):
226+
def test_github_workflows_schema(copie, default_answers):
307227
"""Confirm the current GitHub workflows have valid schemas."""
308-
extra_answers = {
228+
extra_answers = default_answers | {
309229
"include_benchmarks": True,
310230
"include_docs": True,
311231
}
312232
result = create_project_with_basic_checks(copie, extra_answers)
313-
314-
assert github_workflows_are_valid(result)

0 commit comments

Comments
 (0)