edgetest package#

Submodules#

Core module.

class edgetest.core.TestPackage(hook: _HookRelay, envname: str, upgrade: List[str] | None = None, lower: List[str] | None = None, package_dir: str | None = None)[source]#

Bases: object

Run test commands with bleeding edge dependencies.

Parameters:
  • hook (_HookRelay) – The hook object from pluggy.

  • envname (str) – The name of the conda environment to create/use.

  • upgrade (list) – The list of packages to upgrade

  • lower (list) – The list of packages to install lower bounds alongside the lower bound value. E.g. ["pandas==1.5.2"].

  • package_dir (str, optional (default None)) – The location of the local package to install and test.

_basedir#

The base directory location for each environment

Type:

str

status#

A boolean status indicator for whether or not the tests passed. Only populated after run_tests has been executed.

Type:

bool

lowered_packages() List[Dict[str, str]][source]#

Get list of lowered packages for the test environment.

Returns:

List of lowered packages and their versions

Return type:

List[Dict[str, str]]

property python_path: str#

Get the path to the python executable.

Returns:

The path to the python executable.

Return type:

str

run_tests(command: str) int[source]#

Run the tests in the package directory.

Parameters:

command (str) – The test command

Returns:

The exit code

Return type:

int

setup(extras: List[str] | None = None, deps: List[str] | None = None, skip: bool = False, **options) None[source]#

Set up the testing environment.

Parameters:
  • extras (list, optional (default None)) – The list of extra installations to include.

  • deps (list, optional (default None)) – A list of additional dependencies to install via pip

  • skip (bool, optional (default False)) – Whether to skip setup as a pre-made environment has already been created.

  • **options – Additional options for self.hook.create_environment.

Return type:

None

Raises:

RuntimeError – This error will be raised if any part of the set up process fails.

upgraded_packages() List[Dict[str, str]][source]#

Get the list of upgraded packages for the test environment.

Parameters:

None

Returns:

The output of pip list --format json, filtered to the packages upgraded for this environment.

Return type:

List

Hook specifications for edgetest.

edgetest.hookspecs.addoption(schema: Schema)[source]#

Modify the schema for custom options.

You can add environment-level options through add_envoption or global configuration options through add_globaloption.

edgetest.hookspecs.create_environment(basedir: str, envname: str, conf: Dict)[source]#

Create the virtual environment for testing.

Parameters:
  • basedir (str) – The base directory location for the environment.

  • envname (str) – The name of the virtual environment.

  • conf (dict) – The configuration dictionary for the environment. This is useful if you want to add configuration arguments for additional dependencies that can only be installed through the environment manager (e.g. Conda).

Raises:

RuntimeError – Error raised if the environment cannot be created.

edgetest.hookspecs.path_to_python(basedir: str, envname: str) str[source]#

Return the path to the python executable.

Parameters:
  • basedir (str) – The base directory location for the environment.

  • envname (str) – The name of the virtual environment.

Returns:

The path to the python executable for the environment. For installations via pip, we’ll be running python -m pip install ..., where python is the python executable for the environment.

Return type:

str

edgetest.hookspecs.post_run_hook(testers: List, conf: Dict)[source]#

Post testing hook.

For executing code after the environment set up and testing.

Parameters:
  • testers (list) – The list of TestPackage objects.

  • conf (dict) – The entire configuration dictionary.

edgetest.hookspecs.pre_run_hook(conf: Dict)[source]#

Pre-setup and test hook.

Parameters:

conf (Dict) – The entire configuration dictionary.

edgetest.hookspecs.run_install_lower(basedir: str, envname: str, lower: Dict[str, str], conf: Dict)[source]#

Install lower bounds of packages provided.

Parameters:
  • basedir (str) – The base directory location for the environment.

  • envname (str) – Environment to install into.

  • lower_bounds (Dict[str, str]) – Lower bounds of packages to install.

  • conf (Dict) – The configuration dictionary for the environment. This is useful if you want to add configuration arguments for additional dependencies that can only be installed through the environment manager (e.g. Conda).

