jaraco / jaraco.packaging

MIT License
4 stars 4 forks source link

Q: how to obtain author in conf.py? #15

Open kloczek opened 3 months ago

kloczek commented 3 months ago

Sorry for the question raised as issue ticket but I don't see better place to ask and I cannot find any examples of obtaining module metadata after importing jaraco.packaging.sphinx or place it conf.py extensions.

On use jaraco.packaging.sphinx in conf.py how can I obtain for example author? 🤔

jaraco commented 2 months ago

I'm not familiar enough with Sphinx to know the answer to that question. I created the plugin for Sphinx so that I wouldn't have to configure the author/package_url/version, etc in conf.py. Given that Sphinx has to read extensions=['jaraco.packaging.sphinx'] from conf.py before jaraco.packaging.sphinx could possibly have any effect, I don't think it's possible to access the config values in conf.py.

What is it you're seeking to do with the values?

What you might be able to do is import jaraco.packaging.sphinx to imperatively execute the code, but right now, this extension doesn't expose the functionality to simply query it. Instead, it expects to be run only as the extension and set the config there. If it would help, I'd definitely consider adding a function you could call to get the metadata.

You could, I suppose, call jaraco.packaging.metadata.load() for an importlib.metadata.PackageMetadata object.

Note that due to #17 (and linked issues), the meaning of Author is messy.

kloczek commented 2 months ago

What is it you're seeking to do with the values?

I have already packaged +1.25k python modules as rpm packages and my typical packaging procedure is if module has generated sphinx based documentation I'm rendering it as python-foo(3) man page. To add that typically I'm adding patch which adds in conf.py

man_pages = [
    (
        "index",
        "python-foo",
        "foo Python Module Documentation",
        author,
        3,
    )
]

If jaraco-packaging already is used it is possible to generalize this patch by obtaining for example author over jaraco-packaging. This is why I'm looking for kind of template solution for above 😋

kloczek commented 2 months ago

You could, I suppose, call jaraco.packaging.metadata.load() for an importlib.metadata.PackageMetadata object.

Using importlib.metadata is not an useful option 😞 Why? Because typical python module packaging procedure used not only by me but by Fedora and few others performs build from non-root without installing module. If seruptools or setuptools-scm is used as pep517 backend during for example build execution module metadata directory is generated but in case pdb-backedn, whey, poetry-core, hatchlings and few other such directory do not generates at all and all metadata are inside generated dist/foo-*.whl archive.

In other words I'm looking for some greneric method which provide reading necessary data like project name, author, version from pyproject.toml (I don't care about use setup.py/setup.cfg because IMO sooner or later all those modules will migrate to pyproject.toml)

jaraco commented 2 months ago

I'm afraid pep517 is going to be the only reliable way to get that metadata. Although pyproject.toml does provide one fairly standard way for users to supply metadata, the build backend could opt to get the values from other sources (like how setuptools gets the version from SCM metadata). I have aspirations to create a zero-config backend that gets the author and project name and description from git and GitHub sources (avoiding the need to configure those things in multiple places). The only standard you can rely on for getting metadata for a (built or unbuilt) package is the PEP 517/518 process.

In jaraco.packaging.metadata.load(), I've attempted to create a mechanism by which you could have the build dependencies pre-installed and bypass the isolated build in order to load the metadata (just set BUILD_ENVIRONMENT=current prior to invoking load()). Have you had a chance to explore using that instead of the deprecated JARACO_PACKAGING_SPHINX_WHEEL (https://github.com/pypa/build/issues/556)? I'm hoping that unlocks the ability for your packaging routines to get metadata reliably.

Note that you're probably going to have to do this anyway in order to support other things like the sphinx plugin or the checkdocs plugin.

To add that typically I'm adding patch which adds in conf.py

Because of the dynamism you're looking for here, it may be better to add a plugin for sphinx that performs this configuration, thought that admittedly would be a substantial bit of work and might still require editing the conf.py file to enable the extension.

kloczek commented 2 months ago

I have aspirations to create a zero-config backend that gets the author and project name and description from git and GitHub sources (avoiding the need to configure those things in multiple places). The only standard you can rely on for getting metadata for a (built or unbuilt) package is the PEP 517/518 process.

This would entangle your module to it. IMO better would be extract data only over pyproject.toml because it would make that pep517 backend independent. If for examplel setuptools-scm would e used it will provide version taken from git metadata or if those metadata will be not present it will be possible to inject that by $SETUPTOOLS_SCM_PRETEND_VERSION env variable. Let me show you my rpm macro used to build python nodules

%pyproject_wheel() %{expand:\\\
%{set_build_flags} \\\
PBR_VERSION=%(v=%{version}; echo ${v%~*}) \\\
PDM_BUILD_SCM_VERSION=%(v=%{version}; echo ${v%~*}) \\\
SETUPTOOLS_SCM_PRETEND_VERSION=%(v=%{version}; echo ${v%~*}) \\\
%__python3 -sBm build -w --no-isolation }

