Setup dev environment
These notes are mostly for me, but I suppose if anyone ever takes an interest in submitting a pull request, the documentation here will help get the local dev environment set up.
Requirements
- PDM
pdmis used to manage this package and its dependencies- Take a look at the project's
pyproject.tomlfor available dependency groups. As you develop modules, consider which dependency group they belong in, i.e. most dependencies should not be added to the default dependency group.- If you are working on a FastAPI module, for example, add new dependencies to the
fastapiandallgroups. pdm add -G fastapi <package>pdm add -G all <package>
- If you are working on a FastAPI module, for example, add new dependencies to the
- There are also a number of project scripts configured in the
pyproject.tomlfile, which aid in development- Scripts are declared in sections that look like
[tool.pdm.scripts.<script-name>], and can be called withpdm run <script-name> - For example, to run the PDM script that calls
blackandruffto format code:pdm run lint
- To run the PDM script that exports a
requirements.txtfile:pdm run export
- Scripts are declared in sections that look like
- (Optional) Pre-commit
- There are some
pre-commitscripts configured, too, for things like linting/formatting the code during commit.- To see configured
pre-commitsteps, check.pre-commit-config.yaml
- To see configured
- To use these
pre-commitscripts, they need to be installed locally withpdm run pre-commit install - To disable the pre-commit hooks, run
pdm run pre-commit uninstall
Using the VSCode Workspace
If you use Visual Studio Code as your text editor, you can open the workspace in the .vscode directory to have a more focused view of the code.
Developing new modules
The red-utils package separates modules into std and ext, which are respectively modules that require only the modules in the Python stdlib, or extended modules that require external dependencies.
Any modules in the red_utils.std package should rely only on Python stdlib packages. In fact, anything outside of the red_utils.ext module should rely only on the Python stdlib (i.e. red_utils.core, red_utils.domain).
If developing a utility for an external dependency (like sqlalchemy, fastapi, pandas/polars, etc), add the module to the red_utils.ext group and keep all code related to that dependency beneath the red_utils.ext module.
You can reference other modules in red_utils.ext to learn how to use pkgutils to control import flow. There are many if pkgutil.find_loader("<package-name>") lines throughout the red-utils app; the .find_loader() function searches for a package in the global namespace, and if it is not found, that module is not imported. This helps keep red-utils stable if, for example, a user installs a dependency group instead of the entirety of red-utils.
As an example real-world scenario, if a user installs red-utils[http], they will only have access to the red_utils.ext modules for dependencies in the http dependency group in the project's pyproject.toml. A package like sqlalchemy is not installed with this group, and so red_utils.ext.sqlalchemy_utils will not be imported or available to the user. Type hinting in an IDE will not suggest red_utils.ext.sqlalchemy_utils as an importable module, and red-utils will skip any modules looking for sqlalchemy.
Testing with PDM
You can test a new build before pushing a release by creating a new PDM project somewhere else on the system and importing the path to the red-utils repository.
For example, if creating a module pandas_utils for utility functions related to Pandas DataFrames, and assuming the red-utils repository was cloned to ~/git/red-utils, you would follow a process like the following:
- In the
~/git/red-utilsdirectory, installpandasin the[all]and[data]dependency groups pdm add -G all pandaspdm add -G data pandas- Create a directory at
red_utils.ext.pandas_utils - In this directory, create a file
operations.pyand add some utility functions (such as a function to scan a directory and load all CSV files into a DataFrame). - Create
red_utils/ext/pandas_utils/__init__.py:- Contents of
__init__.py:
- Contents of
- In
red_utils/ext/__init__.py, add apkgutil.find_loader()line to detect ifpandasis installed, then loadpandas_utils- Contents of
red_utils/ext/__init__.py:
- Contents of
- The new
pandas_utilsmodule should be available ifpandasis available in the Python path - Build the app with
pdm build - Create a new directory somewhere outside the repository, i.e.
~/testing/red-utils - Initialize the project (example uses
pdm):pdm init- Answer the initialization prompts
- Add
red-utilsfrom its local pathpdm add ~/git/red-utils
- To remove the local dependency, just run
pdm remove ~/git/red-utils