pyscaffold package

Submodules

pyscaffold.cli module

Command-Line-Interface of PyScaffold

pyscaffold.cli.add_default_args(parser)[source]

Add the default options and arguments to the CLI parser.

Parameters

parser (argparse.ArgumentParser) – CLI parser object

pyscaffold.cli.list_actions(opts)[source]

Do not create a project, just list actions considering extensions

Parameters

opts (dict) – command line options as dictionary

pyscaffold.cli.main(args)[source]

Main entry point for external applications

Parameters

args ([str]) – command line arguments

pyscaffold.cli.parse_args(args)[source]

Parse command line parameters respecting extensions

Parameters

args ([str]) – command line parameters as list of strings

Returns

command line parameters

Return type

dict

pyscaffold.cli.process_opts(opts)[source]

Process and enrich command line arguments

Parameters

opts (dict) – dictionary of parameters

Returns

dictionary of parameters from command line arguments

Return type

dict

pyscaffold.cli.run()[source]

Entry point for console script

pyscaffold.cli.run_scaffold(opts)[source]

Actually scaffold the project, calling the python API

Parameters

opts (dict) – command line options as dictionary

pyscaffold.exceptions module

Custom exceptions used by PyScaffold to identify common deviations from the expected behavior.

exception pyscaffold.exceptions.ActionNotFound(name, *args, **kwargs)[source]

Bases: KeyError

Impossible to find the required action.

exception pyscaffold.exceptions.DirectoryAlreadyExists[source]

Bases: RuntimeError

The project directory already exists, but no update or force option was used.

exception pyscaffold.exceptions.DirectoryDoesNotExist[source]

Bases: RuntimeError

No directory was found to be updated.

exception pyscaffold.exceptions.GitDirtyWorkspace(message="Your working tree is dirty. Commit your changes first or use '--force'.", *args, **kwargs)[source]

Bases: RuntimeError

Workspace of git is empty.

DEFAULT_MESSAGE = "Your working tree is dirty. Commit your changes first or use '--force'."
exception pyscaffold.exceptions.GitNotConfigured(message='Make sure git is configured. Run:\n git config --global user.email "you@example.com"\n git config --global user.name "Your Name"\nto set your account\'s default identity.', *args, **kwargs)[source]

Bases: RuntimeError

PyScaffold tries to read user.name and user.email from git config.

DEFAULT_MESSAGE = 'Make sure git is configured. Run:\n git config --global user.email "you@example.com"\n git config --global user.name "Your Name"\nto set your account\'s default identity.'
exception pyscaffold.exceptions.GitNotInstalled(message='Make sure git is installed and working.', *args, **kwargs)[source]

Bases: RuntimeError

PyScaffold requires git to run.

DEFAULT_MESSAGE = 'Make sure git is installed and working.'
exception pyscaffold.exceptions.InvalidIdentifier[source]

Bases: RuntimeError

Python requires a specific format for its identifiers.

https://docs.python.org/3.6/reference/lexical_analysis.html#identifiers

exception pyscaffold.exceptions.NoPyScaffoldProject(message='Could not update project. Was it generated with PyScaffold?', *args, **kwargs)[source]

Bases: RuntimeError

PyScaffold cannot update a project that it hasn’t generated

DEFAULT_MESSAGE = 'Could not update project. Was it generated with PyScaffold?'
exception pyscaffold.exceptions.OldSetuptools(message='Your setuptools version is too old (<38.3). Use `pip install -U setuptools` to upgrade.\nIf you have the deprecated `distribute` package installed remove it or update to version 0.7.3.', *args, **kwargs)[source]

Bases: RuntimeError

PyScaffold requires a recent version of setuptools.

DEFAULT_MESSAGE = 'Your setuptools version is too old (<38.3). Use `pip install -U setuptools` to upgrade.\nIf you have the deprecated `distribute` package installed remove it or update to version 0.7.3.'
exception pyscaffold.exceptions.PyScaffoldTooOld(message='setup.cfg has no section [pyscaffold]! Are you trying to update a pre 3.0 version?', *args, **kwargs)[source]

