Skip to content

API

Bump'R: Version bumper and Python package releaser

  • Clean-up release artifact
  • Bump version and tag it
  • Build a source distrbution and upload on PyPI
  • Update version for new develpoment cycle
  • Can run test suite before
  • Can be customized with a config file
  • Extensible with hooks

config

BumprConfigParser (RawConfigParser)

A config parser with optionnal implicit bumpr: prefix on sections.

Allow better isolation in setup.cfg.

get(self, section, option, **kwargs)

Get an option value for a given section.

If vars' is provided, it must be a dictionary. The option is looked up invars' (if provided), section', and inDEFAULTSECT' in that order. If the key is not found and fallback' is provided, it is used as a fallback value.None' can be provided as a `fallback' value.

If interpolation is enabled and the optional argument `raw' is False, all interpolations are expanded in the return values.

Arguments raw',vars', and `fallback' are keyword only.

The section DEFAULT is special.

Source code in bumpr/config.py
def get(self, section, option, **kwargs):
    for section in self.candidate_sections(section):
        if RawConfigParser.has_option(self, section, option):
            return RawConfigParser.get(self, section, option)

has_option(self, section, option)

Check for the existence of a given option in a given section. If the specified section' is None or an empty string, DEFAULT is assumed. If the specifiedsection' does not exist, returns False.

Source code in bumpr/config.py
def has_option(self, section, option):
    sections = self.candidate_sections(section)
    return any(RawConfigParser.has_option(self, section, option) for section in sections)

has_section(self, section)

Indicate whether the named section is present in the configuration.

The DEFAULT section is not acknowledged.

Source code in bumpr/config.py
def has_section(self, section):
    sections = self.candidate_sections(section)
    return any(RawConfigParser.has_section(self, section) for section in sections)

items(self, section)

Return a list of (name, value) tuples for each option in a section.

All % interpolations are expanded in the return values, based on the defaults passed into the constructor, unless the optional argument raw' is true. Additional substitutions may be provided using thevars' argument, which must be a dictionary whose contents overrides any pre-existing defaults.

The section DEFAULT is special.

Source code in bumpr/config.py
def items(self, section):
    for section in self.candidate_sections(section):
        if RawConfigParser.has_section(self, section):
            return RawConfigParser.items(self, section)

options(self, section)

Return a list of option names for the given section name.

Source code in bumpr/config.py
def options(self, section):
    for section in self.candidate_sections(section):
        if RawConfigParser.has_section(self, section):
            return RawConfigParser.options(self, section)

helpers

ObjectDict (dict)

A dictionnary with object-like attribute access and depp merge

update(self, *args, **kwargs)

D.update([E, ]**F) -> None. Update D from dict/iterable E and F. If E is present and has a .keys() method, then does: for k in E: D[k] = E[k] If E is present and lacks a .keys() method, then does: for k, v in E: D[k] = v In either case, this is followed by: for k in F: D[k] = F[k]

Source code in bumpr/helpers.py
def update(self, *args, **kwargs):
    for key, value in dict(*args, **kwargs).items():
        if isinstance(value, dict) and not isinstance(value, ObjectDict):
            value = ObjectDict(value)
        self[key] = value

check_output(*args, **kwargs)

A wrapper for preconfigured calls to subprocess.check_output

Source code in bumpr/helpers.py
def check_output(*args, **kwargs):
    """A wrapper for preconfigured calls to subprocess.check_output"""
    return subprocess.check_output(
        stderr=subprocess.STDOUT, universal_newlines=True, *args, **kwargs
    )

hooks

ChangelogHook (Hook)

This hook bump the changelog version header and prepare a new section for the next release.

validate(self)

Override this method to implement initial validation

Source code in bumpr/hooks.py
def validate(self):
    if not self.config.get("file"):
        raise BumprError("Changelog file has not been specified")
    elif not exists(self.config.file):
        raise BumprError("Changelog file does not exists")

CommandsHook (Hook)

This hook execute commands

Hook

validate(self)

Override this method to implement initial validation

Source code in bumpr/hooks.py
def validate(self):
    """Override this method to implement initial validation"""

ReadTheDocHook (Hook)

This hook set the readthedoc url corresponding to the version

ReplaceHook (Hook)

This hook perform replacements in files

log

ANSIFormatter (Formatter)

Convert a `logging.LogRecord' object into colored text, using ANSI escape sequences.

format(self, record)

Format the specified record as text.

The record's attribute dictionary is used as the operand to a string formatting operation which yields the returned string. Before formatting the dictionary, a couple of preparatory steps are carried out. The message attribute of the record is computed using LogRecord.getMessage(). If the formatting string uses the time (as determined by a call to usesTime(), formatTime() is called to format the event time. If there is exception information, it is formatted using formatException() and appended to the message.

Source code in bumpr/log.py
def format(self, record):
    msg = record.getMessage()
    if record.levelname == "INFO":
        return ansi("cyan", "-> ") + msg
    elif record.levelname == "DRYRUN":
        return ansi("magenta", "dryrun-> ") + msg
    elif record.levelname == "DIFF":
        if msg.startswith("+"):
            return ansi("green", msg)
        elif msg.startswith("-"):
            return ansi("red", msg)
        else:
            return msg
    else:
        color = LEVEL_COLORS.get(record.levelname, "white")
        return ansi(color, record.levelname.lower()) + ": " + msg

TextFormatter (Formatter)

