Skip to content

Commit

Permalink
Merge pull request #931 from python-cmd2/branching_strategy
Browse files Browse the repository at this point in the history
Added info on SemVer and branching strategy to CONTRIBUTING.md
  • Loading branch information
tleonhardt committed Apr 25, 2020
2 parents 9c7bbfa + 9b78cf4 commit d4653e6
Show file tree
Hide file tree
Showing 42 changed files with 143 additions and 63 deletions.
39 changes: 33 additions & 6 deletions CONTRIBUTING.md
Expand Up @@ -65,7 +65,7 @@ The tables below list all prerequisites along with the minimum required version
#### Additional prerequisites to build cmd2 documentation
| Prerequisite | Minimum Version |
| ------------------------------------------- | --------------- |
| [sphinx](http://www.sphinx-doc.org) | `1.4.9` |
| [sphinx](http://www.sphinx-doc.org) | `2.0.0` |
| [sphinx-rtd-theme](https://github.com/snide/sphinx_rtd_theme) | `0.1.9` |

#### Optional prerequisites for enhanced unit test features
Expand Down Expand Up @@ -211,7 +211,7 @@ pipenv install --dev
To create a new virtualenv, using a specific version of Python you have installed (and on your PATH), use the
--python VERSION flag, like so:
```sh
pipenv install --dev --python 3.7
pipenv install --dev --python 3.8
```

Then you can enter that virtual environment with:
Expand All @@ -221,8 +221,8 @@ pipenv shell

#### Create a new environment for cmd2 using Conda
```sh
$ conda create -n cmd2_py36 python=3.6
$ conda activate cmd2_py36
$ conda create -n cmd2_py37 python=3.7
$ conda activate cmd2_py37
```

#### Create a new environment for cmd using Virtualenv
Expand All @@ -233,13 +233,13 @@ We recommend that you use [pyenv](https://github.com/pyenv/pyenv) to manage your
pyenv versions

# Install python version defined
pyenv install 3.6.3
pyenv install 3.8.2
```
With the Python version installed, you can set the virtualenv properly.

```sh
$ cd ~/src/cmd2
$ virtualenv -p $(pyenv root)/versions/3.6.3/ cmd_py36
$ virtualenv -p $(pyenv root)/versions/3.8.2/ cmd_py38
$ source ~/src/cmd2/bin/activate
```

Expand Down Expand Up @@ -544,6 +544,33 @@ excellent support for debugging console applications.

[PyCharm](https://www.jetbrains.com/pycharm/) is also quite good and has very nice [code inspection](https://www.jetbrains.com/help/pycharm/code-inspection.html) capabilities.

## Branching Strategy and Semantic Versioning

Starting with version 1.0.0, `cmd2` has adopted [Semantic Versioning](https://semver.org).

### Semantic Versioning Summary
Given a version number `MAJOR`.`MINOR`.`PATCH`, increment the:

- `MAJOR` version when you make incompatible API changes,
- `MINOR` version when you add functionality in a backwards compatible manner, and
- `PATCH` version when you make backwards compatible bug fixes.

### Branching Strategy

We use the **master** branch for the upcoming `PATCH` release - i.e. if the current version
of `cmd2` is 1.0.2, then the **master** branch contains code which is planned for release
in 1.0.3.

If work needs to be done for a `MAJOR` or `MINOR` release when we anticipate there will be
a `PATCH` release in-between, then a branch should be created named for the appropriate version
number for the work, e.g. if the current release of `cmd2` is 1.0.2 and a backwards-incompatible
change needs to be committed for an upcoming `MAJOR` release, then this work should be committed
to a **2.0.0** branch until such a time as we are ready to release version 2.0.0.

Following this strategy, releases are always done from the **master** branch and `MAJOR` or `MINOR`
branches are merged to **master** immediately prior to doing a release. Once merged to **master**, the
other branches can be deleted. All releases are tagged so that they can be reproduced if necessary.

## Publishing a new release

Since 0.9.2, the process of publishing a new release of `cmd2` to [PyPi](https://pypi.org/) has been
Expand Down
1 change: 1 addition & 0 deletions Pipfile
Expand Up @@ -18,6 +18,7 @@ flake8 = "*"
gnureadline = {version = "*",sys_platform = "== 'darwin'"}
invoke = "*"
ipython = "*"
isort = "*"
mock = {version = "*",markers = "python_version < '3.6'"}
plumbum = "*"
pyreadline = {version = "*",sys_platform = "== 'win32'"}
Expand Down
4 changes: 2 additions & 2 deletions cmd2/ansi.py
Expand Up @@ -6,10 +6,10 @@
import functools
import re
from enum import Enum
from typing import Any, IO, List, Union
from typing import IO, Any, List, Union

import colorama
from colorama import Fore, Back, Style
from colorama import Back, Fore, Style
from wcwidth import wcswidth

# On Windows, filter ANSI escape codes out of text sent to stdout/stderr, and replace them with equivalent Win32 calls
Expand Down
14 changes: 10 additions & 4 deletions cmd2/argparse_completer.py
Expand Up @@ -14,10 +14,16 @@
from typing import Dict, List, Optional, Union

from . import ansi, cmd2, constants
from .argparse_custom import ATTR_CHOICES_CALLABLE, generate_range_error
from .argparse_custom import ATTR_SUPPRESS_TAB_HINT, ATTR_DESCRIPTIVE_COMPLETION_HEADER, ATTR_NARGS_RANGE
from .argparse_custom import ChoicesCallable, CompletionItem
from .utils import basic_complete, CompletionError
from .argparse_custom import (
ATTR_CHOICES_CALLABLE,
ATTR_DESCRIPTIVE_COMPLETION_HEADER,
ATTR_NARGS_RANGE,
ATTR_SUPPRESS_TAB_HINT,
ChoicesCallable,
CompletionItem,
generate_range_error,
)
from .utils import CompletionError, basic_complete

# If no descriptive header is supplied, then this will be used instead
DEFAULT_DESCRIPTIVE_HEADER = 'Description'
Expand Down
2 changes: 1 addition & 1 deletion cmd2/argparse_custom.py
Expand Up @@ -203,7 +203,7 @@ def my_completer_method(self, text, line, begidx, endidx, arg_tokens)
import re
import sys
# noinspection PyUnresolvedReferences,PyProtectedMember
from argparse import ZERO_OR_MORE, ONE_OR_MORE, ArgumentError, _
from argparse import ONE_OR_MORE, ZERO_OR_MORE, ArgumentError, _
from typing import Callable, Optional, Tuple, Type, Union

from . import ansi, constants
Expand Down
11 changes: 4 additions & 7 deletions cmd2/cmd2.py
Expand Up @@ -42,17 +42,14 @@
from contextlib import redirect_stdout
from typing import Any, Callable, Dict, Iterable, List, Mapping, Optional, Tuple, Type, Union

from . import ansi
from . import constants
from . import plugin
from . import utils
from .argparse_custom import CompletionItem, DEFAULT_ARGUMENT_PARSER
from . import ansi, constants, plugin, utils
from .argparse_custom import DEFAULT_ARGUMENT_PARSER, CompletionItem
from .clipboard import can_clip, get_paste_buffer, write_to_paste_buffer
from .decorators import with_argparser
from .exceptions import Cmd2ArgparseError, Cmd2ShlexError, EmbeddedConsoleExit, EmptyStatement, RedirectionError
from .history import History, HistoryItem
from .parsing import StatementParser, Statement, Macro, MacroArg, shlex_split
from .rl_utils import rl_type, RlType, rl_get_point, rl_set_prompt, vt100_support, rl_make_safe_prompt, rl_warning
from .parsing import Macro, MacroArg, Statement, StatementParser, shlex_split
from .rl_utils import RlType, rl_get_point, rl_make_safe_prompt, rl_set_prompt, rl_type, rl_warning, vt100_support
from .utils import CompletionError, Settable

# Set up readline
Expand Down
1 change: 0 additions & 1 deletion cmd2/history.py
Expand Up @@ -4,7 +4,6 @@
"""

import re

from typing import List, Union

import attr
Expand Down
3 changes: 1 addition & 2 deletions cmd2/parsing.py
Expand Up @@ -8,8 +8,7 @@

import attr

from . import constants
from . import utils
from . import constants, utils
from .exceptions import Cmd2ShlexError


Expand Down
4 changes: 2 additions & 2 deletions cmd2/py_bridge.py
Expand Up @@ -5,10 +5,10 @@
"""

import sys
from contextlib import redirect_stdout, redirect_stderr
from contextlib import redirect_stderr, redirect_stdout
from typing import Optional

from .utils import namedtuple_with_defaults, StdSim
from .utils import StdSim, namedtuple_with_defaults


class CommandResult(namedtuple_with_defaults('CommandResult', ['stdout', 'stderr', 'stop', 'data'])):
Expand Down
2 changes: 1 addition & 1 deletion cmd2/rl_utils.py
Expand Up @@ -2,8 +2,8 @@
"""
Imports the proper readline for the platform and provides utility functions for it
"""
from enum import Enum
import sys
from enum import Enum

# Prefer statically linked gnureadline if available (for macOS compatibility due to issues with libedit)
try:
Expand Down
3 changes: 1 addition & 2 deletions docs/conf.py
Expand Up @@ -17,10 +17,9 @@
add these directories to sys.path here. If the directory is relative to the
documentation root, use os.path.abspath to make it absolute, like shown here.
"""
from pkg_resources import get_distribution

# Import for custom theme from Read the Docs
import sphinx_rtd_theme
from pkg_resources import get_distribution

# -- General configuration -----------------------------------------------------

Expand Down
1 change: 1 addition & 0 deletions examples/alias_startup.py
Expand Up @@ -5,6 +5,7 @@
2) How to run an initialization script at startup
"""
import os

import cmd2


Expand Down
4 changes: 2 additions & 2 deletions examples/argparse_completion.py
Expand Up @@ -6,8 +6,8 @@
import argparse
from typing import Dict, List

from cmd2 import Cmd, Cmd2ArgumentParser, with_argparser, CompletionItem
from cmd2.utils import basic_complete, CompletionError
from cmd2 import Cmd, Cmd2ArgumentParser, CompletionItem, with_argparser
from cmd2.utils import CompletionError, basic_complete

# Data source for argparse.choices
food_item_strs = ['Pizza', 'Ham', 'Ham Sandwich', 'Potato']
Expand Down
2 changes: 1 addition & 1 deletion examples/async_printing.py
Expand Up @@ -10,7 +10,7 @@
from typing import List

import cmd2
from cmd2 import style, fg
from cmd2 import fg, style

ALERTS = ["Watch as this application prints alerts and updates the prompt",
"This will only happen when the prompt is present",
Expand Down
2 changes: 1 addition & 1 deletion examples/basic.py
Expand Up @@ -9,7 +9,7 @@
6) Shell-like capabilities
"""
import cmd2
from cmd2 import style, fg, bg
from cmd2 import bg, fg, style


class BasicApp(cmd2.Cmd):
Expand Down
3 changes: 2 additions & 1 deletion examples/colors.py
Expand Up @@ -26,9 +26,10 @@
import argparse
from typing import Any

from colorama import Back, Fore, Style

import cmd2
from cmd2 import ansi
from colorama import Fore, Back, Style


class CmdLineApp(cmd2.Cmd):
Expand Down
3 changes: 1 addition & 2 deletions examples/custom_parser.py
Expand Up @@ -4,8 +4,7 @@
"""
import sys

from cmd2 import Cmd2ArgumentParser, set_default_argument_parser
from cmd2 import ansi
from cmd2 import Cmd2ArgumentParser, ansi, set_default_argument_parser


# First define the parser
Expand Down
3 changes: 2 additions & 1 deletion examples/exit_code.py
Expand Up @@ -2,9 +2,10 @@
# coding=utf-8
"""A simple example demonstrating the following how to emit a non-zero exit code in your cmd2 application.
"""
import cmd2
from typing import List

import cmd2


class ReplWithExitCode(cmd2.Cmd):
""" Example cmd2 application where we can specify an exit code when existing."""
Expand Down
1 change: 0 additions & 1 deletion examples/hooks.py
Expand Up @@ -10,7 +10,6 @@
"""

import re

from typing import List

import cmd2
Expand Down
2 changes: 1 addition & 1 deletion examples/initialization.py
Expand Up @@ -13,7 +13,7 @@
10) How to make custom attributes settable at runtime
"""
import cmd2
from cmd2 import style, fg, bg
from cmd2 import bg, fg, style


class BasicApp(cmd2.Cmd):
Expand Down
3 changes: 1 addition & 2 deletions examples/migrating.py
Expand Up @@ -3,9 +3,8 @@
"""
A sample application for cmd which can be used to show how to migrate to cmd2.
"""
import random

import cmd
import random


class CmdLineApp(cmd.Cmd):
Expand Down
4 changes: 3 additions & 1 deletion examples/override_parser.py
Expand Up @@ -10,12 +10,14 @@
# See the code for custom_parser.py. It simply defines a parser and calls cmd2.set_default_argument_parser()
# with the custom parser's type.
import argparse
argparse.cmd2_parser_module = 'examples.custom_parser'

# Next import stuff from cmd2. It will import your module just before the cmd2.Cmd class file is imported
# and therefore override the parser class it uses on its commands.
from cmd2 import cmd2

argparse.cmd2_parser_module = 'examples.custom_parser'


if __name__ == '__main__':
import sys
app = cmd2.Cmd(use_ipython=True, persistent_history_file='cmd2_history.dat')
Expand Down
3 changes: 2 additions & 1 deletion examples/plumbum_colors.py
Expand Up @@ -27,9 +27,10 @@
"""
import argparse

from plumbum.colors import bg, fg

import cmd2
from cmd2 import ansi
from plumbum.colors import fg, bg


class FgColors(ansi.ColorBase):
Expand Down
1 change: 1 addition & 0 deletions examples/scripts/arg_printer.py
Expand Up @@ -2,6 +2,7 @@
# coding=utf-8
import os
import sys

print("Running Python script {!r} which was called with {} arguments".format(os.path.basename(sys.argv[0]),
len(sys.argv) - 1))
for i, arg in enumerate(sys.argv[1:]):
Expand Down
1 change: 1 addition & 0 deletions examples/subcommands.py
Expand Up @@ -7,6 +7,7 @@
and provides separate contextual help.
"""
import argparse

import cmd2

sport_item_strs = ['Bat', 'Basket', 'Basketball', 'Football', 'Space Ball']
Expand Down
1 change: 1 addition & 0 deletions examples/unicode_commands.py
Expand Up @@ -3,6 +3,7 @@
"""A simple example demonstrating support for unicode command names.
"""
import math

import cmd2


Expand Down
17 changes: 17 additions & 0 deletions setup.cfg
@@ -0,0 +1,17 @@
[flake8]
exclude = .git,.idea,.pytest_cache,.tox,.venv,.vscode,build,cmd2.egg-info,dist,htmlcov,__pycache__,*.egg
max-line-length = 127
max-complexity = 26

[isort]
line_length=127
skip=cmd2/__init__.py
multi_line_output = 3
include_trailing_comma = true
force_grid_wrap = 0
use_parentheses = true

[doc8]
ignore-path=docs/_build,.git,.idea,.pytest_cache,.tox,.venv,.vscode,build,cmd2,examples,tests,cmd2.egg-info,dist,htmlcov,__pycache__,*.egg
;max-line-length=99
verbose=0
1 change: 1 addition & 0 deletions setup.py
Expand Up @@ -4,6 +4,7 @@
Setuptools setup file, used to install or test 'cmd2'
"""
import codecs

from setuptools import setup

DESCRIPTION = "cmd2 - quickly build feature-rich and user-friendly interactive command line applications in Python"
Expand Down
1 change: 1 addition & 0 deletions tasks.py
Expand Up @@ -15,6 +15,7 @@

import invoke


# shared function
def rmrf(items, verbose=True):
"Silently remove a list of directories or files"
Expand Down

0 comments on commit d4653e6

Please sign in to comment.