Bases: RuntimeError

PyScaffold cannot update a pre 3.0 version

DEFAULT_MESSAGE = 'setup.cfg has no section [pyscaffold]! Are you trying to update a pre 3.0 version?'
exception pyscaffold.exceptions.ShellCommandException(message, *args, **kwargs)[source]

Bases: RuntimeError

Outputs proper logging when a ShellCommand fails

pyscaffold.info module

Provide general information about the system, user etc.

class pyscaffold.info.GitEnv[source]

Bases: enum.Enum

An enumeration.

author_date = 'GIT_AUTHOR_DATE'
author_email = 'GIT_AUTHOR_EMAIL'
author_name = 'GIT_AUTHOR_NAME'
committer_date = 'GIT_COMMITTER_DATE'
committer_email = 'GIT_COMMITTER_EMAIL'
committer_name = 'GIT_COMMITTER_NAME'
pyscaffold.info.best_fit_license(txt)[source]

Finds proper license name for the license defined in txt

Parameters

txt (str) – license name

Returns

license name

Return type

str

pyscaffold.info.check_git()[source]

Checks for git and raises appropriate exception if not

Raises
  • GitNotInstalled – when git command is not available

  • GitNotConfigured – when git does not know user information

pyscaffold.info.email()[source]

Retrieve the user’s email

Returns

user’s email

Return type

str

pyscaffold.info.is_git_configured()[source]

Check if user.name and user.email is set globally in git

Check first git environment variables, then config settings. This will also return false if git is not available at all.

Returns

True if it is set globally, False otherwise

Return type

bool

pyscaffold.info.is_git_installed()[source]

Check if git is installed

Returns

True if git is installed, False otherwise

Return type

bool

pyscaffold.info.is_git_workspace_clean(path)[source]

Checks if git workspace is clean

Parameters

path (str) – path to git repository

Returns

condition if workspace is clean or not

Return type

bool

Raises:

GitNotInstalled: when git command is not available GitNotConfigured: when git does not know user information

pyscaffold.info.project(opts)[source]

Update user options with the options of an existing PyScaffold project

Params:

opts (dict): options of the project

Returns

options with updated values

Return type

dict

Raises
  • PyScaffoldTooOld – when PyScaffold is to old to update from

  • NoPyScaffoldProject – when project was not generated with PyScaffold

pyscaffold.info.username()[source]

Retrieve the user’s name

Returns

user’s name

Return type

str

pyscaffold.integration module

Integration part for hooking into distutils/setuptools

Rationale: The use_pyscaffold keyword is unknown to setuptools’ setup(…) command, therefore the entry_points are checked for a function to handle this keyword which is pyscaffold_keyword below. This is where we hook into setuptools and apply the magic of setuptools_scm as well as other commands.

pyscaffold.integration.build_cmd_docs()[source]

Return Sphinx’s BuildDoc if available otherwise a dummy command

Returns

command object

Return type

Command

pyscaffold.integration.local_version2str(version)[source]

Create the local part of a PEP440 version string

Parameters

version (setuptools_scm.version.ScmVersion) – version object

Returns

local version

Return type

str

pyscaffold.integration.pyscaffold_keyword(dist, keyword, value)[source]

Handles the use_pyscaffold keyword of the setup(…) command

Parameters
  • dist (setuptools.dist) – distribution object as

  • keyword (str) – keyword argument = ‘use_pyscaffold’

  • value – value of the keyword argument

pyscaffold.integration.setuptools_scm_config(value)[source]

Generate the configuration for setuptools_scm

Parameters

value – value from entry_point

Returns

dictionary of options

Return type

dict

pyscaffold.integration.version2str(version)[source]

Creates a PEP440 version string

Parameters

version (setuptools_scm.version.ScmVersion) – version object

Returns

version string

Return type

str

pyscaffold.log module

Custom logging infrastructure to provide execution information for the user.

class pyscaffold.log.ColoredReportFormatter(fmt=None, datefmt=None, style='%', validate=True)[source]

Bases: pyscaffold.log.ReportFormatter

Format logs with ANSI colors.