edgetest.hookspecs.run_update(basedir: str, envname: str, upgrade: List, conf: Dict)[source]#

Update packages from upgrade list.

Parameters:
  • basedir (str) – The base directory location for the environment.

  • envname (str) – The name of the virtual environment.

  • upgrade (list) – The list of packages to upgrade

  • conf (dict) – The configuration dictionary for the environment. This is useful if you want to add configuration arguments for additional dependencies that can only be installed through the environment manager (e.g. Conda).

Raises:

RuntimeError – Error raised if the packages cannot be updated.

Command-line interface.

edgetest.interface.get_plugin_manager() PluginManager[source]#

Get the plugin manager.

Registers the default venv plugin.

Returns:

The plugin manager.

Return type:

PluginManager

Default virtual environment hook.

edgetest.lib.create_environment(basedir: str, envname: str, conf: Dict)[source]#

Create the virtual environment for testing.

Creates an environment using venv.

Parameters:
  • basedir (str) – The base directory location for the environment.

  • envname (str) – The name of the virtual environment.

  • conf (dict) – Ignored.

Raises:

RuntimeError – Error raised if the environment cannot be created.

edgetest.lib.path_to_python(basedir: str, envname: str) str[source]#

Return the path to the python executable.

edgetest.lib.run_install_lower(basedir: str, envname: str, lower: List[str], conf: Dict)[source]#

Install lower bounds of packages provided.

Parameters:
  • basedir (str) – The base directory location for the environment.

  • envname (str) – Environment to install into.

  • lower (List[str]) – Lower bounds of packages to install.

  • conf (Dict) – The configuration dictionary for the environment. This is useful if you want to add configuration arguments for additional dependencies that can only be installed through the environment manager (e.g. Conda).

edgetest.lib.run_update(basedir: str, envname: str, upgrade: List, conf: Dict)[source]#

Update packages from upgrade list.

Parameters:
  • basedir (str) – The base directory location for the environment.

  • envname (str) – The name of the virtual environment.

  • upgrade (list) – The list of packages to upgrade

  • conf (dict) – Ignored.

Raises:

RuntimeError – Error raised if the packages cannot be updated.

Logging Module.

Module which setsup the basic logging infrustrcuture for the application.

edgetest.logger.get_logger(name=None, log_level=20)[source]#

Set the basic logging features for the application.

Parameters:
  • name (str, optional) – The name of the logger. Defaults to None

  • log_level (int, optional) – The logging level. Defaults to logging.INFO

Returns:

Returns a Logger obejct which is set with the passed in paramters.

Return type:

logging.Logger

Generate rST reports.

edgetest.report.gen_report(testers: List[TestPackage], output_type: str = 'rst') Any[source]#

Generate a rST report.

Parameters:
  • testers (list) – A list of TestPackage objects.

  • output_type (str) – A valid output type of rst or github

Returns:

The report.

Return type:

Any

Define the Cerberus schema for the testing configuration.

class edgetest.schema.EdgetestValidator(*args, **kwargs)[source]#

Bases: Validator

Custom validator for coercing lists from .ini style files.

