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 support #34

Merged
merged 39 commits into from
Feb 2, 2023
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
b2e74b5
pyproject.toml poetry file
gpongelli Jan 22, 2023
7d36495
search for pyproject.toml file
gpongelli Jan 22, 2023
45540d7
add library to parse pyproject and add new file to SOURCES
gpongelli Jan 22, 2023
fd5c470
implement pieces for pyproject.toml handling
gpongelli Jan 22, 2023
51c045f
return FileLines instead of dict
gpongelli Jan 24, 2023
f54b957
first version for tests
gpongelli Jan 24, 2023
d8bc619
build-system seems interfere with appveyor
gpongelli Jan 24, 2023
a5a6565
fix deprecation warning
gpongelli Jan 24, 2023
b15d091
indentation
gpongelli Jan 24, 2023
08a92d5
fix message when no required files are present
gpongelli Jan 24, 2023
16f0c7d
toml does not need comma
gpongelli Jan 24, 2023
76c40f2
removed version from toml
gpongelli Jan 24, 2023
483d27b
using tomlkit package
gpongelli Jan 24, 2023
0aca989
moved to tomlkit, small set of working tests
gpongelli Jan 24, 2023
ac1b95d
manage different tools that use pyproject.toml
gpongelli Jan 24, 2023
dad4492
renamed module to generic pyproject.py
gpongelli Jan 24, 2023
8a515de
renamed objects removing poetry reference
gpongelli Jan 24, 2023
7ea9050
tool.setuptools is optional table
gpongelli Jan 25, 2023
12c5265
removed wrong test
gpongelli Jan 25, 2023
ed48eda
same test name as setup.py
gpongelli Jan 25, 2023
d748483
unsupported dynamic format on toml file
gpongelli Jan 25, 2023
583c366
manage StringIO input
gpongelli Jan 25, 2023
b10da17
fixed latest tests
gpongelli Jan 25, 2023
8349504
setuptools pyproject test and implementation
gpongelli Jan 25, 2023
c7e1623
renamed files to have all pyproject tests with same prefix
gpongelli Jan 25, 2023
82c67ea
added flit implementation and tests
gpongelli Jan 25, 2023
63e735a
fix trailing whitespace
gpongelli Jan 25, 2023
7ed0b9a
review comments
gpongelli Jan 25, 2023
605fe9a
pass flake8 tests
gpongelli Jan 25, 2023
c166aed
new tests for cli
gpongelli Jan 25, 2023
f2c7d21
fix after latest changes
gpongelli Jan 25, 2023
2a0d7d4
fix test
gpongelli Jan 25, 2023
1214b38
fix isort stage
gpongelli Jan 26, 2023
572ca6e
install tomlkit for mypy run
gpongelli Jan 26, 2023
7e471e4
fix mypy checks
gpongelli Jan 26, 2023
4539a49
removed unused pyproject.toml file
gpongelli Jan 27, 2023
f1cb32e
checks done in previous call on the chain
gpongelli Jan 27, 2023
de13d7a
new tests and changes to reach 100%
gpongelli Jan 27, 2023
04c8988
test file names
gpongelli Jan 27, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
[tool.poetry]
name = "check-python-versions"
version = "1.0.0"
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not the version that's a problem, it's that this project (check-python-versions) doesn't use Poetry and therefore it shouldn't have Poetry configuration in its top-level pyproject.toml.

Please move this file into tests/sources/data/ or a similarly named subdirectory if it's needed by the test suite.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's clear that this project doesn't use poetry to build it.

I've made the file to do a live check with check-python-versions.py , so it could be related to test_cli.py , I've to look at it.

homepage = "https://github.com/mgedmin/check-python-versions"
description = "Compare supported Python versions in setup.py vs tox.ini et al."
authors = ["Marius Gedminas <[email protected]>"]
Expand Down
4 changes: 2 additions & 2 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
universal = 1

[metadata]
license_file = LICENSE
license_files = LICENSE

[zest.releaser]
python-file-with-version = src/check_python_versions/__init__.py
Expand All @@ -13,7 +13,7 @@ include_trailing_comma = true
lines_after_imports = 2
reverse_relative = true
known_first_party = check_python_versions
known_third_party = pytest, yaml
known_third_party = pytest, yaml, tomlkit
skip = check-python-versions

