Skip to content

Add: hatch plus meson-python python package example to guidebook #274

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

Merged
merged 5 commits into from
May 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
3 changes: 3 additions & 0 deletions examples/extension-hatch/README
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
An example Python package used to support Python packaging tutorials
Copy link
Member

Choose a reason for hiding this comment

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

@ucodery could you add a bit more about how this works with meson-python? the key elements that make it work which i suspect are the meson.build files?

it seems like hatch just magically recognizes it and then builds for us. thank you AGAIN for this. i know this was a lot of work between you - @kenseehart and @ryanskeith !

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

The "magic" is that this project declares mesonpy as its backend in pyproject.toml, which is a universal tool-agnostic standard. Hatch is compliant with PEP standards, thus it acquiesces and when asked to build the project uses mesonpy to create the wheel, which hatch can then do more tool-agnostic actions with, like install locally.

Copy link
Member

Choose a reason for hiding this comment

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

so related to below - what i'm remembering is folks arguing about hatch's approach to plugins ... i could probably find it for you. this might have been BEFORE pycon 2023 (so before we met) ... and that argument could actually have been around hatchling (the backend) and at the time hatch did NOT support other backends.

this makes sense to me now. thank you for the explanation. in this case i think you are saying hatch the front-end tool just runs build and build knows to use mesonpy which knows to find the meson.build file? so everything just works as it should.


This project demonstrates mixing C and Python code by using the frontend hatch with the backend mesonpy
4 changes: 4 additions & 0 deletions examples/extension-hatch/examplePy/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
from .temperature import celsius_to_fahrenheit, fahrenheit_to_celsius

__all__ = ["celsius_to_fahrenheit", "fahrenheit_to_celsius"]
__version__ = "0.1.0dev0"
15 changes: 15 additions & 0 deletions examples/extension-hatch/examplePy/meson.build
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
py.extension_module(
'temperature',
'temperature.c',
install: true,
subdir: 'examplePy'
)

python_sources = [
'__init__.py'
]

py.install_sources(
python_sources,
subdir: 'examplePy'
)
63 changes: 63 additions & 0 deletions examples/extension-hatch/examplePy/temperature.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
#define PY_SSIZE_T_CLEAN
#include <Python.h>

static PyObject *
temperature_celsius_to_fahrenheit(PyObject *self, PyObject *args)
{
long celsius;
Copy link
Contributor

Choose a reason for hiding this comment

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

Recommend adding fahrenheit variable and make the assignment correctly named (fahrenheit = ...celsius and celsius = ...fahrenheit

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

great suggestion. All seems to work now, thanks!

long fahrenheit;
PyObject *ret;

if (!PyArg_ParseTuple(args, "l", &celsius))
return NULL;

fahrenheit = (celsius * 9/5) + 32;

ret = PyLong_FromLong(fahrenheit);
Py_INCREF(ret);
return ret;
}

static PyObject *
temperature_fahrenheit_to_celsius(PyObject *self, PyObject *args)
{
long fahrenheit;
long celsius;
PyObject *ret;

if (!PyArg_ParseTuple(args, "l", &fahrenheit))
return NULL;

celsius = (fahrenheit - 32) * 9/5;

ret = PyLong_FromLong(celsius);
Py_INCREF(ret);
return ret;
}

static PyMethodDef CoreMethods[] = {
{"celsius_to_fahrenheit", temperature_celsius_to_fahrenheit, METH_VARARGS, "Convert temperature from Celsius to Fahrenheit"},
{"fahrenheit_to_celsius", temperature_fahrenheit_to_celsius, METH_VARARGS, "Convert temperature from Fahrenheit to Celsius"},
{NULL, NULL, 0, NULL} /* Sentinel */
};

static struct PyModuleDef temperaturemodule = {
PyModuleDef_HEAD_INIT,
"temperature", /* name of module */
NULL, /* module documentation, may be NULL */
-1, /* size of per-interpreter state of the module,
or -1 if the module keeps state in global variables. */
CoreMethods
};

PyMODINIT_FUNC
PyInit_temperature(void)
{
PyObject *m;

m = PyModule_Create(&temperaturemodule);
if (m == NULL)
return NULL;

return m;
}
20 changes: 20 additions & 0 deletions examples/extension-hatch/meson.build
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
project(
'examplePy',
'c',
version: '0.1.dev0',
license: 'MIT',
meson_version: '>= 0.64.0',
default_options: [
'buildtype=debugoptimized',
'c_std=c99',
'cpp_std=c++14',
],
)

cc = meson.get_compiler('c')

py_mod = import('python')
py = py_mod.find_installation(pure: false)
py_dep = py.dependency()

subdir('examplePy')
23 changes: 23 additions & 0 deletions examples/extension-hatch/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
[build-system]
build-backend = "mesonpy"
requires = [
"meson-python>=0.13.0rc0",
]

[project]
name = "examplePy"
version = "0.1"
authors = [
{name = "Some Maintainer", email = "[email protected]"},
]
maintainers = [
{name = "All the contributors"},
]
description = "An example Python package used to support Python packaging tutorials"
keywords = ["pyOpenSci", "python packaging"]
readme = "README"
classifiers = [
"Programming Language :: Python :: 3",
"License :: OSI Approved :: BSD License",
"Operating System :: OS Independent",
]
Loading