ACTIVITY_STYLES = {'create': ('green', 'bold'), 'delete': ('red', 'bold'), 'invoke': ('bold',), 'move': ('green', 'bold'), 'remove': ('red', 'bold'), 'run': ('magenta', 'bold'), 'skip': ('yellow', 'bold')}
CONTEXT_PREFIX = '\x1b[35m\x1b[1mfrom\x1b[0m'
LOG_STYLES = {'critical': ('red', 'bold'), 'debug': ('green',), 'error': ('red',), 'info': ('blue',), 'warning': ('yellow',)}
SUBJECT_STYLES = {'invoke': ('blue',)}
TARGET_PREFIX = '\x1b[35m\x1b[1mto\x1b[0m'
format_activity(activity)[source]

Format the activity keyword.

format_default(record)[source]

Format default log messages.

format_subject(subject, activity=None)[source]

Format the subject of the activity.

class pyscaffold.log.ReportFormatter(fmt=None, datefmt=None, style='%', validate=True)[source]

Bases: logging.Formatter

Formatter that understands custom fields in the log record.

ACTIVITY_MAXLEN = 12
CONTEXT_PREFIX = 'from'
SPACING = ' '
TARGET_PREFIX = 'to'
create_padding(activity)[source]

Create the appropriate padding in order to align activities.

format(record)[source]

Compose message when a record with report information is given.

format_activity(activity)[source]

Format the activity keyword.

format_context(context, _activity=None)[source]

Format extra information about the activity context.

format_default(record)[source]

Format default log messages.

format_path(path)[source]

Simplify paths to avoid wasting space in terminal.

format_report(record)[source]

Compose message when a custom record is given.

format_subject(subject, _activity=None)[source]

Format the subject of the activity.

format_target(target, _activity=None)[source]

Format extra information about the activity target.

class pyscaffold.log.ReportLogger(logger=None, handler=None, formatter=None, extra=None)[source]

Bases: logging.LoggerAdapter

Suitable wrapper for PyScaffold CLI interactive execution reports.

Parameters
  • logger (logging.Logger) – custom logger to be used. Optional: the default logger will be used.

  • handlers (logging.Handler) – custom logging handler to be used. Optional: a logging.StreamHandler is used by default.

  • formatter (logging.Formatter) – custom formatter to be used. Optional: by default a ReportFormatter is created and used.

  • extra (dict) – extra attributes to be merged into the log record. Options, empty by default.

wrapped

underlying logger object.

Type

logging.Logger

handler

stream handler configured for providing user feedback in PyScaffold CLI.

Type

logging.Handler

formatter

formatter configured in the default handler.

Type

logging.Formatter

nesting

current nesting level of the report.

Type

int

copy()[source]

Produce a copy of the wrapped logger.

Sometimes, it is better to make a copy of th report logger to keep indentation consistent.

indent(count=1)[source]

Temporarily adjust padding while executing a context.

Example

from pyscaffold.log import logger
logger.report('invoke', 'custom_action')
with logger.indent():
   logger.report('create', 'some/file/path')

# Expected logs:
# --------------------------------------
#       invoke  custom_action
#       create    some/file/path
# --------------------------------------
# Note how the spacing between activity and subject in the
# second entry is greater than the equivalent in the first one.

Note

This method is not thread-safe and should be used with care.

property level

Effective level of the logger

process(msg, kwargs)[source]

Method overridden to augment LogRecord with the nesting attribute.

report(activity, subject, context=None, target=None, nesting=None, level=20)[source]

Log that an activity has occurred during scaffold.

Parameters
  • activity (str) – usually a verb or command, e.g. create, invoke, run, chdir

  • subject (str) – usually a path in the file system or an action identifier.

  • context (str) – path where the activity take place.

  • target (str) – path affected by the activity

  • nesting (int) – optional nesting level. By default it is calculated from the activity name.

  • level (int) – log level. Defaults to logging.INFO. See logging for more information.

Notes

This method creates a custom log record, with additional fields: activity, subject, context, target and nesting, but an empty msg field. The ReportFormatter creates the log message from the other fields.