Convert a `logging.LogRecord' object into text.

format(self, record)

Format the specified record as text.

The record's attribute dictionary is used as the operand to a string formatting operation which yields the returned string. Before formatting the dictionary, a couple of preparatory steps are carried out. The message attribute of the record is computed using LogRecord.getMessage(). If the formatting string uses the time (as determined by a call to usesTime(), formatTime() is called to format the event time. If there is exception information, it is formatted using formatException() and appended to the message.

Source code in bumpr/log.py
def format(self, record):
    if not record.levelname or record.levelname in ("INFO", "DIFF"):
        return record.getMessage()
    elif record.levelname == "DRYRUN":
        return "dryrun-> {0}".format(record.getMessage())
    else:
        return record.levelname.lower() + ": " + record.getMessage()

ansi(color, text)

Wrap text in an ansi escape sequence

Source code in bumpr/log.py
def ansi(color, text):
    """Wrap text in an ansi escape sequence"""
    code = COLOR_CODES[color]
    return "\033[1;{0}m{1}{2}".format(code, text, RESET_TERM)

releaser

Releaser

Release workflow executor

clean(self)

Clean the workspace

Source code in bumpr/releaser.py
def clean(self):
    """Clean the workspace"""
    if self.config.clean:
        logger.info("Cleaning")
        self.execute(self.config.clean)

publish(self)

Publish the current release to PyPI

Source code in bumpr/releaser.py
def publish(self):
    """Publish the current release to PyPI"""
    if self.config.publish:
        logger.info("Publish")
        self.execute(self.config.publish)

vcs

BaseVCS

commit(self, message)

Commit all modified files

Source code in bumpr/vcs.py
def commit(self, message):
    """Commit all modified files"""
    raise NotImplementedError

execute(self, command)

Execute a command

Source code in bumpr/vcs.py
def execute(self, command):
    """Execute a command"""
    execute(command, verbose=self.verbose)

push(self)

Push changes to remote repository

Source code in bumpr/vcs.py
def push(self):
    """Push changes to remote repository"""
    raise NotImplementedError

tag(self, name, annotation=None)

Create a tag

Source code in bumpr/vcs.py
def tag(self, name, annotation=None):
    """Create a tag"""
    raise NotImplementedError

validate(self, dryrun=False)

Ensure the working dir is a repository and there is no modified files

Source code in bumpr/vcs.py
def validate(self, dryrun=False):
    """Ensure the working dir is a repository and there is no modified files"""
    raise NotImplementedError

Bazaar (BaseVCS)

commit(self, message)

Commit all modified files

Source code in bumpr/vcs.py
def commit(self, message):
    self.execute(["bzr", "commit", "-m", message])

push(self)

Push changes to remote repository

Source code in bumpr/vcs.py
def push(self):
    self.execute(["bzr", "push"])

tag(self, name, annotation=None)

Create a tag

Source code in bumpr/vcs.py
def tag(self, name, annotation=None):
    if annotation:
        log.warning("Tag annotation is not supported by Bazaar")
    self.execute(["bzr", "tag", name])

validate(self, dryrun=False)

Ensure the working dir is a repository and there is no modified files

Source code in bumpr/vcs.py
def validate(self, dryrun=False):
    if not isdir(".bzr"):
        raise BumprError("Current directory is not a bazaar repopsitory")

    for line in execute("bzr status --short", verbose=False).splitlines():
        if not line.startswith("?"):
            if dryrun:
                log.warning(MSG)
                break
            else:
                raise BumprError(MSG)

Fake (BaseVCS)

validate(self, dryrun=False)

Ensure the working dir is a repository and there is no modified files

Source code in bumpr/vcs.py
def validate(self, dryrun=False):
    return True

Git (BaseVCS)

commit(self, message)

Commit all modified files

Source code in bumpr/vcs.py
def commit(self, message):
    self.execute(["git", "commit", "-am", message])

push(self)

Push changes to remote repository

Source code in bumpr/vcs.py
def push(self):
    self.execute(["git", "push"])
    self.execute(["git", "push", "--tags"])

tag(self, name, annotation=None)

Create a tag

Source code in bumpr/vcs.py
def tag(self, name, annotation=None):
    cmd = ["git", "tag", name]
    if annotation:
        cmd += ["--annotate", "-m", '"{0}"'.format(annotation)]
    self.execute(cmd)

validate(self, dryrun=False)

Ensure the working dir is a repository and there is no modified files

Source code in bumpr/vcs.py
def validate(self, dryrun=False):
    if not isdir(".git"):
        raise BumprError("Current directory is not a git repopsitory")

    for line in execute("git status --porcelain", verbose=False).splitlines():
        if not line.startswith("??"):
            if dryrun:
                log.warning(MSG)
                break
            else:
                raise BumprError(MSG)

Mercurial (BaseVCS)

commit(self, message)

Commit all modified files

Source code in bumpr/vcs.py
def commit(self, message):
    self.execute(["hg", "commit", "-A", "-m", message])

push(self)

Push changes to remote repository

Source code in bumpr/vcs.py
def push(self):
    self.execute(["hg", "push"])

tag(self, name, annotation=None)

Create a tag

Source code in bumpr/vcs.py
def tag(self, name, annotation=None):
    cmd = ["hg", "tag", name]
    if annotation:
        cmd += ["-m", '"{0}"'.format(annotation)]
    self.execute(cmd)

validate(self, dryrun=False)

Ensure the working dir is a repository and there is no modified files

Source code in bumpr/vcs.py
def validate(self, dryrun=False):
    if not isdir(".hg"):
        raise BumprError("Current directory is not a mercurial repopsitory")

    for line in execute("hg status -mard", verbose=False).splitlines():
        if not line.startswith("??"):
            if dryrun:
                log.warning(MSG)
                break
            else:
                raise BumprError(MSG)
Back to top