checkers = ()#
coercers = ('listify', 'strip')#
default_setters = ()#
normalization_rules = {'coerce': {'oneof': [{'type': 'callable'}, {'type': 'list', 'schema': {'oneof': [{'type': 'callable'}, {'type': 'string', 'allowed': ('listify', 'strip')}]}}, {'type': 'string', 'allowed': ('listify', 'strip')}]}, 'default': {'nullable': True}, 'default_setter': {'oneof': [{'type': 'callable'}, {'type': 'string', 'allowed': ()}]}, 'purge_unknown': {'type': 'boolean'}, 'rename': {'type': 'hashable'}, 'rename_handler': {'oneof': [{'type': 'callable'}, {'type': 'list', 'schema': {'oneof': [{'type': 'callable'}, {'type': 'string', 'allowed': ('listify', 'strip')}]}}, {'type': 'string', 'allowed': ('listify', 'strip')}]}}#
rules = {'allof': {'logical': 'allof', 'type': 'list'}, 'allow_unknown': {'oneof': [{'type': 'boolean'}, {'type': ['dict', 'string'], 'check_with': 'bulk_schema'}]}, 'allowed': {'type': 'container'}, 'anyof': {'logical': 'anyof', 'type': 'list'}, 'check_with': {'oneof': [{'type': 'callable'}, {'type': 'list', 'schema': {'oneof': [{'type': 'callable'}, {'type': 'string', 'allowed': ()}]}}, {'type': 'string', 'allowed': ()}]}, 'coerce': {'oneof': [{'type': 'callable'}, {'type': 'list', 'schema': {'oneof': [{'type': 'callable'}, {'type': 'string', 'allowed': ('listify', 'strip')}]}}, {'type': 'string', 'allowed': ('listify', 'strip')}]}, 'contains': {'empty': False}, 'default': {'nullable': True}, 'default_setter': {'oneof': [{'type': 'callable'}, {'type': 'string', 'allowed': ()}]}, 'dependencies': {'check_with': 'dependencies', 'type': ('dict', 'hashable', 'list')}, 'empty': {'type': 'boolean'}, 'excludes': {'schema': {'type': 'hashable'}, 'type': ('hashable', 'list')}, 'forbidden': {'type': 'list'}, 'items': {'check_with': 'items', 'type': 'list'}, 'keysrules': {'check_with': 'bulk_schema', 'forbidden': ['rename', 'rename_handler'], 'type': ['dict', 'string']}, 'max': {'nullable': False}, 'maxlength': {'type': 'integer'}, 'meta': {}, 'min': {'nullable': False}, 'minlength': {'type': 'integer'}, 'noneof': {'logical': 'noneof', 'type': 'list'}, 'nullable': {'type': 'boolean'}, 'oneof': {'logical': 'oneof', 'type': 'list'}, 'purge_unknown': {'type': 'boolean'}, 'readonly': {'type': 'boolean'}, 'regex': {'type': 'string'}, 'rename': {'type': 'hashable'}, 'rename_handler': {'oneof': [{'type': 'callable'}, {'type': 'list', 'schema': {'oneof': [{'type': 'callable'}, {'type': 'string', 'allowed': ('listify', 'strip')}]}}, {'type': 'string', 'allowed': ('listify', 'strip')}]}, 'require_all': {'type': 'boolean'}, 'required': {'type': 'boolean'}, 'schema': {'anyof': [{'check_with': 'schema'}, {'check_with': 'bulk_schema'}], 'type': ['dict', 'string']}, 'type': {'check_with': 'type', 'type': ['string', 'list']}, 'valuesrules': {'check_with': 'bulk_schema', 'forbidden': ['rename', 'rename_handler'], 'type': ['dict', 'string']}}#
validation_rules = {'allof': {'logical': 'allof', 'type': 'list'}, 'allow_unknown': {'oneof': [{'type': 'boolean'}, {'type': ['dict', 'string'], 'check_with': 'bulk_schema'}]}, 'allowed': {'type': 'container'}, 'anyof': {'logical': 'anyof', 'type': 'list'}, 'check_with': {'oneof': [{'type': 'callable'}, {'type': 'list', 'schema': {'oneof': [{'type': 'callable'}, {'type': 'string', 'allowed': ()}]}}, {'type': 'string', 'allowed': ()}]}, 'contains': {'empty': False}, 'dependencies': {'check_with': 'dependencies', 'type': ('dict', 'hashable', 'list')}, 'empty': {'type': 'boolean'}, 'excludes': {'schema': {'type': 'hashable'}, 'type': ('hashable', 'list')}, 'forbidden': {'type': 'list'}, 'items': {'check_with': 'items', 'type': 'list'}, 'keysrules': {'check_with': 'bulk_schema', 'forbidden': ['rename', 'rename_handler'], 'type': ['dict', 'string']}, 'max': {'nullable': False}, 'maxlength': {'type': 'integer'}, 'meta': {}, 'min': {'nullable': False}, 'minlength': {'type': 'integer'}, 'noneof': {'logical': 'noneof', 'type': 'list'}, 'nullable': {'type': 'boolean'}, 'oneof': {'logical': 'oneof', 'type': 'list'}, 'readonly': {'type': 'boolean'}, 'regex': {'type': 'string'}, 'require_all': {'type': 'boolean'}, 'required': {'type': 'boolean'}, 'schema': {'anyof': [{'check_with': 'schema'}, {'check_with': 'bulk_schema'}], 'type': ['dict', 'string']}, 'type': {'check_with': 'type', 'type': ['string', 'list']}, 'valuesrules': {'check_with': 'bulk_schema', 'forbidden': ['rename', 'rename_handler'], 'type': ['dict', 'string']}}#
class edgetest.schema.Schema[source]#

