All Projects → StephanErb → pexample

StephanErb / pexample

Licence: Apache-2.0 license
Building and packaging Python with Pants and PEX - an annotated example

Programming Languages

shell
77523 projects
python
139335 projects - #7 most used programming language
Starlark
911 projects
Dockerfile
14818 projects

Projects that are alternatives of or similar to pexample

Pants
The Pantsbuild developer workflow system
Stars: ✭ 1,814 (+8538.1%)
Mutual labels:  build, pex, pants
Please
High-performance extensible build system for reproducible multi-language builds.
Stars: ✭ 1,856 (+8738.1%)
Mutual labels:  build, pants
open-electronics
📚 💻 Great Resources for Electronics Enthusiasts
Stars: ✭ 347 (+1552.38%)
Mutual labels:  build
autosetup
A better, faster autoconf replacement
Stars: ✭ 60 (+185.71%)
Mutual labels:  build
xcodedevtools
Xcode Development Scripts
Stars: ✭ 44 (+109.52%)
Mutual labels:  build
rebuild
Zero-dependency, reproducible build environments
Stars: ✭ 48 (+128.57%)
Mutual labels:  build
k8s-knative-gitlab-harbor
Build container images with Knative + Gitlab + Harbor inside Kops cluster running on AWS
Stars: ✭ 23 (+9.52%)
Mutual labels:  build
defold-deployer
Universal build && deploy script for Defold projects
Stars: ✭ 23 (+9.52%)
Mutual labels:  build
AzDo.VstsDashboard
Provide a simple way to view all Builds and Releases on a single page. The intend was to see what's currently happened into the CI/CD pipeline and provide quick feedback of what's going on.
Stars: ✭ 16 (-23.81%)
Mutual labels:  build
build verify
A Dart package to verify that the build is up-to-date with respect to a git repository
Stars: ✭ 28 (+33.33%)
Mutual labels:  build
ngp
New Go Package
Stars: ✭ 22 (+4.76%)
Mutual labels:  build
mix script
A build tool which allows you to use mix packages in an elixir script
Stars: ✭ 16 (-23.81%)
Mutual labels:  build
ios-build-action
Build iOS project (.xcodeproj, .xcworkspace), export .ipa, optional upload to BrowserStack App Live.
Stars: ✭ 73 (+247.62%)
Mutual labels:  build
icon-pipeline
🚚 SVG icon pipeline - Optimize icons & build SVG sprites
Stars: ✭ 43 (+104.76%)
Mutual labels:  build
gradle-android-appiconoverlay
Plugin for Android Gradle to automatically overlay the app icon with the current git commit SHA1.
Stars: ✭ 64 (+204.76%)
Mutual labels:  build
build
Build system scripts based on GENie (https://github.com/bkaradzic/genie) project generator
Stars: ✭ 30 (+42.86%)
Mutual labels:  build
sphinx-markdown-builder
sphinx builder that outputs markdown files.
Stars: ✭ 135 (+542.86%)
Mutual labels:  build
get-cmake
Install and Cache latest CMake and ninja executables for your workflows on your GitHub
Stars: ✭ 52 (+147.62%)
Mutual labels:  build
whey
A simple Python wheel builder for simple projects.
Stars: ✭ 17 (-19.05%)
Mutual labels:  build
Carbon.Gulp
Carbon/Gulp is a delicious blend of tasks and build tools poured into Gulp to form a full-featured modern asset pipeline for Flow Framework and Neos CMS.
Stars: ✭ 15 (-28.57%)
Mutual labels:  build

pExample: Python with Pants and PEX

This repository features a running example of the pants build system and Python packaging with PEX.

Build

What is Pants?

Pants is a build system for large or rapidly growing code bases. It supports all stages of a typical build: tool bootstrapping, code generation, third-party dependency resolution, compilation, test running, linting, bundling and more.

The latest version of pants is currently focused on Python, with support for other languages coming (back) soon.

With pants, you can organize your code via targets for binaries, libraries, and tests. For Python programmers, pants is especially interesting, as it makes the manipulation and distribution of hermetically sealed Python environments painless. For example, pants handles dependencies for you. It never installs anything globally. Instead, it builds the dependencies, caches them, and assembles them a la carte into execution environments - so called PEXes.

What is PEX?

A PEX is, roughly, an archive file containing a runnable Python environment. The ideas is based on PEP 441. Pants isn't the only PEX-generation tool out there; but if you have some "common code" used by more than one PEX, Pants makes it easy to manage everything.

Getting Started

In this example, everything is controlled via the ./pants script that will automatically bootstrap pants and its dependencies.

# bootstrap
$ ./pants --version

Let's start with something simple:

# List everything pants can do for us
$ ./pants help goals

# List all registered source roots
$ ./pants roots

According to the command above, we have tests defined. Let's run them (using the recursive wildcard ::):

$ ./pants test tests/python::

The example also comes with a (highly sophisticated) command line client:

$ ./pants run src/python/hello_world/cli:hello_world
Hello World!

We can also build a self-contained PEX binary with our code, so that it can be used independent of pants and the build environment:

$ ./pants package src/python/hello_world/cli:hello_world

The binary is dropped into dist/. Let's run it:

$ ./dist/src.python.hello_world.cli/hello_world.pex
Hello World!

$ ./dist/src.python.hello_world.cli/hello_world.pex --name Stephan
Hello Stephan!

Mhh, let's make that a bit more exciting:

$ ./dist/src.python.hello_world.cli/hello_world.pex --name Stephan --mode cow

________________
< Hello Stephan! >
----------------
       \   ^__^
        \  (oo)\_______
           (__)\       )\/
               ||----w |
               ||     ||

