Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

pyproject.toml cleanup #50

Open
lwasser opened this issue Oct 30, 2024 · 9 comments
Open

pyproject.toml cleanup #50

lwasser opened this issue Oct 30, 2024 · 9 comments

Comments

@lwasser
Copy link
Member

lwasser commented Oct 30, 2024

Is it possible to clean up the pyproject.toml just a little bit so the spacing is uniform between tables? It will be easier to read if each table has a space after it! some do and others don't.

[tool.hatch.build]
only-packages = true

[tool.hatch.build.targets.wheel]
packages = ["src/mypkg"]
[tool.pytest.ini_options]
testpaths = ["tests"]
markers = ["raises"]

[tool.coverage.paths]
source = [
    "src/mypkg",
    "*/site-packages/mypkg",
]

[tool.coverage.run]
branch = true
parallel = true

[tool.coverage.report]
exclude_lines = ["pragma: no cover"]
precision = 2
[tool.ruff]
line-length = 88

[tool.ruff.lint]
select = ["ALL"]
ignore = [
    "D107",  # 'Missing docstring in __init__' ignored because pydoclint wants us to document the class instead.
    "D203",  # '1 blank line required before class docstring' ignored because we want no blank line.
    "D212",  # 'Multi-line docstring summary should start at the first line' ignored because we want the summary to start on the second line.
    "D407",  # 'Missing dashed underline after section' ignored because Google style docstrings don't underline.
    "ANN002",  # 'Missing type annotation for {*args} in method'.
    "ANN003",  # 'Missing type annotation for {*kwargs} in method'.
    "ANN101",  # 'Missing type annotation for {self} in method'.
    "ANN102",  # 'Missing type annotation for {cls} in classmethod'.
]
exclude = [
    "docs/conf.py",
]

[tool.ruff.lint.extend-per-file-ignores]
"__init__.py" = [
    "E401",  # 'Multiple imports on one line'
    "E402",  # 'Module level import not at top of file'
    "F401",  # 'Imported but unused'
    "I001",  # 'Import block is un-sorted or un-formatted' ignored because we may have to import in a particular, not-alphabetical order.
]
"tests/**/*.py" = [
    "S101",  # 'Use of assert detected' ignored because we are using pytest.
    "INP001",  # 'Insecure input' ignored because we are testing.
    "ANN201",  # 'Missing type annotation for {return}' ignored because all tests return `None`.
]

[tool.ruff.lint.isort]
case-sensitive = true
known-first-party = ["src", "mypkg"]
lines-after-imports = 1

[tool.pydoclint]
style = "google"  # TODO: Other styles are possible here, like 'numpy'
arg-type-hints-in-docstring = false
check-return-types = false
check-yield-types = false
################################################################################
# Hatch Environments
################################################################################
[tool.hatch.envs.style]
description = """Check the style of the codebase."""
dependencies = [
    "pydoclint",
    "ruff",
]
detached = true

[tool.hatch.envs.style.scripts]
docstrings = "pydoclint"
code = "ruff check {args}"
format = "ruff format {args}"
check = ["docstrings", "code"]

[tool.hatch.envs.audit]
description = """Check dependencies for security vulnerabilities."""
extra-dependencies = [
    "pip-audit",
]

[tool.hatch.envs.audit.scripts]
check = ["pip-audit"]
[tool.hatch.envs.docs]
description = """Build or serve the documentation."""
dependencies = [
    "pydata_sphinx_theme ~=0.16",
    "myst-parser ~=4.0",
    "Sphinx ~=8.0",
    "sphinx-autobuild ==2024.10.3"
]

[tool.hatch.envs.docs.scripts]
build = ["sphinx-apidoc -o docs/api src/mypkg", "sphinx-build {args:-W -b html docs docs/_build}"]
serve = ["sphinx-apidoc -o docs/api src/mypkg", "sphinx-autobuild docs --watch src/mypkg {args:-b html docs/_build/serve}"]

[tool.hatch.envs.install]
description = """Test the installation the package."""
dependencies = [
    "pip",
    "twine",
]
detached = true

[tool.hatch.envs.install.scripts]
check = [
    "pip check",
    "hatch build {args:--clean}",
    "twine check dist/*",
]
[tool.hatch.envs.test]
description = """Run the test suite."""
extra-dependencies = [
    "pytest",
    "pytest-cov",
    "pytest-raises",
    "pytest-randomly",
    "pytest-xdist",
]

[[tool.hatch.envs.test.matrix]]
python = ["3.10", "3.11", "3.12", "3.13"]

[tool.hatch.envs.test.scripts]
run = "pytest {args:--cov=mypkg --cov-report=term-missing}"
@tkoyama010
Copy link
Member

Using toml-sort in a pre-commit hook is an effective way to resolve this issue.

@Midnighter
Copy link
Contributor

I was not very careful with managing whitespace in the jinja statements. Doing some kind of automated formatting would be my preferred option, too.

@Midnighter
Copy link
Contributor

Midnighter commented Oct 30, 2024

toml-sort looks nice, but I'm not sure how to best introduce it. I see the following possible solutions:

  1. Go through the jinja statements and carefully consider how they add or remove whitespace.
  2. Run toml-sort as a task post template initialization. This will require users to install toml-sort beforehand and add --trust to the copier command (https://copier.readthedocs.io/en/stable/configuring/#unsafe).
  3. We can offer a hatch environment for running the command.
  4. It could be turned into a pre-commit hook perhaps?
  • For options 2-4, we can provide a default configuration in the pyproject.toml for toml-sort itself.
  • Options 3&4 require user interaction before the file is formatted.
  • Option 2 provides a nicely formatted TOML right when the template is initialized but may raise user questions, "why do I need to --trust the template?"
  • Option 1 will also provide decent TOML right from the start but requires us to fiddle a bit with the details.

@sneakers-the-rat
Copy link
Contributor

if we move the actual items in the template into sidecar .yaml data files, then in the template we can sort the data and focus on the meta-layout rather than having the syntactic layout function of the template be mixed with the semantic content of what's being laid out :)

@blink1073
Copy link
Contributor

I've been keeping an eye on https://github.com/tox-dev/pyproject-fmt, and I think most of the kinks are worked out. I'd be in favor of adding that to the pre-commit hooks in the template.

@sneakers-the-rat
Copy link
Contributor

How about adding a call to that as a post-generation script with this: https://copier.readthedocs.io/en/stable/configuring/#tasks

Rather than as a pre-commit hook? It would be nice to separate the code generation part from the generated code, so e.g. someone could choose not to use the pre-commit hooks and still get a formatted pyproject.toml

@Midnighter
Copy link
Contributor

See caveats of option 2 that I listed above with regard to tasks.

@sneakers-the-rat
Copy link
Contributor

Aha, ya im back to "lets just split off the deps into yaml and sort them in the template"

Here ill do this and test the output against the formatter one sec.

Also curious how this plays with being able to update the template, like if someone adds deps to a project (which we assume will happen 99.9% of the time) does that break their ability to update? Idk how that works. I feel like if formatting happens after templating that also increases the odds we get spurious update conflicts

@Midnighter
Copy link
Contributor

If you are familiar with handling merge conflicts, the update experience is okay, I think. If not, it's probably a bit of a challenge.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants