PEP 631: Refactor reference implementation (#1606)

This uses f-strings for string interpolation, which means this only
works for Python 3.6+, but is more readable.

It also moves the requirement sorting logic into the metadata output
function. Since the sorting logic exists mainly for the purposes of
reproducible builds, it is better to abandon the idea of a
case-insensitive comparison, and to sort as late in the process as
possible (so that anything before the sort can remain agnostic to the
order).
This commit is contained in:
Paul Ganssle 2020-09-18 17:08:19 -04:00 committed by GitHub
parent ea8b7737b7
commit e8d68f32b4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 21 additions and 19 deletions

View File

@ -141,27 +141,27 @@ Parsing
for i, entry in enumerate(dependencies, 1):
if not isinstance(entry, str):
raise TypeError('Dependency #{} of field `project.dependencies` must be a string'.format(i))
raise TypeError(f'Dependency #{i} of field `project.dependencies` must be a string')
try:
Requirement(entry)
except InvalidRequirement as e:
raise ValueError('Dependency #{} of field `project.dependencies` is invalid: {}'.format(i, e))
raise ValueError(f'Dependency #{i} of field `project.dependencies` is invalid: {e}')
return sorted(dependencies, key=lambda d: d.lower())
return dependencies
def parse_optional_dependencies(config):
optional_dependencies = config.get('optional-dependencies', {})
if not isinstance(optional_dependencies, dict):
raise TypeError('Field `project.optional-dependencies` must be a table')
optional_dependency_entries = OrderedDict()
optional_dependency_entries = {}
for option, dependencies in sorted(optional_dependencies.items()):
for option, dependencies in optional_dependencies.items():
if not isinstance(dependencies, list):
raise TypeError(
'Dependencies for option `{}` of field `project.optional-dependencies` '
'must be an array'.format(option)
f'Dependencies for option `{option}` of field '
'`project.optional-dependencies` must be an array'
)
entries = []
@ -169,21 +169,21 @@ Parsing
for i, entry in enumerate(dependencies, 1):
if not isinstance(entry, str):
raise TypeError(
'Dependency #{} of option `{}` of field `project.optional-dependencies` '
'must be a string'.format(i, option)
f'Dependency #{i} of option `{option}` of field '
'`project.optional-dependencies` must be a string'
)
try:
Requirement(entry)
except InvalidRequirement as e:
raise ValueError(
'Dependency #{} of option `{}` of field `project.optional-dependencies` '
'is invalid: {}'.format(i, option, e)
f'Dependency #{i} of option `{option}` of field '
f'`project.optional-dependencies` is invalid: {e}'
)
else:
entries.append(entry)
optional_dependency_entries[option] = sorted(entries, key=lambda d: d.lower())
optional_dependency_entries[option] = entries
return optional_dependency_entries
@ -201,17 +201,19 @@ Metadata
...
if metadata_object.dependencies:
for dependency in metadata_object.dependencies:
metadata_file += 'Requires-Dist: {}\n'.format(dependency)
# Sort dependencies to ensure reproducible builds
for dependency in sorted(metadata_object.dependencies):
metadata_file += f'Requires-Dist: {dependency}\n'
if metadata_object.optional_dependencies:
for option, dependencies in metadata_object.optional_dependencies.items():
metadata_file += 'Provides-Extra: {}\n'.format(option)
for dependency in dependencies:
# Sort extras and dependencies to ensure reproducible builds
for option, dependencies in sorted(metadata_object.optional_dependencies.items()):
metadata_file += f'Provides-Extra: {option}\n'
for dependency in sorted(dependencies):
if ';' in dependency:
metadata_file += 'Requires-Dist: {} and extra == "{}"\n'.format(dependency, option)
metadata_file += f'Requires-Dist: {dependency} and extra == "{option}"\n'
else:
metadata_file += 'Requires-Dist: {}; extra == "{}"\n'.format(dependency, option)
metadata_file += f'Requires-Dist: {dependency}; extra == "{option}"\n'
...