Python Feature¶
The “python” feature is the base feature required for all python projects.
Medikit only supports python 3.5+ projects, which we believe is a future proof choice.
Overview¶
from medikit import require
# load python feature (idempotent).
python = require('python')
# configure our package.
python.setup(
name = 'awesome-library',
author = 'Chuck Norris',
)
# add base and extras requirements, with "loose" versionning (the frozen version fits better in requirements*.txt)
python.add_requirements(
'django',
dev=[
'pytest',
],
)
Usage¶
To use the Python Feature, make sure your Projectfile contains the following:
from medikit import require
python = require('python')
The python handle is a PythonConfig
instance, and can be used to customize the feature.
The python features makes your package real (at least if it uses python). Medikit was written originally for python, and although it’s not completely true anymore, a lot of features depends on this.
Setup¶
You can define the setuptools’ setup(…) arguments using python.setup(…):
python.setup(
name='medikit',
description='Opinionated python 3.5+ project management.',
license='Apache License, Version 2.0',
url='https://github.com/python-medikit/medikit',
download_url='https://github.com/python-medikit/medikit/tarball/{version}',
author='Romain Dorgueil',
author_email='romain@dorgueil.net',
entry_points={
'console_scripts': ['medikit=medikit.__main__:main'],
}
)
This is required for any python package.
Requirements¶
Requirements are managed using two different mechanisms:
- The setup.py file, autogenerated and overriden by medikit, will contain the “loose” requirements as you define them. You’re encouraged to use “~x.y.z” or “~x.y” versions. You should use each versions (“==x.y.z”) only in case you’re relying on a package you never want to update.
- The requirements*.txt files will contain frozen version numbers. Those requirements will be commited, and you can ensure the reproducibility of your installs by using pip install -r requirements.txt instead of python setup.py install.
In medikit, we call what is present in setup.py “constraints”, and what is in requirements*.txt files “requirements”.
Let’s see how we can set them:
python.add_requirements(
"requests ~2.18"
)
This will set a constraint on any semver compatible requests version, and update the requirement to latest requests version, compatible with the constraint (as of writing, 2.18.4).
It means that if you run make install, python setup.py install or pip install -e ., requests will only be downloaded and installed if there is no installation complying to the constraint in your current env. This is very handy if you have local, editable packages that you want to use instead of PyPI versions.
It also means that when you run pip install -r requirements.txt, you’ll get requests 2.18.4 even if a new version was released.
If you want to upgrade to the new released version, use make update-requirements, review the git changes (git diff –cached), test your software with the new version and eventually (git) commit to this dependency update.
Constraints¶
Sometimes, you want a dependency to only be a constraint, and not a frozen requirement.
python.add_constraints(
"certifi ~2018,<2019"
)
This will ensure that your env contains “certifi”, a version released in the 2018 year, but also says you don’t care which one.
This is an advanced feature that you should only use if you really know what you’re doing, otherwise, use a requirement (reproducibility of installs is gold).
Extras¶
You can create as much “extras” as you want.
As a default, medikit will create a “dev” extra, but you can add whatever you need:
python.add_requirements(
sql=[
'sqlalchemy ~=1.2.5',
]
)
The same works with constraints, of course.
Changing package generation behaviour¶
Medikit creates the necessary directory structure for your package, named after your package name defined in the python.setup() call.
If you don’t want medikit to create this directory structure:
python.create_packages = False
Medikit also considers you’ll need a version number tracking mechanism for your project. It creates a _version.py file in your package’s root directory. To override this file’s name:
python.version_file = 'my_version.py'
Configuration¶
Implementation¶
-
class
medikit.feature.python.
PythonFeature
(dispatcher)[source]¶ Adds the requirements/requirements-dev logic, virtualenv support, setup.py generation, a few metadata files used by setuptools…
-
Config
¶ alias of
PythonConfig
-
on_make_generate
(event)[source]¶ Environment variables
PACKAGE
PYTHON
PYTHON_BASENAME
PYTHON_DIR
PYTHON_REQUIREMENTS_FILE
PYTHON_REQUIREMENTS_DEV_FILE
Shortcuts -
PIP
-PIP_INSTALL_OPTIONS
Make targets
install
install-dev
Parameters: event (MakefileEvent) – Listens to
medikit.feature.make.on_generate
event (priority: -100)
-
on_start
(event)[source]¶ Events
medikit.feature.python.on_generate
(with the sameProjectEvent
we got, todo: why not deprecate it in favor of higher priority medikit.on_start?)
Files
<yourpackage>/__init__.py
MANIFEST.in
README.rst
classifiers.txt
requirements-dev.txt
requirements.txt
setup.cfg
setup.py
(overwritten)
Parameters: event (ProjectEvent) – Listens to
medikit.on_start
event (priority: -100)
-
requires
= {'make'}¶
-