You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 
Hannu Nyman 6c2235253f
Merge pull request #11872 from jefferyto/python3-makefile-cleanup
5 years ago
..
Flask treewide: Use pypi.mk for Python packages 5 years ago
Jinja2 Jinja2: update to version 2.10.3 5 years ago
MarkupSafe treewide: Use pypi.mk for Python packages 5 years ago
Werkzeug treewide: Use pypi.mk for Python packages 5 years ago
bcrypt python-libraries: Remove Python 2 variants 5 years ago
click treewide: Use pypi.mk for Python packages 5 years ago
click-log click-log: fix circular dependency 6 years ago
django python3-django: update to version 3.0.5 5 years ago
django-appconf python-libraries: Remove Python 2 variants 5 years ago
django-compressor python-libraries: Remove Python 2 variants 5 years ago
django-formtools python-libraries: Remove Python 2 variants 5 years ago
django-jsonfield python-libraries: Remove Python 2 variants 5 years ago
django-picklefield python-libraries: Remove Python 2 variants 5 years ago
django-postoffice python-libraries: Remove Python 2 variants 5 years ago
django-ranged-response python-libraries: Remove Python 2 variants 5 years ago
django-restframework django1: Add python3-django1 package 5 years ago
django-restframework39 python-libraries: Remove Python 2 variants 5 years ago
django-simple-captcha python-libraries: Remove Python 2 variants 5 years ago
django-statici18n python-libraries: Remove Python 2 variants 5 years ago
django-webpack-loader python-libraries: Remove Python 2 variants 5 years ago
django1 python-libraries: Remove Python 2 variants 5 years ago
gunicorn python3: Rename canned recipes in python3-package.mk 5 years ago
itsdangerous treewide: Use pypi.mk for Python packages 5 years ago
micropython micropython: Update to 1.94 6 years ago
micropython-lib micropython-lib: Update to 1.9.3 6 years ago
openpyxl openpyxl: bump to version 3.0.3 5 years ago
passlib python-libraries: Remove Python 2 variants 5 years ago
pillow pillow: bump to version 7.1.1 5 years ago
pyjwt python-libraries: Remove Python 2 variants 5 years ago
pymysql pymysql: make python3-cryptography optional 5 years ago
pyodbc python-libraries: Remove Python 2 variants 5 years ago
python-aiohttp python-aiohttp: update to version 3.6.1 5 years ago
python-aiohttp-cors treewide: Use pypi.mk for Python packages 5 years ago
python-appdirs treewide: Use pypi.mk for Python packages 5 years ago
python-asn1crypto python-asn1crypto: bump to version 1.3.0 + rework 5 years ago
python-astral python-libraries: Remove Python 2 variants 5 years ago
python-async-timeout treewide: Use pypi.mk for Python packages 5 years ago
python-atomicwrites python-atomicwrites: add new package 5 years ago
python-attrs python-libraries: Remove Python 2 variants 5 years ago
python-automat python-libraries: Remove Python 2 variants 5 years ago
python-awscli python-libraries: Remove Python 2 variants 5 years ago
python-boto3 treewide: Use pypi.mk for Python packages 5 years ago
python-botocore python-libraries: Remove Python 2 variants 5 years ago
python-cachelib treewide: Use pypi.mk for Python packages 5 years ago
python-cachetools treewide: Use pypi.mk for Python packages 5 years ago
python-certifi python-libraries: Remove Python 2 variants 5 years ago
python-cffi python-libraries: Remove Python 2 variants 5 years ago
python-chardet python-libraries: Remove Python 2 variants 5 years ago
python-colorama python-libraries: Remove Python 2 variants 5 years ago
python-constantly python-libraries: Remove Python 2 variants 5 years ago
python-contextlib2 treewide: Use pypi.mk for Python packages 5 years ago
python-crypto python-libraries: Remove Python 2 variants 5 years ago
python-cryptodome python-cryptodome: update to 3.9.7 5 years ago
python-cryptodomex python-cryptodome: update to 3.9.7 5 years ago
python-cryptography python-cryptography: Update to 2.9, remove setup patch 5 years ago
python-curl python-libraries: Remove Python 2 variants 5 years ago
python-dateutil python-libraries: Remove Python 2 variants 5 years ago
python-decorator treewide: add PKG_CPE_ID for cvescanner 5 years ago
python-defusedxml python-libraries: Remove Python 2 variants 5 years ago
python-dns python-libraries: Remove Python 2 variants 5 years ago
python-docutils python-libraries: Remove Python 2 variants 5 years ago
python-et_xmlfile python-libraries: Remove Python 2 variants 5 years ago
python-evdev python-libraries: Remove Python 2 variants 5 years ago
python-flask-login python-flask-login: update to version 0.5.0 5 years ago
python-gmpy2 python-libraries: Remove Python 2 variants 5 years ago
python-gnupg python3: Rename canned recipes in python3-package.mk 5 years ago
python-hyperlink python-libraries: Remove Python 2 variants 5 years ago
python-idna python-libraries: Remove Python 2 variants 5 years ago
python-ifaddr treewide: Use pypi.mk for Python packages 5 years ago
python-incremental python-libraries: Remove Python 2 variants 5 years ago
python-influxdb treewide: Use pypi.mk for Python packages 5 years ago
python-intelhex treewide: Use pypi.mk for Python packages 5 years ago
python-jdcal python-libraries: Remove Python 2 variants 5 years ago
python-jmespath python-libraries: Remove Python 2 variants 5 years ago
python-jsonpath-ng treewide: Use pypi.mk for Python packages 5 years ago
python-libmodbus python-libraries: Remove Python 2 variants 5 years ago
python-lxml python3: Rename canned recipes in python3-package.mk 5 years ago
python-markdown python-markdown: update to version 3.2.1 5 years ago
python-more-itertools python-more-itertools: update to version 8.2.0 5 years ago
python-multidict treewide: Use pypi.mk for Python packages 5 years ago
python-mysqlclient python-libraries: Remove Python 2 variants 5 years ago
python-netdisco treewide: Use pypi.mk for Python packages 5 years ago
python-oauthlib python-libraries: Remove Python 2 variants 5 years ago
python-packaging python-packaging: add new package 5 years ago
python-paho-mqtt python-paho-mqtt: Update to version 1.5.0 5 years ago
python-parsley python-libraries: Remove Python 2 variants 5 years ago
python-pip-conf python-pip-conf: split package away from python package 7 years ago
python-pluggy python-pluggy: add new package 5 years ago
python-ply python-libraries: Remove Python 2 variants 5 years ago
python-py python-py: update to version 1.8.1 5 years ago
python-pyasn1 python-libraries: Remove Python 2 variants 5 years ago
python-pyasn1-modules python-libraries: Remove Python 2 variants 5 years ago
python-pycparser python-libraries: Remove Python 2 variants 5 years ago
python-pyopenssl python-libraries: Remove Python 2 variants 5 years ago
python-pyotp pyotp: update to version 2.3.0 5 years ago
python-pyparsing python-pyparsing: update to version 2.4.7 5 years ago
python-pyrsistent treewide: Use pypi.mk for Python packages 5 years ago
python-pyserial python-libraries: Remove Python 2 variants 5 years ago
python-pytest python-pytest: add new package 5 years ago
python-pytz python-libraries: Remove Python 2 variants 5 years ago
python-qrcode python-libraries: Remove Python 2 variants 5 years ago
python-rcssmin python-libraries: Remove Python 2 variants 5 years ago
python-requests python-libraries: Remove Python 2 variants 5 years ago
python-requests-oauthlib python-libraries: Remove Python 2 variants 5 years ago
python-rsa python-libraries: Remove Python 2 variants 5 years ago
python-s3transfer python-libraries: Remove Python 2 variants 5 years ago
python-schedule treewide: Use pypi.mk for Python packages 5 years ago
python-schema python-schema: update to version 0.7.1 5 years ago
python-sentry-sdk python-sentry-sdk: Update to version 0.13.5 5 years ago
python-service-identity python-libraries: Remove Python 2 variants 5 years ago
python-simplejson python-libraries: Remove Python 2 variants 5 years ago
python-six python3: Rename canned recipes in python3-host.mk 5 years ago
python-slugify python-slugify: update to version 4.0.0 5 years ago
python-sqlalchemy python-sqlalchemy: update to version 1.3.13 5 years ago
python-stem python-stem: add a new package 5 years ago
python-twisted python-libraries: Remove Python 2 variants 5 years ago
python-urllib3 python-libraries: Remove Python 2 variants 5 years ago
python-voluptuous python-libraries: Remove Python 2 variants 5 years ago
python-voluptuous-serialize python-voluptuous-serialize: update to version 2.3.0 5 years ago
python-wcwidth python-wcwidth: update to version 0.1.9 5 years ago
python-yaml python-yaml: update to version 5.3.1 5 years ago
python-yarl treewide: Use pypi.mk for Python packages 5 years ago
python-zeroconf python-zeroconf: update to version 0.24.4 5 years ago
python-zipp python-zipp: update to version 3.1.0 5 years ago
python-zope-interface python-zope-interface: Update to 5.0.2 5 years ago
python3 python3: Change PYTHON_VERSION references to PYTHON3_VERSION 5 years ago
python3-asgiref python3-asgiref: update version to 3.2.7 5 years ago
python3-bottle treewide: Use pypi.mk for Python packages 5 years ago
python3-django-cors-headers django1: Add python3-django1 package 5 years ago
python3-django-etesync-journal django1: Add python3-django1 package 5 years ago
python3-drf-nested-routers django1: Add python3-django1 package 5 years ago
python3-maxminddb python-maxminddb: update to version 1.5.2 5 years ago
python3-netifaces python-packages: Clean up Makefiles 5 years ago
python3-packages python3: Rename canned recipes in python3-package.mk 5 years ago
python3-pyroute2 python-packages: Clean up Makefiles 5 years ago
python3-speedtest-cli python3-speedtest-cli: a new package 5 years ago
python3-sqlparse python3-sqlparse: update to 0.3.1 5 years ago
python3-unidecode python-packages: Clean up Makefiles 5 years ago
ruamel-yaml python-libraries: Remove Python 2 variants 5 years ago
text-unidecode python-libraries: Remove Python 2 variants 5 years ago
vobject python-libraries: Remove Python 2 variants 5 years ago
xmltodict treewide: Use pypi.mk for Python packages 5 years ago
README.md python: Update readme 5 years ago
pypi.mk python,python3: Add PYPI_SOURCE_NAME to pypi.mk 5 years ago
python-package-install.sh python3: Move functionality into python3-package.mk 5 years ago
python3-host.mk python3: Rename canned recipes in python3-host.mk 5 years ago
python3-package.mk python3: Use PYTHON3_PKG_BUILD to control default Python package build 5 years ago
python3-version.mk python3-pip: Symlink pip3 to pip3.8 5 years ago

