question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Execute python code before parsing setup.cfg

See original GitHub issue

I’m currently trying to make my python packages PEP517/518 compatible. For this, I’m replacing the setup.py with a setup.cfg file and a project.toml file. This was quite straightforward to do for most of my packages, but for one package, I was not able to do this translation.

Package description

The package in question contains a (parent) python package that includes several packages that can also be installed as stand-alone python packages. For this, I created the following project structure:

    ├── main_package
    │   ├── python_module1
    │   ├── python_module3
    │   └── stand_alone_subpackage
    │       ├── stand_alone_subpackage
    │       │   └── subpackage_module
    │       │       └── script.py
    │       ├── pyproject.toml
    │       ├── requirements.txt
    │       ├── setup.py
    │       └── setup.cfg
    └── setup.py

I use the following setup.py file to install the subpackage in the parent package while getting rid of the redundant stand_alone_subpackage namespace.

from setuptools import setup, find_namespace_packages
import re

requirements = [
    "gym",
    "matplotlib",
    "numpy",
    "torch",
    "joblib",
    "tensorboard",
    "mpi4py",
    "psutil",
    "tqdm",
]

# Retrieve package list
PACKAGES = find_namespace_packages(include=["machine_learning_control*"])

# Add extra virtual shortened package for each of namespace_pkgs
namespace_pkgs = ["simzoo"]
exclusions = r"|".join(
    [r"\." + item + r"\.(?=" + item + r".)" for item in namespace_pkgs]
)
PACKAGE_DIR = {}
for package in PACKAGES:
    sub_tmp = re.sub(exclusions, ".", package)
    if sub_tmp is not package:
        PACKAGE_DIR[sub_tmp] = package.replace(".", "/")
PACKAGES.extend(PACKAGE_DIR.keys())

# Run python setup
setup(
    name="main_package",
    version="0.0.0",
    description=(
        "A parent python package."
    ),
    install_requires=requirements,
    packages=PACKAGES,
    package_dir=PACKAGE_DIR,
)

Why this works can be found inside a StackOverflow question I opened some months ago. The main thing it does is adds the virtual shortened modules to the PACKAGES and PACKAGES_DIR variables. This way the PythonClassinside thestandalone_subpackage` can be imported using the following import command:

from main_package.stand_alone_supbpackage import PythonClass
``

instead of using the actual (longer) module namespace:

```python
from main_package.stand_alone_subpackage.stand_alone_supbpackage import PythonClass

Translated setup.py file

I translated the setup.py to the following setup.cfg file:

[metadata]
name = main_package
version = 0.0.0

[options]
packages = find:
include_package_data = True
install_requires =
    gym
    matplotlib
python_requires = >=3.5

I, however, did not yet find a way to inject the extra virtual (shortened) modules before the packages = find: command is parsed. One possible way would be to read the PACKAGES and PACKAGE_DIR variables from a file. This would be similar to using the file: and attr: arguments for the package version parameter. While doing so, this file has to be created before the setup.cfg file is parsed. I, however, did not find a way to do this in setuptools 50.3.2. My question is, therefore, does anybody know a way of achieving the more complicated setup procedure I am trying to achieve?

Update

I just found out that you can combine both the setup.cfg and setup.py code. This allows me to define most of the setup information inside the setup.cfg file while keeping the packages and package_dir arguments inside the setup.py file. This allows me to inject the virtual shortened modules inside the setup.py file. I currently use the following setup.py file:


from setuptools import setup, find_namespace_packages
import re

with open("README.md") as f:
    readme = f.read()

# Add extra virtual shortened package for each of namespace_pkgs
PACKAGES = find_namespace_packages(include=["machine_learning_control*"])
namespace_pkgs = ["simzoo"]
exclusions = r"|".join(
    [r"\." + item + r"\.(?=" + item + r".)" for item in namespace_pkgs]
)
PACKAGE_DIR = {}
for package in PACKAGES:
    sub_tmp = re.sub(exclusions, ".", package)
    if sub_tmp is not package:
        PACKAGE_DIR[sub_tmp] = package.replace(".", "/")
PACKAGES.extend(PACKAGE_DIR.keys())

# Run python setup
setup(
    packages=PACKAGES, package_dir=PACKAGE_DIR,
)

If anybody knows if it is possible to put everything inside the setup.cfg file please let me know. Thanks a lot in advance!

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:5 (2 by maintainers)

github_iconTop GitHub Comments

1reaction
webknjazcommented, Dec 7, 2020

Sounds about right

1reaction
nschloecommented, Dec 7, 2020

As webknjaz said, a setup.cfg file doesn’t allow for much logic at all. If you’re getting more complex than normal (and that’s what your subpackage setup is), you can always keep a stripped-down setup.py around. It’s not unusual either, and necessary for example when you build packages with C++ sources in them. Check out pygalmesh (a package of mine): All metadata in setup.cfg, and the rest of the logic in setup.py. Perhaps this will help.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Configuring setuptools using setup.cfg files
cfg ) to define a package's metadata and other options that are normally supplied to the setup() function (declarative config). This approach not...
Read more >
configparser — Configuration file parser — Python 3.11.1 ...
This module provides the ConfigParser class which implements a basic configuration language which provides a structure similar to what's found in Microsoft ...
Read more >
How to get `setup.cfg` metadata at the command line (Python)
cfg file to parse at all, project name and version would be specified in the TOML (PEP621). Then this approach fails, but the...
Read more >
How to Write a Configuration file in Python | by Xiaoxu Gao
Good configuration management should allow the software to be executed in any environment without changing the code. It helps Ops to manage ...
Read more >
ConfigParser – Work with configuration files - PyMOTW
Config file sections are identified by looking for lines starting with [ and ... Testing if a section exists before calling get() avoids...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found