API

Package et-micc

Top-level package for et-micc.

Module et_micc.project

An OO interface to micc projects.

class et_micc.project.Project(options)[source]

An OO interface to micc projects.

Parameters:options (types.SimpleNameSpace) – all options from the micc CLI.
add_app()[source]

Add a console script (app) to the package.

add_auto_build_code()[source]

Add auto build code for binary extension modules in __init__.py of the package.

add_cmd()[source]

Add some source file to the project.

This method dispatches to

add_cpp_module()[source]

Add a cpp module to this project.

add_dependencies(deps)[source]

Add dependencies to the pyproject.toml file.

Parameters:deps (dict) – (package,version_constraint) pairs.
add_f2py_module()[source]

Add a f2py module to this project.

add_python_module()[source]

Add a python sub-module or sub-package to this project.

app_exists(app_name)[source]

Test if there is already an app with name app_name in this project.

  • <package_name>/cli_<app_name>.py
Parameters:app_name (str) – app name
Returns:bool
cpp_module_exists(module_name)[source]

Test if there is already a cpp module with name py:obj:module_name in this project.

Parameters:module_name (str) – module name
Returns:bool
create()[source]

Create a new project skeleton.

error(msg)[source]

Print an error message msg and set the project’s exit_code.

f2py_module_exists(module_name)[source]

Test if there is already a f2py module with name py:obj:module_name in this project.

Parameters:module_name (str) – module name
Returns:bool
info_cmd()[source]

Output info on the project.

module_exists(module_name)[source]

Test if there is already a module with name py:obj:module_name in this project.

This can be either a Python module, package, or a binary extension module.

Parameters:module_name (str) – module name
Returns:bool
module_to_package(module_py)[source]

Move file module.py to module/__init__.py.

Parameters:module_py (str|Path) – path to module.py
module_to_package_cmd()[source]

Convert a module project (module.py) to a package project (package/__init__.py).

py_module_exists(module_name)[source]

Test if there is already a python module with name module_name in the project at project_path.

Parameters:module_name (str) – module name
Returns:bool
py_package_exists(module_name)[source]

Test if there is already a python package with name module_name in the project at project_path.

Parameters:module_name (str) – module name
Returns:bool
tag_cmd()[source]

Create and push a version tag v<Major>.<minor>.<patch> for the current version.

version_cmd()[source]

Bump the version according to self.options.rule or show the current version if no rule is specified.

The version is stored in pyproject.toml in the project directory, and in __version__ variable of the top-level package, which is either in <package_name>.py, <package_name>/__init__.py, or in <package_name>/__version__.py.

warning(msg)[source]

Print an warning message msg and set the project’s exit_code.

Module et_micc.expand

Helper functions for dealing with Cookiecutter templates.

et_micc.expand.expand_templates(options)[source]

Expand a list of cookiecutter templates in directory project_path.

Expanding templates may require overwriting pre-existing files. Micc handles this situation in different ways:

  • If options.overwrite equals False the exansion will fail without overwriting any pre-existing files. The project is not modified. A warning is produced. This is the default. To continue, rerun the command with one of the two options below.
  • If options.overwrite equals True the exansion will overwrite any pre-existing files without backup, and produce a warning, listing the overwritten files.
  • If options.backup equals True pre-existing files will be backed up (.bak) before the new files are expanded. If anything went wrong, you can inspect the backup files, and correct the errors manually.
Parameters:options (types.SimpleNamespace) –

namespace object with options accepted by et_micc commands. Relevant attributes are

  • templates: ordered list of (paths to) cookiecutter templates that will be expanded as they appear. The template parameters are propagated from each template to the next.
  • verbosity
  • project_path: Path to the project on which the command operates.
  • template_parameters: extra template parameters not read from micc_file
et_micc.expand.get_preferences(micc_file)[source]

Get the preferences from micc_file.

(This function requires user interaction if no micc_file was provided!)

Parameters:micc_file (Path) – path to a json file.
et_micc.expand.get_template_parameters(preferences)[source]

Get the template parameters from the preferences.

Parameters:preferenes (dict|Path) –
Returns:dict of (parameter name,parameter value) pairs.
et_micc.expand.resolve_template(template)[source]

Compose the absolute path of a template.

et_micc.expand.set_preferences(micc_file)[source]

Set the preferences in micc_file.

(This function requires user interaction!)

Parameters:micc_file (Path) – path to a json file.

Module et_micc.logger

Helper functions for logging.

class et_micc.logger.IndentingLogger(name, level=0)[source]

Cuastom Logger class for creating indented logs.

This is the class for the et_micc logger.

dedent()[source]

Increase the indentation level.

Future log messages will shift to the left. The width of the shift is determined by the last call to indent()

indent(n=4)[source]

Increase the indentation level.

Future log messages will shift to the right by n spaces.

et_micc.logger.create_logger(path_to_log_file, filemode='a')[source]

Create a logger object for et_micc.

It will log to:

  • the console
  • file path_to_log_file. By default log message will be appended to the
et_micc.logger.log(logfun=None, before='doing', after='done.', bracket=True)[source]

Print a message before and after executing the body of the contextmanager.

Parameters:
  • logfun (callable) – a function that can print a log message, e.g. print(), info().
  • before (str) – print this before body is executed
  • after (str) – print this after body is executed
  • bracket (bool) – append ‘ [‘ to before and prepend ‘] ‘ to after.

This works best with the IndentingLogger.

et_micc.logger.logtime(project=None)[source]

Log start time, end time and duration of the task in the body of the context manager to the et_micc logger.

This logs on debug level. To see in in the console output you must pass -vv to et_micc.