Bases: object

An editable schema.

add_envoption(option: str, schema: Dict)[source]#

Add an environment-level option.

Parameters:
  • option (str) – The name of the option. This will be the key in the key-value pair.

  • schema (dict) – The schema for the option.

Examples

>>> Schema().add_envoption("command", {"type": "string", "default": "pytest"})
add_globaloption(option: str, schema: Dict)[source]#

Add a global option.

Parameters:
  • option (str) – The name of the option. This will be the key in the key-value pair.

  • schema (dict) – The schema for the option.

Examples

>>> Schema().add_globaloption("print_message", {"type": "string"})
schema = {'envs': {'required': True, 'schema': {'schema': {'command': {'coerce': 'strip', 'default': 'pytest', 'type': 'string'}, 'deps': {'coerce': 'listify', 'default': None, 'nullable': True, 'schema': {'type': 'string'}, 'type': 'list'}, 'extras': {'coerce': 'listify', 'default': None, 'nullable': True, 'schema': {'type': 'string'}, 'type': 'list'}, 'lower': {'coerce': 'listify', 'excludes': 'upgrade', 'required': True, 'schema': {'type': 'string'}, 'type': 'list'}, 'name': {'coerce': 'strip', 'required': True, 'type': 'string'}, 'package_dir': {'coerce': 'strip', 'default': '.', 'type': 'string'}, 'upgrade': {'coerce': 'listify', 'excludes': 'lower', 'required': True, 'schema': {'type': 'string'}, 'type': 'list'}}, 'type': 'dict'}, 'type': 'list'}}#

Utility functions.

edgetest.utils.convert_requirements(requirements: str, conf: Dict | None = None) Dict[source]#

Generate environments for a newline-separate list of package requirements.

This function will generate one environment per entry with an additional environment that upgrades all requirements simultaneously.

Parameters:
  • requirements (str) – The requirements string.

  • conf (dict, optional (default None)) – An existing configuration to edit.

Returns:

A configuration dictionary.

Return type:

Dict

edgetest.utils.gen_requirements_config(fname_or_buf: str, **options) Dict[source]#

Generate a configuration file from package requirements.

This function will convert the package installation requirements to a configuration file with one environment per requirement.

Parameters:
  • fname_or_buf (str) – Path to the requirements file to parse using pkg_resources.parse_requirements or the string representing the requirements file.

  • **options – Options to apply to each test environment.

Returns:

The configuration file.

Return type:

Dict

edgetest.utils.get_lower_bounds(requirements: str, lower: str) str[source]#

Get lower bounds of requested packages from installation requirements.

Parses through the project requirements and the newline-delimited packages requested in lower to find the lower bounds.

Parameters:
  • requirements (str) – Project setup requirements, e.g. "pandas>=1.5.1,<=1.4.2\nnumpy>=1.22.1,<=1.25.4"

  • lower (str) –

    Newline-delimited packages requested,

    e.g. "pandas\nnumpy".

Returns:

The packages along with the lower bound, e.g. "pandas==1.5.1\nnumpy==1.22.1".

Return type:

str

edgetest.utils.parse_cfg(filename: str = 'setup.cfg', requirements: str | None = None) Dict[source]#

Generate a configuration from a .ini style file.

This function can operate in two ways. First, it can look for sections that start with edgetest and build a configuration. Suppose you have setup.cfg as follows:

[edgetest.envs.pandas]
upgrade =
    pandas

