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

Migrate to pyproject.toml #379

Merged
merged 24 commits into from
Jan 22, 2025
Merged

Conversation

nirosys
Copy link
Contributor

@nirosys nirosys commented Oct 19, 2024

Issue #, if available: #305

Description of changes:
This PR migrates ion-python away from a setup.py/install.py based project to a PEP 517 compliant build system. By updating the build system we are able to adopt better tooling through the formalized nature of PEP 517 projects, and how tooling can integrate with the build tree.

One tool that we can use is a PEP 517 build system called py-build-cmake which allows us use CMake for building our C extension. By using CMake, we're able to place ion-c into the build tree and include it as a subdirectory, letting py-build-cmake handle the python build flags.

A side effect of this, is that the code layout now splits the C module into src/ and the python code into src-python/.

Building the Package

Building the extension is now a simple:

$ python -m build
* Creating isolated environment: venv+pip...
* Installing packages in isolated environment:
  - py-build-cmake~=0.1.8
* Getting build dependencies for sdist...
...
* Building wheel...
...
[100%] Built target _ioncmodule
-- Installing: /var/folders/ld/sktjjrk132z_f7_95g908dxr0000gr/T/tmp4ekl7bjs/staging/amazon/_ioncmodule.so
Successfully built amazon_ion-0.12.0.tar.gz and amazon_ion-0.12.0-cp312-cp312-macosx_13_0_x86_64.whl
(venv) glitch@147dda5e5395 ~/C/ion-python>

This will build both the sdist (source distribution) and a binary wheel for the current platform & python version. This can be used to ensure the module compiles, but does not install the package. By default everything is built in isolation, using a virtual environment and pip, everything (including the C module) is built in a temporary directory.

C Extension Changes

Prior to this PR when installing the package the C extension would be present under amazon.ion.ionc. Due to a limitation in py-build-cmake (at the time of implementation) the C extension is now under top-level package, and has been renamed _ioncmodule. This is reflected in the simpleion module when testing for the extension's existance.

Dependencies

Prior to pyproject.toml, it was common practice to put dependencies into a text file called requirements.txt. With PEP 517 dependency management has been formalized, along with other metadata that previously could be provided differently depending on which build tools you were actually using.

In pyproject.toml we have a section [project] which includes a dependencies field, containing all of the dependencies needed for the package to work. We also have some optional dependencies that we can install for benchmarking, and/or unit testing. Unit testing and benchmarking are not something that most users would need when installing ion-python, so these dependencies are kept separate in the [project.optional-dependencies] section. Each list in this section is a named set of dependencies or extras that can be installed, but are not installed by default.

pip supports these optional dependencies through PEP 517, and they can be installed with pip using a command like:

$ python -m pip install -e '.[test]'

The above command would install the package in editable mode, which only installs the dependencies. Since we reference test, it includes the optional dependencies named test with the required dependencies. This allows us to keep benchmarking dependencies (like ujson, rapidjson, etc) separate so that our users do not need to install them unless they want to do benchmarking. Likewise, if the user isn't contributing or changing ion-python, there's no need for specific versions of venv and tox, required by ion-python.

Configuration

All of the 3rd party tooling configuration (eg. tox, pytest, etc) has been moved into the pyproject.toml.

Additional Changes

In addition to the pyproject.toml migration, I added in a new function for the C extension. Ion C has had a version API since Oct 2023, that can return the version and revision. I've added a new method within the _ioncmodule package that exposes this functionality:

>>> import amazon._ioncmodule
>>> amazon._ioncmodule.ionc_version()
'v1.1.3 (rev: d61c09a)'
>>>

This should make it easier to determine what Ion C fixes/bugs/etc are present in a given ion-python installation.


By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.

@nirosys nirosys force-pushed the rgiliam/build-rework branch from 635da05 to e6e16a2 Compare January 16, 2025 00:44
@nirosys
Copy link
Contributor Author

nirosys commented Jan 16, 2025

Windows build issue:

LINK : fatal error LNK1181: cannot open input file 'm.lib' [C:\Users\runneradmin\AppData\Local\Temp\build-via-sdist-rkldgbwp\amazon_ion-0.13.0\.py-build-cmake_cache\pp310-pypy310_pp73-win_amd64\_ioncmodule.vcxproj]

and I missed the performance regression workflow:

ERROR: Could not open requirements file: [Errno 2] No such file or directory: 'requirements.txt'

@nirosys nirosys marked this pull request as ready for review January 17, 2025 23:36
@nirosys nirosys requested a review from rmarrowstone January 17, 2025 23:48
Copy link
Contributor

@rmarrowstone rmarrowstone left a comment

Choose a reason for hiding this comment

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

Awesome!

- run: pip install --upgrade setuptools
- run: pip install -r requirements.txt
- run: pip install -e .
- run: python -m pip install build virtualenv
Copy link
Contributor

Choose a reason for hiding this comment

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

Why does this action also install virtualenv but the test-windows does not?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah good catch, ty. I'll remove that, we're not using virtualenv in the workflows.

@@ -15,6 +15,7 @@ env:
specs: '{command:read,format:ion_text} {command:write,format:ion_text} {command:read,format:ion_binary} {command:write,format:ion_binary}'
test_data_id: 'generated-test-data'
run_cli: 'python amazon/ionbenchmark/ion_benchmark_cli.py'
run_cli_new: 'python src-python/amazon/ionbenchmark/ion_benchmark_cli.py'
Copy link
Contributor

Choose a reason for hiding this comment

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

Should we just replace run_cli instead of run_cli_new?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The new run_cli_new is temporary, to allow this PR to run the perf regression workflow. Since it pulls down the current HEAD which has the pre-PR layout, I need to run the benchmark CLI from that revision with run_cli.

Once this PR is merged, then I can follow up with a PR to replace run_cli with run_cli_new, so that the perf regression workflow continues working using the src-python layout for everything.

Copy link
Contributor

Choose a reason for hiding this comment

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

Makes sense.

C_EXTENSION.md Outdated
compile setup import ionc module

The `amazon.ion.simpleion` module then makes use of this extension when it is available to provide more efficient
Ion parsing. Importing `amazon._ioncmodule` directly can determine if it is available, however simpleion also provides
Copy link
Contributor

Choose a reason for hiding this comment

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

reading and writing, loading and dumping, not just parsing is all i mean.

test = [
"pytest==8.3.3"
]
benchmarking = [
Copy link
Contributor

Choose a reason for hiding this comment

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

🙌

COMPONENT python_module
DESTINATION ${PY_BUILD_CMAKE_MODULE_NAME})

# install(FILES _ioncmodule.pyi
Copy link
Contributor

Choose a reason for hiding this comment

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

delete?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah! Yes, I'll get rid of that and follow up. There is a way to export python stubs for extensions to allow IDEs to present function and type information for an extension's methods. I left that as a reminder, but will follow up with it after this PR.

Copy link
Contributor

Choose a reason for hiding this comment

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

That would be neat.

@@ -1531,6 +1531,12 @@ PyObject* ionc_read(PyObject* self, PyObject *args, PyObject *kwds) {
return exception;
}

PyObject *ionc_version() {
Copy link
Contributor

Choose a reason for hiding this comment

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

nice.

@nirosys nirosys merged commit 85ee6ab into amazon-ion:master Jan 22, 2025
27 checks passed
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

Successfully merging this pull request may close these issues.

2 participants