Often target and context complement the logs when subject does not hold all the necessary information. For example:

logger.report('copy', 'my/file', target='my/awesome/path')
logger.report('run', 'command', context='current/working/dir')
pyscaffold.log.configure_logger(opts)[source]

Configure the default logger

Parameters

opts (dict) – command line parameters

pyscaffold.log.logger = <ReportLogger pyscaffold.log (WARNING)>

Default logger configured for PyScaffold.

pyscaffold.repo module

Functionality for working with a git repository

pyscaffold.repo.add_tag(project, tag_name, message=None, **kwargs)[source]

Add an (annotated) tag to the git repository.

Parameters
  • project (str) – path to the project

  • tag_name (str) – name of the tag

  • message (str) – optional tag message

Additional keyword arguments are passed to the git callable object.

pyscaffold.repo.get_git_root(default=None)[source]

Return the path to the top-level of the git repository or default.

Parameters

default (str) – if no git root is found, default is returned

Returns

top-level path or default

Return type

str

pyscaffold.repo.git_tree_add(struct, prefix='', **kwargs)[source]

Adds recursively a directory structure to git

Parameters
  • struct (dict) – directory structure as dictionary of dictionaries

  • prefix (str) – prefix for the given directory structure

Additional keyword arguments are passed to the git callable object.

pyscaffold.repo.init_commit_repo(project, struct, **kwargs)[source]

Initialize a git repository

Parameters
  • project (str) – path to the project

  • struct (dict) – directory structure as dictionary of dictionaries

Additional keyword arguments are passed to the git callable object.

pyscaffold.repo.is_git_repo(folder)[source]

Check if a folder is a git repository

Parameters

folder (str) – path

pyscaffold.shell module

Shell commands like git, django-admin.py etc.

class pyscaffold.shell.ShellCommand(command, shell=True, cwd=None)[source]

Bases: object

Shell command that can be called with flags like git(‘add’, ‘file’)

Parameters
  • command (str) – command to handle

  • shell (bool) – run the command in the shell

  • cwd (str) – current working dir to run the command

The produced command can be called with the following keyword arguments:

  • log (bool): log activity when true. False by default.

  • pretend (bool): skip execution (but log) when pretending. False by default.

The positional arguments are passed to the underlying shell command.

pyscaffold.shell.command_exists(cmd)[source]

Check if command exists

Parameters

cmd – executable name

pyscaffold.shell.django_admin = <pyscaffold.shell.ShellCommand object>

Command for django-admin.py

pyscaffold.shell.get_git_cmd(**args)[source]

Retrieve the git shell command depending on the current platform

Parameters

**args – additional keyword arguments to ShellCommand

pyscaffold.shell.git = <pyscaffold.shell.ShellCommand object>

Command for git

pyscaffold.shell.shell_command_error2exit_decorator(func)[source]

Decorator to convert given ShellCommandException to an exit message

This avoids displaying nasty stack traces to end-users

pyscaffold.structure module

Functionality to generate and work with the directory structure of a project

class pyscaffold.structure.FileOp[source]

Bases: object

Namespace for file operations during an update

NO_CREATE = 1

Do not create the file during an update

NO_OVERWRITE = 0

Do not overwrite an existing file during update (still created if not exists)

pyscaffold.structure.create_structure(struct, opts, prefix=None)[source]

Manifests a directory structure in the filesystem

Parameters
  • struct (dict) – directory structure as dictionary of dictionaries

  • opts (dict) – options of the project

  • prefix (str) – prefix path for the structure

Returns

directory structure as dictionary of dictionaries (similar to input, but only containing the files that actually changed) and input options

Return type

tuple(dict, dict)

Raises

RuntimeError – raised if content type in struct is unknown

pyscaffold.structure.define_structure(_, opts)[source]

Creates the project structure as dictionary of dictionaries

Parameters
  • struct (dict) – previous directory structure (ignored)

  • opts (dict) – options of the project

Returns

structure as dictionary of dictionaries and input options

Return type

tuple(dict, dict)

pyscaffold.termui module

Basic support for ANSI code formatting.

pyscaffold.termui.curses_available()[source]