Parameters:global_options (SimpleNameSpace) – pass verbosity to the et_micc logger.
et_micc.logger.verbosity_to_loglevel(verbosity)[source]

Tranlate verbosity into a loglevel.

Parameters:verbosity (int) –

Created on 18 Nov 2019

@author: etijskens

Module et_micc.utils

Utility functions for et_micc.

et_micc.utils.execute(cmds, logfun=None, stop_on_error=True, env=None, cwd=None)[source]

Executes a list of OS commands, and logs with logfun.

Parameters:cmds (list) – list of OS commands (=list of list of str) or a single command (list of str)
Parma callable logfun:
 a function to write output, typically logging.getLogger('et_micc').debug.
Returns int:return code of first failing command, or 0 if all commanbds succeed.
et_micc.utils.get_project_path(p)[source]

Look for a project directory in the parents of path p.

Parameters:p (Path) –
Returns:the nearest directory above p that is project directory.
Raise:RuntimeError if p is noe inside a project directory.
et_micc.utils.in_directory(path)[source]

Context manager for changing the current working directory while the body of the context manager executes.

et_micc.utils.insert_in_file(file, lines=[], before=False, startswith=None)[source]

Insert lines at a specific position in a <file>.

Parameters:
  • file (Path) – path to file in which to insert
  • lines (list) – list of lines to insert. If a line does not end with a newline, it is added.
  • before (bool) – insert before or after a reference line.
  • startswith (str) – find the reference line as the first line that starts with <startswith>. If no such line is found the text is inserted at the end.
et_micc.utils.intersect(version_range_1, version_range_2)[source]

Compute the intersection of two version ranges

et_micc.utils.is_project_directory(path, project=None)[source]

Verify that the directory path is a project directory.

Parameters:
  • path (Path) – path to a directory.
  • project (Project) –

    if not None these variables are set:

    • project.project_name
    • project.package_name
    • project.pyproject_toml
Returns:

bool.

As a sufficident condition, we request that

  • there is a pyproject.toml file, exposing the project’s name:py:obj:[‘tool’][‘poetry’][‘name’]
  • that there is a python package or module with that name, converted by pep8_module_name().
et_micc.utils.operator_version(version_constraint_string)[source]

Split version_constraint_string in operator and version.

Returns:(str,semantic_version.Version)
et_micc.utils.pep8_module_name(name)[source]

Convert a module name to a PEP8 compliant module name.

  • lowercase
  • whitespace -> underscore
  • dash -> underscore
et_micc.utils.replace_in_file(file_to_search, look_for, replace_with)[source]

Replace the text look_for with replace_with in file file_to_search

et_micc.utils.validate_intersection(intersection)[source]

Test if the intersection is not empty. :returns: bool

et_micc.utils.verify_project_name(project_name)[source]

Project names must start with a char, and contain only chars, digits, underscores and dashes.

Returns:bool
et_micc.utils.verify_project_structure(path, project=None)[source]

Verify that there is either a Python module <package_name>.py, or a package <package_name>/__init__.py (and not both).

Returns:a list with what was found. This list should have length 1. If its length is 0, neither module.py, nor module/__init__.py were found. If its length is 2, both were found.
et_micc.utils.version_constraint(version_range)[source]

Convert a version_range to a version constraing string

et_micc.utils.version_range(version_constraint_string)[source]

Return interval [lower_bound,upper_bound[ as a tuple for a given version constraint.

Note that the lower bound is inclusive, but the upper bound is exclusive. If one of the bounds is None, then it is unbound in that direction.

Module et_micc.tomlfile

class et_micc.tomlfile.TomlFile(path)[source]

Read/write access to .toml files (pyproject.toml in particular).

Open a .toml file and read its content

The content is accessed by subscripting:

toml = TomlFile('path/to/toml')
# Read an item from the .toml file's content:
old_name = toml['tool']['poetry']['name']
# Modify an item in the .toml file's content (but not yet in the file):
toml['tool']['poetry']['name'] = 'new_name'
# Now modify the file with the modified content:
toml.save()
Parameters:path (str|Path) – path to the .toml file.
Raises:FileNotFoundError if the file does not exist.
exists()[source]

Does the .toml file exist?

path

Path object of the .toml file

save()[source]

Write the current content of the .toml file back to file.

Module Stopwatch

A context manager class for timing a piece of code.

class et_micc.stopwatch.Stopwatch(message='', ndigits=6)[source]

Context manager class for timing a code fragment.

Usage:

with Stopwatch('This took me') as sw:
    for i in range(3):
        sleep(1)
        print(i,sw.timelapse(),'s)
        
 0 1.004215 s
 1 1.003996 s
 2 1.001949 s
 This took me 3.010238 s
Parameters:
  • comment (str) – text in front of the total time. If None nothing is printed. Default is empty str,
  • ndigits (int) – number of digits after the decimal sign.
start()[source]

Start or restart this Stopwatch object.

stop()[source]

Stop the Stopwatch object and return the number of seconds since it was started.

time

Return number of seconds between starting and stopping the stopwatch (for the last time)

timelapse()[source]

Return number of seconds (float) since last call to timelapse (or to start if called for the first time).

Module et_micc.static_vars

A decorator for adding static variables to a function. see https://stackoverflow.com/questions/279561/what-is-the-python-equivalent-of-static-variables-inside-a-function

et_micc.static_vars.static_vars(**kwargs)[source]

Add static variables to a method.

To add the variable counter to foo() :

@static_vars(counter=0)
def foo():
    foo.counter += 1 # foo.counter is incremented on every call to foo