README.md

Python packages folder

Table of contents

  1. Description
  2. Introduction
  3. Python 2 end-of-life
  4. Using Python in external/other package feeds
  5. Build considerations
  6. General folder structure
  7. Building a Python package
    1. Include python3-package.mk
    2. Add Package/<PKG_NAME> OpenWrt definitions
    3. Wrapping things up so that they build
    4. Customizing things
    5. Host-side Python packages for build

Description

This section describes specifics for the Python packages that are present in this repo, and how things are structured.

In terms of license, contributing guide, etc, all of that information is described in the top README.md file, and it applies here as well. This document attempts to cover only technical aspects of Python packages, and maybe some explanations about how things are (and why they are as they are).

Introduction

This sub-tree came to exist after a number of contributions (Python packages) were made to this repo, and the lang subtree grew to a point where a decision was made to move all Python packages under lang/python.

It contains the Python 3 interpreter and Python packages. Most of the Python packages are downloaded from pypi.org. Python packages from pypi.org are typically preferred when adding new packages.

If more packages (than the ones packaged here) are needed, they can be downloaded via pip. Note that the versions of pip & setuptools [available in this repo] are the ones that are packaged inside the Python package (yes, Python comes packaged with pip & setuptools).

Python 2 end-of-life

Python 2 will not be maintained past 2020. All Python 2 packages have been removed from the packages feed (this repo) and archived in the abandoned packages feed.