Check if the curses package from stdlib is available.

Usually not available for windows, but its presence indicates that the terminal is capable of displaying some UI.

Returns

result of check

Return type

bool

pyscaffold.termui.decorate(msg, *styles)[source]

Use ANSI codes to format the message.

Parameters
  • msg (str) – string to be formatted

  • *styles (list) – the remaining arguments should be strings that represent the 8 basic ANSI colors. clear and bold are also supported. For background colors use on_<color>.

Returns

styled and formatted message

Return type

str

pyscaffold.termui.init_colorama()[source]

Initialize colorama if it is available.

Returns

result of check

Return type

bool

pyscaffold.termui.isatty(stream=None)[source]

Detect if the given stream/stdout is part of an interactive terminal.

Parameters

stream – optionally the stream to check

Returns

result of check

Return type

bool

pyscaffold.termui.supports_color(stream=None)[source]

Check if the stream is supposed to handle coloring.

Returns

result of check

Return type

bool

pyscaffold.update module

Functionality to update one PyScaffold version to another

pyscaffold.update.add_entrypoints(struct, opts)[source]

Add [options.entry_points] to setup.cfg

Parameters
  • struct (dict) – previous directory structure (ignored)

  • opts (dict) – options of the project

Returns

structure as dictionary of dictionaries and input options

Return type

tuple(dict, dict)

pyscaffold.update.add_setup_requires(struct, opts)[source]

Add setup_requires in setup.cfg

Parameters
  • struct (dict) – previous directory structure (ignored)

  • opts (dict) – options of the project

Returns

structure as dictionary of dictionaries and input options

Return type

tuple(dict, dict)

pyscaffold.update.apply_update_rule_to_file(path, value, opts)[source]

Applies the update rule to a given file path

Parameters
  • path (str) – file path

  • value (tuple or str) – content (and update rule)

  • opts (dict) –

    options of the project, containing the following flags:

    • update: if the project already exists and should be updated

    • force: overwrite all the files that already exist

Returns

content of the file if it should be generated or None otherwise.

pyscaffold.update.apply_update_rules(struct, opts, prefix=None)[source]

Apply update rules using FileOp to a directory structure.

As a result the filtered structure keeps only the files that actually will be written.

Parameters
  • opts (dict) –

    options of the project, containing the following flags:

    • update: when the project already exists and should be updated

    • force: overwrite all the files that already exist

  • struct (dict) – directory structure as dictionary of dictionaries (in this tree representation, each leaf can be just a string or a tuple also containing an update rule)

  • prefix (str) – prefix path for the structure

Returns

directory structure with keys removed according to the rules (in this tree representation, all the leaves are strings) and input options

Return type

tuple(dict, dict)

pyscaffold.update.get_curr_version(project_path)[source]

Retrieves the PyScaffold version that put up the scaffold

Parameters

project_path – path to project

Returns

version specifier

Return type

Version

pyscaffold.update.invoke_action(action, struct, opts)[source]

Invoke action with proper logging.

Parameters
  • struct (dict) – project representation as (possibly) nested dict.

  • opts (dict) – given options, see create_project for an extensive list.

Returns

updated project representation and options

Return type

tuple(dict, dict)

pyscaffold.update.read_setupcfg(project_path)[source]

Reads-in setup.cfg for updating

Parameters

project_path (str) – path to project

Returns:

pyscaffold.update.update_pyscaffold_version(project_path, pretend)[source]

Update setup_requires in setup.cfg

Parameters
  • project_path (str) – path to project

  • pretend (bool) – only pretend to do something

pyscaffold.update.version_migration(struct, opts)[source]

Migrations from one version to another

Parameters
  • struct (dict) – previous directory structure (ignored)

  • opts (dict) – options of the project

Returns

structure as dictionary of dictionaries and input options

Return type

tuple(dict, dict)

pyscaffold.utils module

Miscellaneous utilities and tools

pyscaffold.utils.chdir(path, **kwargs)[source]

Contextmanager to change into a directory

Parameters

path (str) – path to change current working directory to