Better :)

Running Tests

As a build system pants is also responsible for running tests:

# Run all tests (using the recursive wildcard ::)
$ ./pants test ::

# Run one specific test target
$ ./pants test tests/python/hello_world/messages

Under the hood pants is using pytest. We can pass arbitrary arguments to pytest (i.e., anything after --). For example, we can use -k to limit the test execution to tests containing a particular name:

# Run tests whose name contains "cow"
$ ./pants test tests/python/hello_world/messages -- -k cow

Pants can also leverage SCM information to restrict operations to a set of changed targets and thus improve turnaround times:

# NOTE: To follow the commands below you might want to change the content
#       of `src/python/hello_world/messages/greetings.py`

# List all changed targets with uncommitted changes
$ ./pants --changed-since=HEAD list

# Run tests for all targets listed above and their direct dependencies
$ ./pants --changed-since=HEAD --changed-dependees=direct test

# Run tests for all targets directly or transitively depending on the changed targets
$ ./pants --changed-since=HEAD --changed-dependees=transitive test

On build servers such as Jenkins it can also be useful to run tests for anything that changed between branches or since a particular commit:

# Run tests for anything changed on this branch (compared to master)
$ ./pants --changed-since=origin/master --changed-dependees=transitive test

Python Code Quality Tools

Pants ships with a plugins such as isort, black, and flake8 to ensure code is consistent:

# Run quality checks on everything
$ ./pants lint :: 

# correct sort order and formatting for everything
$ ./pants fmt ::

We can also run mypy to check (optional) Python types:

# Run mypy on everything
$ ./pants typecheck ::

Interactive Python Sessions

It can sometimes be helpful to investigate a build environment within an interactive Python REPL. Within such a session it is then possible to import a target's code and its dependencies:

$ ./pants repl src/python/hello_world/messages
>>> from hello_world.messages.animals import cow
>>> print(cow('Hello Betty'))

It is also possible to drop into an interactive session for a PEX binary:

$ PEX_INTERPRETER=1 ./dist/src.python.hello_world.cli/hello_world.pex
>>> from hello_world.messages.animals import unicorn
>>> print(unicorn('wow unicorn'))


    \
     \
      \\
       \\
         >\/7
    _.-(6'  \
   (=___._/` \
        )  \ |
       /   / |       ________________
      /    > /       < WOW unicorn >
     j    < _\       ----------------
 _.-' :      ``.
 \ r=._\        `.
<`\\_  \         .`-.
 \ r-7  `-. ._  ' .  `\
  \`,      `-.`7  7)   )
   \/         \|  \'  / `-._
              ||    .'
              \\  (
               >\  >
            ,.-' >.'
           <.'_.''
             <'

Under the hood: BUILD Files

A large, well-organized codebase divides into many small components. These components, and the code dependencies between them, form a directed graph. This graph is then used for various operations, such as compilation and fine-grained cache invalidation.

Components in pants are defined using BUILD files containing directives (so called targets) such as:

python_library(
  name='mytarget',
  dependencies=[
    '3rdparty/python:external_dep',
    'src/python/foobar/my_explicit_dependency',
  ]
)

Fortunately for us, pants detects imported Python packages automatically, so we don't need to specify those dependencies manually!

Many programming languages (E.g., Java, Python, Go) have a concept of a package, usually corresponding to a single filesystem directory. It turns out that this is often the appropriate level of granularity for targets. It's by no means required, but has proven in practice to be a good rule of thumb.

To make it simpler to follow these best practices, pants can even auto-generate BUILD files:

$ ./pants tailor

To list all build targets in a repository:

$ ./pants list ::

BUILD Example: Deployment Binaries

PEX files in Pants are declared via the pex_binary target type. Commonly used optiones include the binary name and the dependencies, but also the interpreter compatibility as well as the target platform. This allows users to build binaries for different Python versions and operating systems:

pex_binary(
  name='math_fun',
  entry_point='math_fun.cli.main:main',
  platforms=[
    'current',
    'macosx-10.9-x86_64-cp-38-cp38',
  ]
)

Pants also comes with direct integration into Docker, enabling you to ship your PEX files in Docker images. PEX understands the Dockerfile syntax and knows which Docker images to rebuild at what point in time:

$ ./pants package src/docker/math_fun/cli::
$ docker run -it --rm math_fun:latest --version

Build Example: Source Distributions

In addition to PEX files, Pants can also generate source distributions. Source distributions can be installed via pip and uploaded to PyPi.org. All you need is a python_distribution:

python_distribution(
  name='wheel',
  dependencies=[':lib'], # reference libraries to include
  provides=python_artifact(
    name='math_fun',
    version='0.0.24', # can also be dynamic. BUILD files are just Python
    description='Math lib as a source distribution',
    classifiers=[
      'Intended Audience :: Developers',
      'Programming Language :: Python',
    ]   
  ),  
  setup_py_commands=["bdist_wheel", "sdist"]
)

Pants can the be used to generate the source distribution. Similar to binaries, those will be placed in the dist folder:

$ ./pants package src/python/math_fun/lib:wheel
$ ls dist/math_fun-0.0.24.tar.gz

References

Most of the content above is directly extracted from the pants and PEX documentation.

Further reading:

Helpful talks:

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].