This will result in a configuration that has one testing environment, named pandas, that upgrades the pandas package.

If you don’t have any sections that start with edgetest.envs, we will look for the PEP 517-style setup.cfg install requirements (the install_requires key within the options section). To set global defaults for you environments, use the edgetest section:

[edgetest]
extras =
    tests
command =
    pytest tests -m "not integration"

[edgetest.envs.pandas]
upgrade =
    pandas

For this single environment file, the above configuration is equivalent to

[edgetest.envs.pandas]
extras =
    tests
command =
    pytest tests -m "not integration"
upgrade =
    pandas
Parameters:
  • filename (str, optional (default "setup.cfg")) – The name of the configuration file to read. Defaults to setup.cfg.

  • requirements (str, optional (default None)) – An optional path to the requirements text file. If there are no PEP-517 style dependencies or coded environments in the edgetest configuration, this function will look for dependencies in the requirements file.

Returns:

A configuration dictionary for edgetest.

Return type:

Dict

edgetest.utils.parse_toml(filename: str = 'pyproject.toml', requirements: str | None = None) Dict[source]#

Generate a configuration from a .toml style file.

This function can operate in two ways. First, it will look for tables that start with edgetest and build a configuration. Suppose you have pyproject.toml as follows:

[edgetest.envs.pandas]
upgrade = [
    "pandas"
]

This will result in a configuration that has one testing environment, named pandas, that upgrades the pandas package.

If you don’t have any tables that start with edgetest.envs, we will look for the installation requirements (the dependencies key within the project section). To set global defaults for you environments, use the edgetest table:

[edgetest]
extras = [
    "tests"
]
command = "pytest tests -m 'not integration'"

[edgetest.envs.pandas]
upgrade = [
    "pandas"
]

For this single environment file, the above configuration is equivalent to

[edgetest.envs.pandas]
extras = [
    "tests"
]
command = "pytest tests -m 'not integration'"
upgrade = [
    "pandas"
]
Parameters:
  • filename (str, optional (default "pyproject.toml")) – The name of the toml file to read. Defaults to pyproject.toml.

  • requirements (str, optional (default None)) – An optional path to the requirements text file. If there are no TOML style dependencies or coded environments in the edgetest configuration, this function will look for dependencies in the requirements file.

Returns:

A configuration dictionary for edgetest.

Return type:

Dict

edgetest.utils.pushd(new_dir: str)[source]#

Create a context manager for running commands in sub-directories.

Parameters:

new_dir (str) – The relative directory to run the command in.

edgetest.utils.upgrade_pyproject_toml(upgraded_packages: List[Dict[str, str]], filename: str = 'pyproject.toml') TOMLDocument[source]#

Upgrade the pyproject.toml file.

Parameters:
  • upgraded_packages (List[Dict[str, str]]) – A list of packages upgraded in the testing procedure.

  • filename (str, optional (default "pyproject.toml")) – The name of the configuration file to read. Defaults to pyproject.toml.

Returns:

The updated TOMLDocument.

Return type:

TOMLDocument

edgetest.utils.upgrade_requirements(fname_or_buf: str, upgraded_packages: List[Dict[str, str]]) str[source]#

Create an upgraded requirements file.

Parameters:
  • fname_or_buf (str) – Path to the requirements file to parse using pkg_resources.parse_requirements or the string representing the requirements file.

  • upgraded_packages (list) – A list of packages upgraded in the testing procedure.

Returns:

The string file representing the new requirements file.

Return type:

str

edgetest.utils.upgrade_setup_cfg(upgraded_packages: List[Dict[str, str]], filename: str = 'setup.cfg') ConfigParser[source]#

Upgrade the setup.cfg file.

Parameters:
  • upgraded_packages (List[Dict[str, str]]) – A list of packages upgraded in the testing procedure.

  • filename (str, optional (default "setup.cfg")) – The name of the configuration file to read. Defaults to setup.cfg.

Returns:

The updated configuration file.

Return type:

ConfigParser

Module contents#

Bleeding edge dependency testing <https://github.com/capitalone/edgetest>