Keyword Arguments
  • log (bool) – log activity when true. Default: False.

  • pretend (bool) – skip execution (but log) when pretending. Default False.

pyscaffold.utils.check_setuptools_version()[source]

Check minimum required version of setuptools

Check that setuptools has all necessary capabilities for setuptools_scm as well as support for configuration with the help of setup.cfg.

Raises

OldSetuptools – raised if necessary capabilities are not met

pyscaffold.utils.create_directory(path, update=False, pretend=False)[source]

Create a directory in the given path.

This function reports the operation in the logs.

Parameters
  • path (str) – path in the file system where contents will be written.

  • update (bool) – false by default. A OSError is raised when update is false and the directory already exists.

  • pretend (bool) – false by default. Directory is not created when pretending, but operation is logged.

pyscaffold.utils.create_file(path, content, pretend=False)[source]

Create a file in the given path.

This function reports the operation in the logs.

Parameters
  • path (str) – path in the file system where contents will be written.

  • content (str) – what will be written.

  • pretend (bool) – false by default. File is not written when pretending, but operation is logged.

pyscaffold.utils.dasherize(word)[source]

Replace underscores with dashes in the string.

Example:

>>> dasherize("foo_bar")
"foo-bar"
Parameters

word (str) – input word

Returns

input word with underscores replaced by dashes

pyscaffold.utils.exceptions2exit(exception_list)[source]

Decorator to convert given exceptions to exit messages

This avoids displaying nasty stack traces to end-users

Parameters

[Exception] (exception_list) – list of exceptions to convert

pyscaffold.utils.get_id(function)[source]

Given a function, calculate its identifier.

A identifier is a string in the format <module name>:<function name>, similarly to the convention used for setuptools entry points.

Note

This function does not return a Python 3 __qualname__ equivalent. If the function is nested inside another function or class, the parent name is ignored.

Parameters

function (callable) – function object

Returns

identifier

Return type

str

pyscaffold.utils.get_setup_requires_version()[source]

Determines the proper setup_requires string for PyScaffold

E.g. setup_requires = pyscaffold>=3.0a0,<3.1a0

Returns

requirement string for setup_requires

Return type

str

pyscaffold.utils.is_valid_identifier(string)[source]

Check if string is a valid package name

Parameters

string (str) – package name

Returns

True if string is valid package name else False

Return type

bool

pyscaffold.utils.levenshtein(s1, s2)[source]

Calculate the Levenshtein distance between two strings

Parameters
  • s1 (str) – first string

  • s2 (str) – second string

Returns

distance between s1 and s2

Return type

int

pyscaffold.utils.make_valid_identifier(string)[source]

Try to make a valid package name identifier from a string

Parameters

string (str) – invalid package name

Returns

valid package name as string or RuntimeError

Return type

str

Raises

InvalidIdentifier – raised if identifier can not be converted

pyscaffold.utils.move(*src, **kwargs)[source]

Move files or directories to (into) a new location

Parameters

*src (str[]) – one or more files/directories to be moved

Keyword Arguments
  • target (str) – if target is a directory, src will be moved inside it. Otherwise, it will be the new path (note that it may be overwritten)

  • log (bool) – log activity when true. Default: False.

  • pretend (bool) – skip execution (but log) when pretending. Default False.

pyscaffold.utils.prepare_namespace(namespace_str)[source]

Check the validity of namespace_str and split it up into a list

Parameters

namespace_str (str) – namespace, e.g. “com.blue_yonder”

Returns

list of namespaces, e.g. [“com”, “com.blue_yonder”]

Return type

[str]

Raises

InvalidIdentifier – raised if namespace is not valid

pyscaffold.warnings module

Warnings used by PyScaffold to identify issues that can be safely ignored but that should be displayed to the user.

exception pyscaffold.warnings.UpdateNotSupported(*args, extension=None, **kwargs)[source]

Bases: RuntimeWarning

Extensions that make use of external generators are not able to do updates by default.

DEFAULT_MESSAGE = 'Updating code generated using external tools is not supported. The extension `{}` will be ignored, only changes in PyScaffold core features will take place.'

Module contents