[mypy]
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,6 @@
'check-python-versions = check_python_versions.cli:main',
],
},
install_requires=['pyyaml', 'pytomlpp'],
install_requires=['pyyaml', 'tomlkit'],
zip_safe=False,
)
58 changes: 39 additions & 19 deletions src/check_python_versions/sources/poetry_pyproject.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@
check-python-versions supports both.
"""

import pytomlpp
from tomlkit import dumps
from tomlkit import parse, load
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

flake8 tells me tomlkit.parse is imported but unused.


from typing import (
List,
Expand All @@ -38,11 +39,29 @@
PYPROJECT_TOML = 'pyproject.toml'


def _load_toml(filename: FileOrFilename):
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would be nice if there was a type annotation for the return type. I suppose it's hard to be more specific than a generic Dict[str, Any].

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

seems this row is outdated, also the file was renamed to "pyproject.py" because it handles all the tools that use pyproject.toml

table = {}
# tomlkit has two different API to load from file name or file object
if isinstance(filename, str):
with open_file(filename) as fp:
table = load(fp)
if isinstance(filename, TextIO):
table = load(filename)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's a check_python_version.utils.open_file() context manager that could simplify this.

return table


def get_toml_content(
filename: FileOrFilename = PYPROJECT_TOML
) -> FileLines:
"""Utility method to see if TOML library keeps style and comments."""
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If it's only used by the test suite, it should be moved into test_pyproject.py.

table = _load_toml(filename)
return dumps(table).split('\n')


def _get_pyproject_toml_classifiers(
filename: FileOrFilename = PYPROJECT_TOML
filename: FileOrFilename = PYPROJECT_TOML
) -> List[str]:
with open_file(filename) as f:
table = pytomlpp.load(f)
table = _load_toml(filename)

if 'tool' not in table:
return []
Expand All @@ -55,10 +74,9 @@ def _get_pyproject_toml_classifiers(


def _get_pyproject_toml_python_requires(
filename: FileOrFilename = PYPROJECT_TOML
filename: FileOrFilename = PYPROJECT_TOML
) -> List[str]:
with open_file(filename) as f:
table = pytomlpp.load(f)
table = _load_toml(filename)

if 'tool' not in table:
return []
Expand All @@ -83,6 +101,10 @@ def get_supported_python_versions(
# versions in classifiers.
return []

if not isinstance(classifiers, (list, tuple)):
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does TOML support tuples? Somehow I thought it only had lists ("arrays") and dicts ("tables") as data structures.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you're right, tuples are not supported

warn('The value passed to classifiers is not a list')
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The 'passed to' phrasing makes sense when talking about values passed to Python function calls, which is what happens in a setup.py. For TOML files there are no function calls and no passing, so it should probably say 'The value specified for [tools.poetry] classifiers is not an array'.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I haven't used TOML much. Are there alternative syntaxes? E.g. could I write something like

[tools]
poetry = { classifiers: [...] }

or

[tools.poetry.classifiers]
...

instead? If so maybe the message should say "The value of tools.poetry.classifiers is not an array", or whatever is the common syntax for identifying a piece of a nested data structure in TOML-land.

return []

return get_versions_from_classifiers(classifiers)


Expand All @@ -94,7 +116,7 @@ def get_python_requires(
if python_requires is None:
return None
if not isinstance(python_requires, str):
warn('The value passed to python is not a string')
warn('The value passed to python dependency is not a string')
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Likewise.

return None
return parse_python_requires(python_requires)

Expand All @@ -111,7 +133,7 @@ def update_supported_python_versions(
if classifiers is None:
return None
if not isinstance(classifiers, (list, tuple)):
warn('The value passed to setup(classifiers=...) is not a list')
warn('The value passed to classifiers is not a list')
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Likewise.

return None
new_classifiers = update_classifiers(classifiers, new_versions)
return _update_pyproject_toml_classifiers(filename, new_classifiers)
Expand All @@ -126,7 +148,7 @@ def update_python_requires(
Does not touch the file but returns a list of lines with new file contents.
"""
python_requires = _get_pyproject_toml_python_requires(filename)
if python_requires is None:
if python_requires is None or python_requires == []:
return None
comma = ', '
if ',' in python_requires and ', ' not in python_requires:
Expand All @@ -144,11 +166,10 @@ def update_python_requires(


def _update_pyproject_toml_classifiers(
filename: FileOrFilename,
new_value: Union[str, List[str]]
filename: FileOrFilename,
new_value: Union[str, List[str]],
) -> Optional[FileLines]:
with open_file(filename) as f:
table = pytomlpp.load(f)
table = _load_toml(filename)

if 'tool' not in table:
return []
Expand All @@ -157,15 +178,14 @@ def _update_pyproject_toml_classifiers(

table['tool']['poetry']['classifiers'] = new_value

return pytomlpp.dumps(table).split('\n')
return dumps(table).split('\n')


def _update_pyproject_toml_python_requires(
filename: FileOrFilename,
new_value: Union[str, List[str]]
new_value: Union[str, List[str]],
) -> Optional[FileLines]:
with open_file(filename) as f:
table = pytomlpp.load(f)
table = _load_toml(filename)

if 'tool' not in table:
return []
Expand All @@ -175,7 +195,7 @@ def _update_pyproject_toml_python_requires(
return []

table['tool']['poetry']['dependencies']['python'] = new_value
return pytomlpp.dumps(table).split('\n')
return dumps(table).split('\n')
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note to self: investigate what tomlkit.dumps() returns and whether this should be using .splitlines() instead.

Note to self: make sure the unit tests verify that modifying a .toml file doesn't add or remove any trailing newlines at the end of the FILE.



PoetryPyProject = Source(
Expand Down
Loading