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

Add a public API #472

Closed
wants to merge 65 commits into from
Closed
Show file tree
Hide file tree
Changes from 35 commits
Commits
Show all changes
65 commits
Select commit Hold shift + click to select a range
d5969f0
Replaced old WheelFile with the proposed new one
agronholm Jun 9, 2020
a388212
Added support for using WheelFile with existing file handles
agronholm Jun 10, 2020
376cf99
Use posixpath.join() to put together archive names
agronholm Jun 18, 2020
b03dde9
Removed PathLike support from write_file and added the timestamp argu…
agronholm Jun 18, 2020
0fd872d
Don't test on Python 2.7
agronholm Jun 18, 2020
eb0e459
Removed the write_files_from_directory() method
agronholm Jun 18, 2020
fac7e16
Renamed write_metadata_file() to write_distinfo_file()
agronholm Jun 18, 2020
fe39329
Renamed read_metadata_file() to read_distinfo_file()
agronholm Jun 18, 2020
96b88b5
Reverted the use of posixpath.join()
agronholm Jun 18, 2020
3a3d731
Removed more Python 2 configuration
agronholm Jun 18, 2020
a975348
Added special support for the METADATA file
agronholm Jun 18, 2020
f79c25e
Removed the test workflow trigger for PRs
agronholm Jun 21, 2020
b2d7029
Refactored bdist_wheel to use the new WheelFile API
agronholm Jun 21, 2020
e7fe9bb
Refactored test suite and CLI tools to use tmp_path
agronholm Jun 21, 2020
d7b1f1d
Added the py.typed marker
agronholm Jun 21, 2020
4654492
Removed obsolete modules
agronholm Jun 21, 2020
6591155
Added type annotations to macosx_libfile
agronholm Jun 21, 2020
3667709
Fixed a few WheelFile tests
agronholm Jun 21, 2020
9e63bec
Restored Python 3.5 compatibility to WheelFile
agronholm Jun 21, 2020
cbca67e
Added Python 3.7 to the testing matrix
agronholm Jun 21, 2020
bf0afca
Updated the Github publish workflow
agronholm Jun 22, 2020
71474a5
Updated the Github codeqa/test workflow
agronholm Jun 24, 2020
da30173
Merge branch 'master' into publicapi
agronholm Dec 20, 2020
ec0aded
Removed Python 3.5 support
agronholm Feb 8, 2021
f1a5fd4
WIP refactored the Wheel API
agronholm Feb 8, 2021
fa01be4
Merge branch 'main' into publicapi
agronholm Oct 22, 2022
a2a53de
Improved the API and dropped bdist_wininst convert support
agronholm Oct 24, 2022
34f05ae
Removed install dependency on setuptools
agronholm Oct 24, 2022
85ac7c5
Updated version number
agronholm Oct 24, 2022
e3934a9
Switched to running coverage using "python -m"
agronholm Oct 24, 2022
946f7f9
Fixed no files beside .egg-info being added by bdist_wheel
agronholm Oct 24, 2022
b69c2bc
Fixed test_write_file
agronholm Oct 24, 2022
a2ca178
Added setuptools as test dependency
agronholm Oct 24, 2022
c7167fe
Fixed deprecated pytest imports
agronholm Oct 24, 2022
f4aff15
Made most wheel modules private
agronholm Oct 24, 2022
29a5dfc
Made all remaining modules private
agronholm Oct 24, 2022
9f268c3
Changed the default value for amount in WheelArchiveFile.read() to -1
agronholm Oct 24, 2022
c85a333
Fixed import in wheel.__main__
agronholm Oct 24, 2022
31d0dc9
Fixed the most critical type issues and added a MyPy check to CI (#473)
HexDecimal Oct 25, 2022
81471ec
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Oct 25, 2022
ef1425d
Removed unused module
agronholm Oct 25, 2022
71efa9b
Updated the docs for "wheel convert"
agronholm Oct 25, 2022
c2171c2
Updated CLI help, type annotations and string interpolation
agronholm Oct 25, 2022
122f456
Made WheelContentElement into a named tuple
agronholm Oct 25, 2022
d14b5fc
Removed obsolete options
agronholm Oct 25, 2022
9f2bfc6
Fixed mypy error
agronholm Oct 25, 2022
edcb325
Added tests to type checking and finish annotations. (#477)
HexDecimal Oct 26, 2022
914cc81
Merged the license_paths property back to run()
agronholm Oct 25, 2022
cad0948
Merge branch 'main' into publicapi
agronholm Oct 26, 2022
ea9086a
Removed obsolete test
agronholm Oct 27, 2022
13ae2b6
Re-added test accidentally removed during merge
agronholm Oct 27, 2022
21256df
Merge branch 'main' into publicapi
agronholm Nov 6, 2022
b432977
Moved the bdist_wheel module back to its original location
agronholm Nov 7, 2022
14ca7de
Renamed test() to validate_record()
agronholm Nov 26, 2022
ee91735
Merge branch 'main' into publicapi
agronholm Nov 26, 2022
d5c7dc3
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Nov 26, 2022
eb12145
Added a fix for #489
agronholm Nov 26, 2022
91d0e2e
Fixed cache not being used on Windows and macOS in the test workflow
agronholm Nov 26, 2022
9a18f66
Merge branch 'main' into publicapi
agronholm Dec 10, 2022
d783f6b
Added compatibility shim for wheel.wheelfile
agronholm Dec 10, 2022
ff85f76
Added automatic detection of .dist-info directory
agronholm Dec 11, 2022
6892de4
Refactored code to make mypy happy
agronholm Dec 11, 2022
513f1f7
Refactored pkg_resources imports
agronholm Dec 11, 2022
09c5f64
Fixed the rest of mypy errors
agronholm Dec 11, 2022
59fd006
Added a standalone function for writing a WHEEL file
agronholm Dec 11, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 4 additions & 2 deletions .github/workflows/publish.yml
Expand Up @@ -2,12 +2,14 @@ name: Publish packages to PyPI

on:
create:
tags: "*"
tags:
- "[0-9]+.[0-9]+.[0-9]+"
- "[0-9]+.[0-9]+.[0-9]+[a-b][0-9]+"
- "[0-9]+.[0-9]+.[0-9]+rc[0-9]+"

jobs:
publish:
runs-on: ubuntu-latest
if: startsWith(github.ref, 'refs/tags/')
steps:
- uses: actions/checkout@v3
- name: Set up Python
Expand Down
10 changes: 4 additions & 6 deletions .github/workflows/test.yml
Expand Up @@ -39,14 +39,12 @@ jobs:
with:
path: ~/.cache/pip
key: pip-test-${{ matrix.python-version }}-${{ matrix.os }}
- name: Install the project
run: "pip install --no-binary=:all: ."
- name: Install test dependencies
run: pip install .[test] coverage[toml]
- name: Install the project and its test dependencies
run: pip install --no-binary=setuptools,wheel .[test] coverage[toml]
- name: Test with pytest
run: |
coverage run -m pytest -W always
coverage xml
python -m coverage run -m pytest -W always
python -m coverage xml
- name: Send coverage data to Codecov
uses: codecov/codecov-action@v3
with:
Expand Down
5 changes: 5 additions & 0 deletions docs/news.rst
@@ -1,6 +1,11 @@
Release Notes
=============

**UNRELEASED**

- Added a public API
- Dropped support for converting ``bdist_wininst`` based installers into wheels

**0.38.0 (2022-10-21)**

- Dropped support for Python < 3.7
Expand Down
5 changes: 3 additions & 2 deletions setup.cfg
Expand Up @@ -32,15 +32,15 @@ package_dir=
= src
packages = find:
python_requires = >=3.7
install_requires = setuptools >= 57.0.0
zip_safe = False

[options.packages.find]
where = src

[options.extras_require]
test =
Copy link

Choose a reason for hiding this comment

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

Logically it makes sense to separate these out but is is necessarily worth it? The additional install time is so trivial for the small amount of dependencies so I'm just not sure its really worth the split. It also makes the CI caching harder.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

What are you talking about?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Oh, you mean the separation of test and typing dependencies? That wasn't actually done by me, and I'm still not 100% convinced that we shouldn't be using pre-commit for that. It's not critical either way, and I don't see any particular issues that it would cause for caching. I could of course be convinced otherwise.

pytest >= 3.0.0
pytest >= 6.2.0
setuptools >= 57

[options.entry_points]
console_scripts =
Expand All @@ -58,6 +58,7 @@ max-line-length = 88

[tool:pytest]
testpaths = tests
addopts = --tb=short

[coverage:run]
source = wheel
Expand Down
5 changes: 4 additions & 1 deletion src/wheel/__init__.py
@@ -1,3 +1,6 @@
from __future__ import annotations

__version__ = "0.38.0"
__all__ = ["WheelError", "WheelReader", "WheelWriter", "make_filename"]
__version__ = "1.0.0a1"

from ._wheelfile import WheelError, WheelReader, WheelWriter, make_filename
22 changes: 13 additions & 9 deletions src/wheel/macosx_libfile.py → src/wheel/_macosx_libfile.py
Expand Up @@ -43,6 +43,7 @@
import ctypes
import os
import sys
from typing import BinaryIO

"""here the needed const and struct from mach-o header files"""

Expand Down Expand Up @@ -238,7 +239,7 @@
"""


def swap32(x):
def swap32(x: int) -> int:
return (
((x << 24) & 0xFF000000)
| ((x << 8) & 0x00FF0000)
Expand All @@ -247,7 +248,9 @@ def swap32(x):
)


def get_base_class_and_magic_number(lib_file, seek=None):
def get_base_class_and_magic_number(
lib_file: BinaryIO, seek: int | None = None
) -> tuple[type[ctypes.Structure], int]:
if seek is None:
seek = lib_file.tell()
else:
Expand All @@ -271,11 +274,11 @@ def get_base_class_and_magic_number(lib_file, seek=None):
return BaseClass, magic_number


def read_data(struct_class, lib_file):
def read_data(struct_class: type[ctypes.Structure], lib_file: BinaryIO):
return struct_class.from_buffer_copy(lib_file.read(ctypes.sizeof(struct_class)))


def extract_macosx_min_system_version(path_to_lib):
def extract_macosx_min_system_version(path_to_lib: str) -> tuple[int, int, int] | None:
with open(path_to_lib, "rb") as lib_file:
BaseClass, magic_number = get_base_class_and_magic_number(lib_file, 0)
if magic_number not in [FAT_MAGIC, FAT_MAGIC_64, MH_MAGIC, MH_MAGIC_64]:
Expand Down Expand Up @@ -333,7 +336,9 @@ class FatArch(BaseClass):
return None


def read_mach_header(lib_file, seek=None):
def read_mach_header(
lib_file: BinaryIO, seek: int | None = None
) -> tuple[int, int, int] | None:
"""
This funcition parse mach-O header and extract
information about minimal system version
Expand Down Expand Up @@ -382,14 +387,14 @@ class VersionBuild(base_class):
continue


def parse_version(version):
def parse_version(version: int) -> tuple[int, int, int]:
x = (version & 0xFFFF0000) >> 16
y = (version & 0x0000FF00) >> 8
z = version & 0x000000FF
return x, y, z


def calculate_macosx_platform_tag(archive_root, platform_tag):
def calculate_macosx_platform_tag(archive_root: str, platform_tag: str) -> str:
"""
Calculate proper macosx platform tag basing on files which are included to wheel

Expand Down Expand Up @@ -467,5 +472,4 @@ def calculate_macosx_platform_tag(archive_root, platform_tag):

sys.stderr.write(error_message)

platform_tag = prefix + "_" + fin_base_version + "_" + suffix
return platform_tag
return prefix + "_" + fin_base_version + "_" + suffix
45 changes: 13 additions & 32 deletions src/wheel/metadata.py → src/wheel/_metadata.py
Expand Up @@ -3,11 +3,9 @@
"""
from __future__ import annotations

import os.path
import textwrap
from email.message import Message
from email.parser import Parser
from typing import Iterator
from collections.abc import Iterator
from email.parser import HeaderParser
from pathlib import Path

from pkg_resources import Requirement, safe_extra, split_sections

Expand Down Expand Up @@ -69,41 +67,24 @@ def generate_requirements(
yield "Requires-Dist", new_req + condition


def pkginfo_to_metadata(egg_info_path: str, pkginfo_path: str) -> Message:
"""
Convert .egg-info directory with PKG-INFO to the Metadata 2.1 format
"""
with open(pkginfo_path, encoding="utf-8") as headers:
pkg_info = Parser().parse(headers)
def pkginfo_to_metadata(pkginfo_path: Path) -> list[tuple[str, str]]:
"""Convert an .egg-info/PKG-INFO file to the Metadata 2.1 format."""

with pkginfo_path.open() as fp:
pkg_info = HeaderParser().parse(fp)

pkg_info.replace_header("Metadata-Version", "2.1")

# Those will be regenerated from `requires.txt`.
del pkg_info["Provides-Extra"]
del pkg_info["Requires-Dist"]
requires_path = os.path.join(egg_info_path, "requires.txt")
if os.path.exists(requires_path):
with open(requires_path) as requires_file:
requires = requires_file.read()

requires_path = pkginfo_path.parent / "requires.txt"
if requires_path.exists():
requires = requires_path.read_text()
parsed_requirements = sorted(split_sections(requires), key=lambda x: x[0] or "")
for extra, reqs in parsed_requirements:
for key, value in generate_requirements({extra: reqs}):
if (key, value) not in pkg_info.items():
pkg_info[key] = value

description = pkg_info["Description"]
if description:
description_lines = pkg_info["Description"].splitlines()
dedented_description = "\n".join(
# if the first line of long_description is blank,
# the first line here will be indented.
(
description_lines[0].lstrip(),
textwrap.dedent("\n".join(description_lines[1:])),
"\n",
)
)
pkg_info.set_payload(dedented_description)
del pkg_info["Description"]

return pkg_info
return list(pkg_info.items())