Fedora macro is vey similar bur they are using only $SETUPTOOLS_SCM_PRETEND_VERSION (mine supports much more and this is why I'm able to use in in +95% of all python modules builds autogenerated from git tag tar ball as source:

[tkloczko@pers-jacek SPECS]$ grep "Source:.*%{VCS}/" python-*spec -l | wc -l; ls -1 python-*spec |wc -l
1187
1243

Here is example of my spec for your module 😋

# BUG: no pytest units? https://github.com/jaraco/jaraco.packaging/issues/6
# NOTE: --exit-0-if-no-units pytest option requires G2V pytest
%bcond_without  loopy_deps

Summary:        Tools to supplement packaging Python releases
Name:           python-jaraco-packaging
Version:        9.7.0%{!?with_loopy_deps:~no_loopy_deps}
Release:        2%{?dist}
License:        MIT (https://spdx.org/licenses/MIT.html)
URL:            https://pypi.org/project/jaraco.packaging/
VCS:            https://github.com/jaraco/jaraco.packaging/
Source:         %{VCS}/archive/v%(v=%{version}; echo ${v%~*})/%{name}-%(v=%{version}; echo ${v%~*}).tar.gz
Patch:          %{name}-add_module_path_in_conf.py.patch
Patch:          %{name}-man3_level.patch
BuildArch:      noarch
BuildRequires:  python3dist(build)
BuildRequires:  python3dist(domdf-python-tools)
BuildRequires:  python3dist(installer)
BuildRequires:  python3dist(setuptools)
BuildRequires:  python3dist(setuptools-scm)
%{?with_loopy_deps:
BuildRequires:  python3dist(rst-linker)
BuildRequires:  python3dist(sphinx)}
BuildRequires:  python3dist(wheel)
# CheckRequires:
%{?with_loopy_deps:
BuildRequires:  python3dist(jaraco-context)
BuildRequires:  python3dist(pip)
BuildRequires:  python3dist(pytest)
BuildRequires:  python3dist(pytest-mypy)}
Obsoletes:      python3-jaraco
Obsoletes:      python-jaraco
Obsoletes:      python-jaraco-packaging-doc

%define         loopy_dep_with \
                python3dist(jaraco-context) \
                python3dist(pip) \
                python3dist(pytest) \
                python3dist(pytest-mypy) \
                python3dist(rst-linker) \
                python3dist(sphinx) \

%description
Tools for packaging.dependency_tree A dist-utils command for reporting the
dependency tree as resolved by setup-tools. Use after installing a package.show
A dist-utils command for reporting the attributes of a distribution, such as the
version or author name.

%prep
%autosetup -p1 -n jaraco.packaging-%(v=%{version}; echo ${v%~*})

%__rm -rf SPECPARTS

%{!?with_network:
echo 'intersphinx_mapping.clear()' >> docs/conf.py}

%build
%pyproject_wheel
%{?with_loopy_deps:
JARACO_PACKAGING_SPHINX_WHEEL=$(ls -1 $PWD/dist/*whl) \
%sphinx_build_man}

%install
%pyproject_install

%{?with_loopy_deps:
%__install -Dm644 build/sphinx/man/*.3 -t %{buildroot}%{_mandir}/man3}

%check
%{?with_loopy_deps:
%pytest}

%files
%{?with_loopy_deps:
%{_mandir}/man3/*}
%{python3_sitelib}/jaraco
%{python3_sitelib}/jaraco.packaging-*.*-info

As I'm using if it is only possible autogerated from git tag tar ball as input source this allows me to inject version to the build no matter which pep517 backend is used. setuptools-scm uses $SETUPTOOLS_SCM_PRETEND_VERSION, $PBR_VERSION is used by hatchlings with hatch-vcs and IIRC whey, and $PDM_BUILD_SCM_VERSION by pdb-backend and poetry-core.

Using pep517 as deliverer of those metadata will make that much more flexible and independent from pep517 backends.

So IMO it is some need to provide basic project metadata in conf.py but it should IMO be taken only over pyproject.toml. What is behind that file should be completely transparent.

PS. BTW would you accept as PR my add_module_path_in_conf.py patch? 🤔

--- a/docs/conf.py
+++ b/docs/conf.py
@@ -1,3 +1,8 @@
+
+import sys
+import os
+sys.path.insert(0, os.path.abspath(".."))
+
 extensions = [
     'sphinx.ext.autodoc',
     'jaraco.packaging.sphinx',

This small patch allows build documentation without have jaraco-packaging installed and it guarantees that documentation will be always generated only out of source tree.