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(db_entry)[source]

Add a console script (app, aka CLI) to the package.

add_auto_build_code(db_entry)[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(db_entry)[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_f90_module(db_entry)[source]

Add a f90 module to this project.

add_python_module(db_entry)[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.

deserialize_db()[source]

Read file db.json into self.db.

error(msg)[source]

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

f90_module_exists(module_name)[source]

Test if there is already a f90 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).

mv_component()[source]

Rename or Remove a component (sub-module, sub-package, Fortran module, C++ module, app (CLI).

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
replace_in_file(filepath, cur_name, new_name, contents_only=False)[source]

Replace <cur_name> with <new_name> in the filename and its contents.

serialize_db(db_entry=None, verbose=False)[source]

Write self.db to file db.json.

Self.options is a SimpleNamespace object which is not default json serializable. This function takes care of that by converting to str where possible, and ignoring objects that do not need serialization, as e.g. self.options.logger.

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.is_publishable(package_name, verbose=True)[source]

Is the name <package_name> available for publishing on PyPI?

This is achieved by running pip search <package_name> and examining the output. If <package_name> is in use, it will appear in the output.

Parameters:
  • package_name (str) – name of the package for which we want to verify the availability.
  • verbose (bool) – show the output of pip search <package_name> and the examination process.
Returns:

the answer as a bool, if the command pip search <package_name> was successful, and None otherwise (e.g. because of no connection).

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 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