cpenv

Cross-platform Python environment management.

cpenv makes it easy to manage dependencies, environment variables, and applications through the use of python virtualenvs and modules. Configurations can be shared between windows, linux, or mac and deployed directly from git.

How it looks

From a terminal:

> cpenv create my_env
Creating new environment my_env
...
Activating my_env

[my_env]> cpenv create --module my_module https://github.com/cpenv/template_module.git
Installing https://github.com/cpenv/template_module.git
...

From python:

import cpenv
my_env = cpenv.create('my_env)
my_env.add_module('my_module', 'https://github.com/cpenv/template_module.git')
my_env.activate()

From an environment config:

environment:
    PATH:
        - '$ENVIRON/relative/path'
dependencies:
    modules:
        - name: template_module
        repo: https://github.com/cpenv/template_module.git
        branch: master
    pip:
        - requests
    git: []

Installation

cpenv is available on pypi:

pip install cpenv

Make sure you’ve got Git installed and accessible from your command prompt/terminal and you’re ready to go. Set $CPENV_HOME where you’d like environments to be created (defaults to ~/.cpenv).

Documentation Contents

Guide

# TODO

Environments

# TODO

Environment Variables

Variable Description Default
CPENV_HOME Where to create environments ~/.cpenv
CPENV_MODULES List of module locations Null
CPENV_ACTIVE Path to active environment Null
CPENV_ACTIVE_MODULES List of active module paths Null

Configuration

The environment variables configuration is stored in an environment.yml file within the root directory of the environment. For example ~/.cpenv/myenv/environment.yml.

Variables

You can reference environment variables in configuration files by using $ENVVAR or ${ENVVAR}. Additionally cpenv provides the following variables for you to use.

Variable Value
ENVIRON Path to this environment
PLATFORM win, linux or osx
PYVER version of python

Sections

Configuration is broken down into the following sections.

environment

# TODO

dependencies

# TODO

Modules

# TODO

Configuration

The modules configuration is stored in module.yml file within the root directory of the module. For example ~/.cpenv/myenv/modules/mymodule/module.yml.

Variables

You can reference environment variables in configuration files by using $ENVVAR or ${ENVVAR}. Additionally cpenv provides the following variables for you to use.

Variable Value
ENVIRON Path to parent environment
MODULE Path to this module
PLATFORM win, linux or osx
PYVER version of python

Sections

Configuration is broken down into the following sections.

environment

# TODO

dependencies

# TODO

hooks

Hooks are python modules that have a run function. There are many types of hooks each respond to a different event. The run functions first argument is always a VirtualEnvironment instance. Module events are also passed a Module instance.

Available Hooks

  • Create
    • pre_create.py
      • signature: run(module, config)
    • post_create.py
      • signature: run(module)
  • Activate
    • pre_activate.py
      • signature: run(module)
    • post_activate.py
      • signature: run(module)
  • Remove
    • pre_remove.py
      • signature: run(module)
    • post_remove.py
      • signature: run(module)

Global Hooks

The global hook path is $CPENV_HOME/hooks or ~/.cpenv/hooks if the $CPENV_HOME environment variable is undefined. All hooks are available as global hooks.

Module Hooks

Module hooks are stored in a modules hooks directory(~/.cpenv/test_env/modules/test_module/hooks) and overide environment and global hooks. Only module event hooks are supported. If the module is not inside an environment the env argument will be None.

What’s Next?

Changes and Features

  • Automatically track environment config dependencies
    • wrap pip to add/remove dependencies
  • Give modules their own cli multi-command
    • cpenv module add
    • cpenv module remove
  • Shared modules
    • store in $CPENV_HOME/modules
    • resolver to look ‘em up
  • Allow multiple paths in CPENV_HOME and resolve in order
  • Allow modules to provide commands other than launch
    • Like entry-points from setuptools?
    • As sub-commands of the cpenv cli?
  • Support for versioning of modules
    • Use git tags or commit ids for versions of modules?
    • Add version numbers to module names?
  • Add a build section to module configs
    • Provide a list of commands to run
    • Subsection for build environment
  • Add a test section to module configs
    • Provide a list of commands to run
    • Sub-section build environment
  • Provide more module templates
  • Consolidate VirtualeEnvironments and Modules

API Documentation

API Guide

# TODO

API

cpenv.api.activate(requirements, ignore_unresolved=False)[source]

Resolve and active a list of module requirements.

Usage:
>>> cpenv.activate('moduleA', 'moduleB')
Arguments:
requirements (List[str]): List of module requirements
Returns:
list of Module objects that have been activated
cpenv.api.deactivate()[source]

Deactivates an environment by restoring all env vars to a clean state stored prior to activating environments

cpenv.api.clone(module, from_repo=None, where=None, overwrite=False)[source]

Clone a module for local development.

A typical development workflow using clone and publish:
  1. clone a module
  2. make changes
  3. test changes
  4. increment version in module.yml
  5. publish a new version of your module
cpenv.api.create(where, name, version, **kwargs)[source]

Create a new module.

Arguments:
where (str): Path to new module name (str): Name of module version (str): Version of module description (str): Optional description of module author (str): Optional author of module email (str): Optional email address of author requires (list): Optional modules that this module depends on environment (dict): Optional environment variables
Returns:
Module object
cpenv.api.localize(requirements, to_repo='home', overwrite=False, ignore_unresolved=False)[source]

Localize a list of requirements.

cpenv.api.publish(module, to_repo='home', overwrite=False)[source]

Publish a module to the specified repository.

cpenv.api.resolve(requirements, ignore_unresolved=False)[source]

Resolve a list of module requirements.

cpenv.api.set_home_path(path)[source]

Convenient function used to set the CPENV_HOME environment variable.

cpenv.api.get_home_path()[source]

Returns the cpenv home directory.

Default home paths:
win - C:/ProgramData/cpenv mac - /Library/Application Support/cpenv OR /Library/Caches/cpenv linux - /usr/local/share/cpenv OR ~/.local/share/cpenv
cpenv.api.get_home_modules_path()[source]

Return the modules directory within the cpenv home directory.

cpenv.api.get_cache_path(*parts)[source]

Return the cpenv cache directory within the cpenv home directory.

Arguments:
*parts (str) - List of path parts to join with cache path
cpenv.api.get_user_path()[source]

Returns the cpenv user directory.

Default user paths:
win - C:/Users/<username>/AppData/Roaming/cpenv mac - ~/Library/Application Support/cpenv linux - ~/.local/share/cpenv
cpenv.api.get_user_modules_path()[source]

Returns the modules directory within the cpenv user directory.

Default user paths:
win - C:/Users/<username>/AppData/Roaming/cpenv/modules mac - ~/Library/Application Support/cpenv/modules linux - ~/.local/share/cpenv/modules
cpenv.api.get_modules(*requirements)[source]

Returns a list of available modules.

cpenv.api.get_module_paths()[source]

Returns a list of paths used to lookup local modules.

The list of lookup paths contains:
  1. use modules path
  2. home modules path
  3. paths in CPENV_MODULES environment variable
cpenv.api.add_module_path(path)[source]

Add an additional lookup path for local modules.

cpenv.api.get_active_modules()[source]

Returns a list of active Module s

cpenv.api.add_active_module(module)[source]

Add a module to CPENV_ACTIVE_MODULES environment variable.

Arguments:
module (Module): Module to add to CPENV_ACTIVE_MODULES
cpenv.api.remove_active_module(module)[source]

Remove a module from CPENV_ACTIVE_MODULES environment variable.

Arguments:
module (Module): Module to remove from CPENV_ACTIVE_MODULES
cpenv.api.get_repos()[source]

Get a list of all registered Repos.

cpenv.api.get_repo(name, **query)[source]

Get a repo by specifying an attribute to lookup

cpenv.api.add_repo(repo, priority=None)[source]

Register a Repo.

Arguments:
priority (int): Override the Repos priority when adding.
cpenv.api.read_config(key=None, default=<object object>)[source]

Read the whole config or a specific key from disk.

Examples:

# Read whole config config = read_config()

# Read one key repos = read_config(‘repos’, {})

cpenv.api.write_config(*args)[source]

Write the whole config or a specific key to disk.

Examples:

# Write whole config write_config({‘repos’: {}})

# Write one config key write_config(‘repos’, {})

cpenv.api.update_repo(repo)[source]

Update a registered repo.

cpenv.api.remove_repo(repo)[source]

Unregister a Repo.

class cpenv.hooks.HookFinder(*hook_paths)[source]

Find python hooks by name in the provided path.

usage:

>>> hook_finder = HookFinder('~/.cpenv/hooks')
>>> hook = hook_finder('precreate')
>>> hook.run(env=VirtualEnvironment('path/to/env'))
cpenv.hooks.get_global_hook_path()[source]

Returns the global hook path

cpenv.hooks.run_global_hook(hook_name, *args)[source]

Attempt to run a global hook by name with args

exception cpenv.resolver.ResolveError[source]

Raised when a Resolver fairs to resolve a module or list of modules.

class cpenv.resolver.Resolver(repos)[source]

Responsible for resolving ModuleSpecs from requirement strings.

Modules will be looked up sequentially in all registered Repos. By default this order is:

  1. LocalRepo pointing to current working directory
  2. LocalRepo pointing to cpenv_user_modules_path
  3. LocalRepo pointing to cpenv_home_modules_path ($CPENV_HOME/modules)
  4. LocalRepos pointing to the paths in $CPENV_MODULES
  5. Custom Repos registered via cpenv.add_repo

If there are still unresolved modules, fallback to the old algorithm for module lookups using the resolve functions in the cpenv.resolver.module_resolvers list.

resolve(requirements, ignore_unresolved=False)[source]

Given a list of requirement strings, resolve ModuleSpecs.

Returns:
list of ModuleSpec objects
Raises:
ResolveError when a requirement can not be resolved.
class cpenv.resolver.Activator(localizer=None)[source]

Responsible for activating modules.

activate(module_specs)[source]

Activate a list of module specs.

combine_modules(modules)[source]

Combine a list of module’s environments.

class cpenv.resolver.Copier(to_repo)[source]

Responsible for copying modules to a specific module.

copy(module_specs, overwrite=False)[source]

Given ModuleSpecs, copy them to this copiers to_repo.

class cpenv.resolver.Localizer(to_repo='home')[source]

Downloads modules from remote Repos to a specific LocalRepo.

This is similar to a copy operation, but skips all module_specs that are already in LocalRepos. If they are in LocalRepos then they are already available to be activated.

localize(module_specs, overwrite=False)[source]

Given ModuleSpecs, download them to this Localizers repo.

cpenv.resolver.is_redirecting(path)[source]

Returns True if path contains a .cpenv file

cpenv.resolver.redirect_to_modules(path)[source]

Get environment path from redirect file

cpenv.resolver.parse_redirect(data)[source]

Parses a redirect string - data of a .cpenv file