Using Python in external/other package feeds

In the feeds.conf (or feeds.conf.default file, whatever is preferred), the packages repo should be present.

Example

src-git packages https://git.openwrt.org/feed/packages.git
src-git luci https://git.openwrt.org/project/luci.git
src-git routing https://git.openwrt.org/feed/routing.git
src-git telephony https://git.openwrt.org/feed/telephony.git
#
#
src-git someotherfeed https://github.com/<github-user>/<some-other-package>

Assuming that there are Python packages in the <some-other-package>, they should include python3-package.mk like this:

include $(TOPDIR)/feeds/packages/lang/python/python3-package.mk

Same rules apply for python3-package.mk as the Python packages in this repo.

One important consideration:: if the local name is not packages, it's something else, like openwrt-packages. And in feeds.conf[.default] it's:

src-git openwrt-packages https://git.openwrt.org/feed/packages.git

Then, the inclusions also change:

include $(TOPDIR)/feeds/openwrt-packages/lang/python/python3-package.mk

Each maintainer[s] of external packages feeds is responsible for the local name, and relative inclusion path back to this feed (which is named packages by default).

In case there is a need/requirement such that the local package feed is named something else than packages, one approach to make the package flexible to change is:

PYTHON3_PACKAGE_MK:=$(wildcard $(TOPDIR)/feeds/*/lang/python/python3-package.mk)

# verify that there is only one single file returned
ifneq (1,$(words $(PYTHON3_PACKAGE_MK)))
ifeq (0,$(words $(PYTHON3_PACKAGE_MK)))
$(error did not find python3-package.mk in any feed)
else
$(error found multiple python3-package.mk files in the feeds)
endif
else
$(info found python3-package.mk at $(PYTHON3_PACKAGE_MK))
endif

include $(PYTHON3_PACKAGE_MK)

This should solve the corner-case where the python3-package.mk can be in some other feed, or if the packages feed will be named something else locally.

Build considerations

In order to build the Python interpreter, a host Python interpreter needs to be built, in order to process some of the build for the target Python build. The host Python interpreter is also needed so that Python bytecodes are generated, so the host interpreter needs to be the exact version as on the target. And finally, the host Python interpreter also provides pip, so that it may be used to install some Python packages that are required to build other Python packages. That's why you'll also see a Python build & staging directories.

As you're probably thinking, this sounds [and is] somewhat too much complication [just for packaging], but the status of things is-as-it-is, and it's probably much worse than what's currently visible on the surface [with respect to packaging Python & packages].

As mentioned earlier, Python packages are shipped with bytecodes, and the reason for this is simply performance & size. The thought/discussion matrix derives a bit like this:

  • shipping both Python source-code & bytecodes takes too much space on some devices ; Python source code & byte-code take about similar disk-size
  • shipping only Python source code has a big performance penalty [on some lower end systems] ; something like 500 msecs (Python source-only) -> 70 msecs (Python byte-codes) time reduction for a simple "Hello World" script
  • shipping only Python byte-codes seems like a good trade-off, and this means that python3-src can be provided for people that want the source code

By default, automatic Python byte-code generation is disabled when running a Python script, in order to prevent a disk from accidentally filling up. Since some disks reside in RAM, this also means not filling up the RAM. If someone wants to convert Python source to byte-code then he/she is free to compile it [directly on the device] manually via the Python interpreter & library.

General folder structure

The basis of all these packages is:

This is a normal OpenWrt package, which will build the Python interpreter. This also provides python3-pip & python3-setuptools. Each Python package is actually split into multiple sub-packages [e.g. python3-email, python3-sqlite3, etc]. This can be viewed inside lang/python/python3/files.

The reason for this splitting, is purely to offer a way for some people to package Python in as-minimal-as-possible-and-still-runable way, and also to be somewhat maintainable when packaging. A standard Python installation can take ~20-30 MBs of disk, which can be somewhat big for some people, so there is the python3-base package which brings that down to ~5 MBs. This seems to be good enough (and interesting) for a number of people.

The Python interpreter is structured like this:

  • python3-base, which is just the minimal package to startup Python and run basic commands
  • python3 is a meta-package, which installs almost everything (python3-base [plus] Python library [minus] some unit-tests & some windows-y things)
  • python3-light is python3 [minus] packages that are in lang/python/python3/files ; the size of this package may be sensible (and interesting) to another group of people

All other Python packages (aside from the intepreter) typically use these files:

  • python3-host.mk - this file contains paths and build rules for running the Python interpreter on the host-side; they also provide paths to host interprete, host Python lib-dir & so on
  • python3-package.mk
    • includes python3-host.mk
    • contains all the default build rules for Python packages; these will be detailed below in the [Building a Python package](#Building a Python package) section

Note that Python packages don't need to use these files (i.e. python3-package.mk & python3-host.mk), but they do provide some ease-of-use & reduction of duplicate code. And they do contain some learned-lessons about packaging Python packages, so it's a good idea to use them.

Building a Python package

Packaging for Python uses the VARIANT mechanism for packaging inside OpenWrt. (#### FIXME: find a link for this later if it exists)

Include python3-package.mk

Add this after include $(INCLUDE_DIR)/package.mk

include ../python3-package.mk

This will make sure that build rules for Python can be specified and picked up for build.

Include pypi.mk (optional)

If the package source code will be downloaded from pypi.org, including pypi.mk can help simplify the package Makefile.

To use pypi.mk, add this before include $(INCLUDE_DIR)/package.mk:

include ../pypi.mk

pypi.mk has several PYPI_* variables that must/can be set (see below); these should be set before pypi.mk is included, i.e. before the include ../pypi.mk line.

pypi.mk also provides default values for PKG_SOURCE and PKG_SOURCE_URL, so these variables may be omitted.

One variable is required:

  • PYPI_NAME: Package name on pypi.org. This should match the PyPI name exactly.

    For example (from the python-yaml package):

    PYPI_NAME:=PyYAML
    

These variables are optional:

  • PYPI_SOURCE_NAME: Package name component of the source tarball filename
    Default: Same value as PYPI_NAME

  • PYPI_SOURCE_EXT: File extension of the source tarball filename
    Default: tar.gz

pypi.mk constructs the default PKG_SOURCE value from these variables (and PKG_VERSION):

PKG_SOURCE?=$(PYPI_SOURCE_NAME)-$(PKG_VERSION).$(PYPI_SOURCE_EXT)

The PYPI_SOURCE_* variables allow this default PKG_SOURCE value to be customized as necessary.

Add Package/<PKG_NAME> OpenWrt definitions

This part is similar to default OpenWrt packages.

Example:

define Package/python3-lxml
  SECTION:=lang
  CATEGORY:=Languages
  SUBMENU:=Python
  TITLE:=Pythonic XML processing library
  URL:=https://lxml.de
  DEPENDS:=+python3-light +libxml2 +libxslt +libexslt
  VARIANT:=python3
endef

define Package/python3-lxml/description
  The lxml XML toolkit is a Pythonic binding
  for the C libraries libxml2 and libxslt.
endef

Some considerations here (based on the example above):

  • VARIANT=python3 must be added
  • typically the package is named Package/python3-<something> ; this convention makes things easier to follow, though it could work without naming things this way
  • TITLE can be something a bit more verbose/neat ; typically the name is short as seen above

Wrapping things up so that they build

If all the above prerequisites have been met, all that's left is:

$(eval $(call Py3Package,python3-lxml))
$(eval $(call BuildPackage,python3-lxml))

The $(eval $(call Py3Package,python3-lxml)) part will instantiate all the default Python build rules so that the final Python package is packaged into an OpenWrt. And $(eval $(call BuildPackage,python3-lxml)) will bind all the rules generated with $(eval $(call Py3Package,python3-lxml)) into the OpenWrt build system.

These packages will contain byte-codes and binaries (shared libs & other stuff).

If a user wishes to ship source code, adding one more line creates one more package that ship Python source code:

$(eval $(call Py3Package,python3-lxml))
$(eval $(call BuildPackage,python3-lxml))
$(eval $(call BuildPackage,python3-lxml-src))

The name *-src must be the Python package name; so for python3-lxml-src a equivalent python3-lxml name must exist.

Customizing things

Some packages need custom build rules (because they do).

The default package build and install processes are defined in python3-package.mk.

Building

The default build process calls setup.py install inside the directory where the Python source package is extracted (PKG_BUILD_DIR). This "installs" the Python package to an intermediate location (PKG_INSTALL_DIR) where it is used by the default install process.

There are several Makefile variables that can be used to customize this process (all optional):

  • PYTHON3_PKG_SETUP_DIR: Path where setup.py can be found, relative to the package directory (PKG_BUILD_DIR).
    Default: empty value (setup.py is in the package directory)
  • PYTHON3_PKG_SETUP_VARS: Additional environment variables to set for the call to setup.py. Should be in the form of VARIABLE1=value VARIABLE2=value ....
    Default: empty value
  • PYTHON3_PKG_SETUP_GLOBAL_ARGS: Additional command line arguments to pass to setup.py, before / in front of the install command.
    Default: empty value
  • PYTHON3_PKG_SETUP_ARGS: Additional command line arguments to pass to setup.py, after the install command.
    Default: --single-version-externally-managed

Conceptually, these variables are used in this way:

cd $(PKG_BUILD_DIR)/$(PYTHON3_PKG_SETUP_DIR)
$(PYTHON3_PKG_SETUP_VARS) python3 setup.py $(PYTHON3_PKG_SETUP_GLOBAL_ARGS) install $(PYTHON3_PKG_SETUP_ARGS)

The default build process can be completely overridden by defining a custom Py3Build/Compile rule in the package Makefile.

Installing

The default install process copies some/all of the files from PKG_INSTALL_DIR, placed there by the build process, to a location passed to the install rule as the first argument ($(1)). The OpenWrt build system will then take those files and create the actual .ipk package archives.

This default process uses 2 build rules:

  • Py3Package/<package>/filespec which are Python library files relative to /usr/lib/pythonX.Y ; by default this is /usr/lib/python$(PYTHON3_VERSION)/site-packages (PYTHON3_PKG_DIR) ; most Python packages generate files that get installed in this sub-folder
  • Py3Package/<package>/install is similar to Package/<package>/install ; this allows binary (or other files) to be installed on the target

Both the 2 above rules generate a Package/<package>/install build rule, which gets picked up by the build system. Both can be used together (they are not mutually exclusive), and provide a good enough flexibility for specifying Python packages.

The Py3Package/<package>/filespec rule contains one or more lines of the following format (whitespace added for clarity):

<one of: +-=> | <file/directory path> | <file permissions>

The initial character controls the action that will be taken:

  • +: Install the given path. If the path is a directory, all files and subdirectories inside are installed.
    • If file permissions is specified (optional), then the file or directory (and all files and subdirectories) are assigned the given permissions; if omitted, then the file or directory retains its original permissions.
  • -: Remove the given path. Useful when most of a directory should be installed except for a few files or subdirectories.
    • File permissions is not used / ignored in this case.
  • =: Assign the given file permissions to the given path. File permissions is required in this case.

As mentioned, the default Py3Package/<package>/filespec installs PYTHON3_PKG_DIR:

define Py3Package/python3-example/filespec
+|$(PYTHON3_PKG_DIR)
endef

If the package installs a example_package directory inside PYTHON3_PKG_DIR, and there is an examples directory and test_*.py files that can be omitted to save space, this can be specified as:

define Py3Package/python3-example/filespec
+|$(PYTHON3_PKG_DIR)
-|$(PYTHON3_PKG_DIR)/example_package/examples
-|$(PYTHON3_PKG_DIR)/example_package/test_*.py
endef

Host-side Python packages for build

These can be installed via pip and ideally they should only be installed like this, because it's a bit simpler than running them through the OpenWrt build system. Build variants on the host-side build are more complicated (and nearly impossible to do sanely) in the current OpenWrt build system.

Which is why [for example] if you need python cffi on the host build, it's easier to just add it via:

HOST_PYTHON3_PACKAGE_BUILD_DEPENDS:="cffi==$(PKG_VERSION)"

[cffi is one of those packages that needs a host-side package installed].

This works reasonably well in the current OpenWrt build system, as binaries get built for this package and get installed in the staging-dir $(STAGING_DIR)/usr/lib/pythonX.Y/site-packages.