diff --git a/README.md b/README.md index 9f76b1c..ef18791 100644 --- a/README.md +++ b/README.md @@ -45,7 +45,7 @@ Usage: changes [options] changelog changes [options] release changes [options] bump_version - changes [options] test + changes [options] run_tests changes [options] install changes [options] upload changes [options] pypi @@ -68,12 +68,15 @@ Options: --tox Use `tox` instead of the default: `nosetests` --test-command= Command to use to test the newly installed package --version-prefix= Specify a prefix for version number tags + --noinput To be used in conjuction with one of the increment + options above, this option stops `changes` from + confirming the new version number. --debug Debug output. The commands do the following: changelog Generates an automatic changelog from your commit messages bump_version Increments the __version__ attribute of your module's __init__ - test Runs your tests with nosetests + run_tests Runs your tests with nosetests install Attempts to install the sdist tag Tags your git repo with the new version number upload Uploads your project with setup.py clean sdist upload @@ -176,7 +179,7 @@ Lint the project with: Generate the documentation with: - cd docs && PYTHONPATH=.. make singlehtml + (cd docs && make singlehtml) To monitor changes to Python files and execute flake8 and nosetests automatically, execute the following from the root project directory: diff --git a/changes/__init__.py b/changes/__init__.py index 88e555f..f21a308 100644 --- a/changes/__init__.py +++ b/changes/__init__.py @@ -7,4 +7,4 @@ from .cli import main # noqa -from .pandoc import md2rst +from .pandoc import md2rst # noqa diff --git a/changes/attributes.py b/changes/attributes.py index 87c1c66..ee2e352 100644 --- a/changes/attributes.py +++ b/changes/attributes.py @@ -4,7 +4,7 @@ from path import path -from changes import shell +import sh log = logging.getLogger(__name__) @@ -32,10 +32,7 @@ def replace_attribute(app_name, attribute_name, new_value, dry_run=True): if not dry_run: path(tmp_file).move(init_file) else: - log.debug(shell.execute( - 'diff %s %s' % (tmp_file, init_file), - dry_run=False - )) + log.debug(sh.diff(tmp_file, init_file, _ok_code=1)) def has_attribute(app_name, attribute_name): diff --git a/changes/changelog.py b/changes/changelog.py new file mode 100644 index 0000000..9b96567 --- /dev/null +++ b/changes/changelog.py @@ -0,0 +1,102 @@ +import logging +import re + +import sh +from changes import attributes, config, version + +log = logging.getLogger(__name__) + + +def write_new_changelog(app_name, filename, content_lines, dry_run=True): + heading_and_newline = ( + '# [Changelog](%s/releases)\n' % + attributes.extract_attribute(app_name, '__url__') + ) + + with open(filename, 'r+') as f: + existing = f.readlines() + + output = existing[2:] + output.insert(0, '\n') + + for index, line in enumerate(content_lines): + output.insert(0, content_lines[len(content_lines) - index - 1]) + + output.insert(0, heading_and_newline) + + output = ''.join(output) + + if not dry_run: + with open(filename, 'w+') as f: + f.write(output) + else: + log.info('New changelog:\n%s', ''.join(content_lines)) + + +def replace_sha_with_commit_link(git_log_content): + repo_url = attributes.extract_attribute( + config.common_arguments()[0], + '__url__' + ) + + for index, line in enumerate(git_log_content): + # http://stackoverflow.com/a/468378/5549 + sha1_re = re.match(r'^[0-9a-f]{5,40}\b', line) + if sha1_re: + sha1 = sha1_re.group() + + new_line = line.replace( + sha1, + '[%s](%s/commit/%s)' % (sha1, repo_url, sha1) + ) + log.debug('old line: %s\nnew line: %s', line, new_line) + git_log_content[index] = new_line + + return git_log_content + + +def changelog(): + app_name, dry_run, new_version = config.common_arguments() + + changelog_content = [ + '\n## [%s](%s/compare/%s...%s)\n\n' % ( + new_version, attributes.extract_attribute(app_name, '__url__'), + version.current_version(app_name), new_version, + ) + ] + + git_log_content = sh.git.log( + '--oneline', + '--no-merges', + '%s..master' % version.current_version(app_name), + _tty_out=False + ).split('\n') + log.debug('content: %s' % git_log_content) + + if not git_log_content: + log.debug('sniffing initial release, drop tags') + git_log_content = sh.git.log( + '--oneline', + '--no-merges', + _tty_out=False + ).split('\n') + + git_log_content = replace_sha_with_commit_link(git_log_content) + + log.debug('content: %s' % git_log_content) + + # makes change log entries into bullet points + if git_log_content: + [ + changelog_content.append('* %s\n' % line) + if line else line + for line in git_log_content[:-1] + ] + + write_new_changelog( + app_name, + config.CHANGELOG, + changelog_content, + dry_run=dry_run + ) + log.info('Added content to CHANGELOG.md') diff --git a/changes/cli.py b/changes/cli.py index c14726a..da795a0 100644 --- a/changes/cli.py +++ b/changes/cli.py @@ -5,7 +5,7 @@ changes [options] changelog changes [options] release changes [options] bump_version - changes [options] test + changes [options] run_tests changes [options] install changes [options] upload changes [options] pypi @@ -28,251 +28,36 @@ --tox Use `tox` instead of the default: `nosetests` --test-command= Command to use to test the newly installed package --version-prefix= Specify a prefix for version number tags + --noinput To be used in conjuction with one of the increment + options above, this option stops `changes` from + confirming the new version number. --debug Debug output. The commands do the following: changelog Generates an automatic changelog from your commit messages bump_version Increments the __version__ attribute of your module's __init__ - test Runs your tests with nosetests + run_tests Runs your tests with nosetests install Attempts to install the sdist tag Tags your git repo with the new version number upload Uploads your project with setup.py clean sdist upload pypi Attempts to install your package from pypi release Runs all the previous commands """ - -import re - -import tempfile +import logging from docopt import docopt -from path import path -import logging -import virtualenv import changes -from changes import attributes, probe, shell, version +from changes import config, probe, util, version +from changes.changelog import changelog +from changes.config import arguments +from changes.packaging import install, upload, pypi +from changes.vcs import tag, commit_version_change +from changes.verification import run_tests +from changes.version import bump_version log = logging.getLogger(__name__) -CHANGELOG = 'CHANGELOG.md' -arguments = None - - -def common_arguments(): - """ - Return common arguments - - :return: tuple of , --dry-run, new_version - """ - return ( - arguments[''], - arguments['--dry-run'], - arguments['new_version'], - ) - - -def write_new_changelog(app_name, filename, content_lines, dry_run=True): - heading_and_newline = ( - '# [Changelog](%s/releases)\n' % - attributes.extract_attribute(app_name, '__url__') - ) - - with open(filename, 'r+') as f: - existing = f.readlines() - - output = existing[2:] - output.insert(0, '\n') - - for index, line in enumerate(content_lines): - output.insert(0, content_lines[len(content_lines) - index - 1]) - - output.insert(0, heading_and_newline) - - output = ''.join(output) - - if not dry_run: - with open(filename, 'w+') as f: - f.write(output) - else: - log.info('New changelog:\n%s', ''.join(content_lines)) - - -def changelog(): - app_name, dry_run, new_version = common_arguments() - - changelog_content = [ - '\n## [%s](%s/compare/%s...%s)\n\n' % ( - new_version, attributes.extract_attribute(app_name, '__url__'), - version.current_version(app_name), new_version, - ) - ] - git_log = 'git log --oneline --no-merges' - version_difference = '%s..master' % version.current_version(app_name) - - git_log_content = shell.execute( - '%s %s' % (git_log, version_difference), - dry_run=False - ) - - if not git_log_content: - log.debug('sniffing initial release, drop tags: %s', git_log) - git_log_content = shell.execute(git_log, dry_run=False) - - for index, line in enumerate(git_log_content): - # http://stackoverflow.com/a/468378/5549 - sha1_re = re.match(r'^[0-9a-f]{5,40}\b', line) - if sha1_re: - sha1 = sha1_re.group() - - new_line = line.replace( - sha1, - '[%s](%s/commit/%s)' % ( - sha1, - attributes.extract_attribute(app_name, '__url__'), - sha1 - ) - ) - log.debug('old line: %s\nnew line: %s', line, new_line) - git_log_content[index] = new_line - - if git_log_content: - [ - changelog_content.append('* %s\n' % line) - if line else line - for line in git_log_content[:-1] - ] - - write_new_changelog( - app_name, - CHANGELOG, - changelog_content, - dry_run=dry_run - ) - log.info('Added content to CHANGELOG.md') - - -def bump_version(): - app_name, dry_run, new_version = common_arguments() - - attributes.replace_attribute( - app_name, - '__version__', - new_version, - dry_run=dry_run) - - -def commit_version_change(): - app_name, dry_run, new_version = common_arguments() - - command = 'git commit -m %s %s/__init__.py %s' % ( - new_version, app_name, CHANGELOG - ) - - if not (shell.execute(command, dry_run=dry_run) and - shell.execute('git push', dry_run=dry_run)): - raise Exception('Version change commit failed') - - -def test(): - command = 'nosetests' - if arguments['--tox']: - command = 'tox' - - if not shell.execute(command, dry_run=False): - raise Exception('Test command failed') - - -def make_virtualenv(): - tmp_dir = tempfile.mkdtemp() - virtualenv.create_environment(tmp_dir, site_packages=False) - return tmp_dir - - -def run_test_command(): - if arguments['--test-command']: - test_command = arguments['--test-command'] - result = shell.execute(test_command, dry_run=arguments['--dry-run']) - log.info('Test command "%s", returned %s', test_command, result) - else: - log.warning('Test command "%s" failed', test_command) - - -def install(): - app_name, dry_run, new_version = common_arguments() - - result = shell.execute('python setup.py clean sdist', dry_run=dry_run) - if result: - tmp_dir = make_virtualenv() - try: - virtualenv.install_sdist( - arguments[''], - 'dist/%s-%s.tar.gz' % (app_name, new_version), - '%s/bin/python' % tmp_dir - ) - log.info('Successfully installed %s sdist', app_name) - if run_test_command(): - log.info('Successfully ran test command: %s', - arguments['--test-command']) - except: - raise Exception('Error installing %s sdist', app_name) - - path(tmp_dir).rmtree(path(tmp_dir)) - - -def upload(): - app_name, dry_run, new_version = common_arguments() - pypi = arguments['--pypi'] - - upload = 'python setup.py clean sdist upload' - if pypi: - upload = upload + '-r %s' % pypi - - if not shell.execute(upload, dry_run=dry_run): - raise Exception('Error uploading') - else: - log.info('Succesfully uploaded %s %s', app_name, new_version) - - -def pypi(): - app_name, dry_run, _ = common_arguments() - pypi = arguments['--pypi'] - package_index = 'pypi' - - tmp_dir = make_virtualenv() - install = '%s/bin/pip install %s' % (tmp_dir, app_name) - - if pypi: - install = install + '-i %s' % pypi - package_index = pypi - - try: - result = shell.execute(install, dry_run=dry_run) - if result: - log.info('Successfully installed %s from %s', - app_name, package_index) - else: - log.error('Failed to install %s from %s', - app_name, package_index) - - run_test_command() - except: - raise Exception('Error installing %s from %s', app_name, package_index) - - path(tmp_dir).rmtree(path(tmp_dir)) - - -def tag(): - _, dry_run, new_version = common_arguments() - - if arguments['--version-prefix']: - new_version = arguments['--version-prefix'] + new_version - - shell.execute( - 'git tag -a %s -m "%s"' % (new_version, new_version), - dry_run=dry_run - ) - shell.execute('git push --tags', dry_run=dry_run) def release(): @@ -280,7 +65,7 @@ def release(): if not arguments['--skip-changelog']: changelog() bump_version() - test() + run_tests() commit_version_change() install() upload() @@ -291,24 +76,26 @@ def release(): def initialise(): - global arguments arguments = docopt(__doc__, version=changes.__version__) debug = arguments['--debug'] logging.basicConfig(level=logging.DEBUG if debug else logging.INFO) log.debug('arguments: %s', arguments) + config.arguments = arguments + return arguments def main(): - initialise() + arguments = initialise() - commands = ['release', 'changelog', 'test', 'bump_version', 'tag', + version_arguments = ['--major', '--minor', '--patch'] + commands = ['release', 'changelog', 'run_tests', 'bump_version', 'tag', 'upload', 'install', 'pypi'] - suppress_version_prompt_for = ['test', 'upload'] + suppress_version_prompt_for = ['run_tests', 'upload'] if arguments['--new-version']: arguments['new_version'] = arguments['--new-version'] - app_name = arguments[''] + app_name = config.arguments[''] if not probe.probe_project(app_name): raise Exception('Project does not meet `changes` requirements') @@ -319,6 +106,7 @@ def main(): arguments['new_version'] = version.get_new_version( app_name, version.current_version(app_name), - **version.extract_version_arguments(arguments) + arguments.get('--noinput', False), + **util.extract_arguments(arguments, version_arguments) ) globals()[command]() diff --git a/changes/compat.py b/changes/compat.py new file mode 100644 index 0000000..b161f39 --- /dev/null +++ b/changes/compat.py @@ -0,0 +1,23 @@ +from subprocess import Popen, PIPE, CalledProcessError + + +def check_output(*popenargs, **kwargs): + """ + Run command with arguments and return its output as a byte string. + + Backported from Python 2.7 as it's implemented as pure python on stdlib. + + >>> check_output(['/usr/bin/python', '--version']) + Python 2.6.2 + """ + process = Popen(stdout=PIPE, *popenargs, **kwargs) + output, unused_err = process.communicate() + retcode = process.poll() + if retcode: + cmd = kwargs.get("args") + if cmd is None: + cmd = popenargs[0] + error = CalledProcessError(retcode, cmd) + error.output = output + raise error + return output diff --git a/changes/config.py b/changes/config.py new file mode 100644 index 0000000..eb2164c --- /dev/null +++ b/changes/config.py @@ -0,0 +1,22 @@ +CHANGELOG = 'CHANGELOG.md' +arguments = {} + + +def common_arguments(): + """ + Return common arguments + + :return: tuple of , --dry-run, new_version + """ + + app_name = arguments[''] + + version_prefix = arguments.get('--version-prefix') + new_version = arguments['new_version'] + + common_arguments = ( + app_name, + arguments['--dry-run'], + version_prefix + new_version if version_prefix else new_version, + ) + return common_arguments diff --git a/changes/packaging.py b/changes/packaging.py new file mode 100644 index 0000000..74e4ef8 --- /dev/null +++ b/changes/packaging.py @@ -0,0 +1,82 @@ +import logging +import tempfile + +from path import path +import sh +import virtualenv + +from changes import config, shell, verification + +log = logging.getLogger(__name__) + + +def make_virtualenv(): + tmp_dir = tempfile.mkdtemp() + virtualenv.create_environment(tmp_dir, site_packages=False) + return tmp_dir + + +def install(): + app_name, dry_run, new_version = config.common_arguments() + + result = shell.handle_dry_run(sh.python, ('setup.py', 'clean', 'sdist')) + if result: + tmp_dir = make_virtualenv() + try: + virtualenv.install_sdist( + config.arguments[''], + 'dist/%s-%s.tar.gz' % (app_name, new_version), + '%s/bin/python' % tmp_dir + ) + log.info('Successfully installed %s sdist', app_name) + if verification.run_test_command(): + log.info('Successfully ran test command: %s', + config.arguments['--test-command']) + except: + raise Exception('Error installing %s sdist', app_name) + + path(tmp_dir).rmtree(path(tmp_dir)) + + +def upload(): + app_name, dry_run, new_version = config.common_arguments() + pypi = config.arguments['--pypi'] + + upload_args = 'setup.py clean sdist upload'.split(' ') + if pypi: + upload_args.extend(['-r', pypi]) + + upload_result = shell.handle_dry_run(sh.python, tuple(upload_args)) + if not upload_result: + raise Exception('Error uploading') + else: + log.info('Succesfully uploaded %s %s', app_name, new_version) + + +def pypi(): + app_name, dry_run, _ = config.common_arguments() + + tmp_dir = make_virtualenv() + install_cmd = '%s/bin/pip install %s' % (tmp_dir, app_name) + + package_index = 'pypi' + pypi = config.arguments['--pypi'] + if pypi: + install_cmd += '-i %s' % pypi + package_index = pypi + + try: + result = shell.execute(install_cmd, dry_run=dry_run) + if result: + log.info('Successfully installed %s from %s', + app_name, package_index) + else: + log.error('Failed to install %s from %s', + app_name, package_index) + + verification.run_test_command() + except: + log.exception('error installing %s from %s', app_name, package_index) + raise Exception('Error installing %s from %s', app_name, package_index) + + path(tmp_dir).rmtree(path(tmp_dir)) diff --git a/changes/probe.py b/changes/probe.py index 405f680..3a40dd4 100644 --- a/changes/probe.py +++ b/changes/probe.py @@ -1,7 +1,9 @@ import logging from os.path import exists -from changes import attributes, shell +import sh + +from changes import attributes log = logging.getLogger(__name__) @@ -16,9 +18,9 @@ def probe_project(app_name): """ Check if the project meets `changes` requirements """ - log.info('Checking project for changes requirements..self.') + log.info('Checking project for changes requirements.') # on [github](https://github.com) - git_remotes = shell.execute('git remote -v', dry_run=False) + git_remotes = sh.git.remote('-v') on_github = any(['github.com' in remote for remote in git_remotes]) log.info('On Github? %s', on_github) @@ -45,7 +47,6 @@ def probe_project(app_name): log.info('Has module metadata? %s', has_metadata) # supports executing tests with `nosetests` or `tox` - log.debug(requirements_contents) runs_tests = ( has_requirement('nose', requirements_contents) or has_requirement('tox', requirements_contents) diff --git a/changes/shell.py b/changes/shell.py index fec3908..acd1412 100644 --- a/changes/shell.py +++ b/changes/shell.py @@ -1,17 +1,26 @@ import logging -import iterpipes +from changes import config +from changes.compat import check_output, CalledProcessError log = logging.getLogger(__name__) +def handle_dry_run(function, *args): + if not config.arguments.get('--dry-run', True): + return function(*args) + else: + log.debug('dry run of %s %s, skipping' % (function, args)) + return True + + def execute(command, dry_run=True): - log.debug('executing %s', command) if not dry_run: try: - return [result for result in iterpipes.linecmd(command)(None)] - except iterpipes.CalledProcessError, e: + return check_output(command.split(' ')).split('\n') + except CalledProcessError as e: log.debug('return code: %s, output: %s', e.returncode, e.output) return False else: + log.debug('dry run of %s, skipping' % command) return True diff --git a/changes/util.py b/changes/util.py index 12433c8..5d596ea 100644 --- a/changes/util.py +++ b/changes/util.py @@ -9,3 +9,14 @@ def extract(dictionary, keys): return dict( (k, dictionary[k]) for k in keys if k in dictionary ) + + +def extract_arguments(arguments, long_keys, key_prefix='--'): + long_arguments = extract( + arguments, + long_keys, + ) + return dict([ + (key.replace(key_prefix, ''), value) + for key, value in long_arguments.items() + ]) diff --git a/changes/vcs.py b/changes/vcs.py new file mode 100644 index 0000000..4465eb6 --- /dev/null +++ b/changes/vcs.py @@ -0,0 +1,35 @@ +import logging + +import sh + +from changes import config, shell + +log = logging.getLogger(__name__) + + +def commit_version_change(): + app_name, dry_run, new_version = config.common_arguments() + + commit_result = shell.handle_dry_run( + sh.git.commit, + ('-m', new_version, '%s/__init__.py' % app_name, config.CHANGELOG) + ) + + if commit_result: + push_result = shell.handle_dry_run(sh.git.push, ()) + if not push_result: + raise Exception('Version change commit failed') + + +def tag(): + _, dry_run, new_version = config.common_arguments() + + tag_result = shell.handle_dry_run( + sh.git.tag, + ('-a', new_version, '-m', '"%s"' % new_version) + ) + + if tag_result: + push_tags_result = shell.handle_dry_run(sh.git.push, ('--tags')) + if not push_tags_result: + raise Exception('Tagging failed') diff --git a/changes/verification.py b/changes/verification.py new file mode 100644 index 0000000..6e9f67f --- /dev/null +++ b/changes/verification.py @@ -0,0 +1,27 @@ +import logging + +import sh + +from changes import config, shell + +log = logging.getLogger(__name__) + + +def run_tests(): + if config.arguments['--tox']: + result = sh.tox() + else: + result = sh.nosetests() + + if not result: + raise Exception('Test command failed') + else: + return True + + +def run_test_command(): + if config.arguments['--test-command']: + test_command = config.arguments['--test-command'] + result = shell.execute(sh, tuple(test_command.split(' '))) + log.info('Test command "%s", returned %s', test_command, result) + return True diff --git a/changes/version.py b/changes/version.py index b44edb2..8674620 100644 --- a/changes/version.py +++ b/changes/version.py @@ -2,17 +2,27 @@ import semantic_version -from changes import util, attributes +from changes import config, attributes log = logging.getLogger(__name__) +def bump_version(): + app_name, dry_run, new_version = config.common_arguments() + + attributes.replace_attribute( + app_name, + '__version__', + new_version, + dry_run=dry_run) + + def current_version(app_name): return attributes.extract_attribute(app_name, '__version__') -def get_new_version(app_name, current_version, - major=False, minor=False, patch=True): +def get_new_version(app_name, current_version, no_input, + major=False, minor=False, patch=False): proposed_new_version = increment( current_version, @@ -21,26 +31,17 @@ def get_new_version(app_name, current_version, patch=patch ) - new_version = raw_input( - 'What is the release version for "%s" ' - '[Default: %s]: ' % ( - app_name, proposed_new_version - ) - ) - if not new_version: - return proposed_new_version.strip() + if no_input: + new_version = proposed_new_version.strip() else: - return new_version.strip() - + new_version = raw_input( + 'What is the release version for "%s" ' + '[Default: %s]: ' % ( + app_name, proposed_new_version + ) + ) -def extract_version_arguments(arguments): - long_arguments = util.extract( - arguments, - ['--major', '--minor', '--patch'], - ) - return dict([ - (key[2:], value) for key, value in long_arguments.items() - ]) + return new_version.strip() def increment(version, major=False, minor=False, patch=True): diff --git a/requirements.txt b/requirements.txt index 7473950..202be53 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,6 +1,5 @@ coverage < 4.0.0 docopt < 1.0.0 -iterpipes < 1.0.0 flake8 < 3.0.0 mock < 2.0.0 nose < 2.0.0 @@ -9,6 +8,7 @@ path.py < 5.0.0 pinocchio < 1.0.0 python-coveralls < 3.0.0 semantic_version < 3.0.0 +sh < 2.0.0 sphinx-bootstrap-theme < 1.0.0 sphinxcontrib-httpdomain < 2.0.0 testtube < 1.0.0 diff --git a/setup.py b/setup.py index 0c9a2b2..7a83f3c 100644 --- a/setup.py +++ b/setup.py @@ -18,10 +18,10 @@ packages=['changes'], install_requires=[ 'docopt < 1.0.0', - 'iterpipes < 1.0.0', - 'pypandoc < 1.0.0', 'path.py < 5.0.0', + 'pypandoc < 1.0.0', 'semantic_version < 3.0.0', + 'sh < 2.0.0', 'virtualenv < 2.0.0', ], entry_points={ diff --git a/tests/test_attributes.py b/tests/test_attributes.py index c69b3b1..cde3401 100644 --- a/tests/test_attributes.py +++ b/tests/test_attributes.py @@ -28,6 +28,22 @@ def test_replace_attribute(self): ) ) + def test_replace_attribute_dry_run(self): + attributes.replace_attribute( + 'test_app', + '__version__', + '1.0.0', + dry_run=True + ) + + expected_content = list(self.initial_init_content) + self.assertEquals( + '\n'.join(expected_content), + ''.join( + open(self.tmp_file).readlines() + ) + ) + def test_has_attribute(self): self.assertTrue( attributes.has_attribute( diff --git a/tests/test_changes.py b/tests/test_changelog.py similarity index 80% rename from tests/test_changes.py rename to tests/test_changelog.py index 5557c2b..328d61d 100644 --- a/tests/test_changes.py +++ b/tests/test_changelog.py @@ -1,8 +1,8 @@ -from changes import cli +from changes import changelog from . import BaseTestCase -class CliTestCase(BaseTestCase): +class ChangeLogTestCase(BaseTestCase): def test_write_new_changelog(self): content = [ @@ -13,7 +13,7 @@ def test_write_new_changelog(self): with open(self.tmp_file, 'w') as existing_file: existing_file.writelines(content) - cli.write_new_changelog('test_app', self.tmp_file, 'Now this is') + changelog.write_new_changelog('test_app', self.tmp_file, 'Now this is') self.assertEquals( ''.join(content), @@ -25,7 +25,7 @@ def test_write_new_changelog(self): with open(self.tmp_file, 'w') as existing_file: existing_file.writelines(content) - cli.write_new_changelog( + changelog.write_new_changelog( 'test_app', self.tmp_file, 'Now this is', @@ -42,3 +42,6 @@ def test_write_new_changelog(self): open(self.tmp_file).readlines() ) ) + + def test_changelog(self): + pass diff --git a/tests/test_config.py b/tests/test_config.py new file mode 100644 index 0000000..2c177fa --- /dev/null +++ b/tests/test_config.py @@ -0,0 +1,44 @@ +from changes import config +from . import BaseTestCase + + +class ConfigTestCase(BaseTestCase): + arguments = { + '--debug': True, + '--dry-run': False, + '--help': False, + '--major': False, + '--minor': False, + '--new-version': '0.0.1', + 'new_version': '0.0.1', + '--noinput': True, + '--patch': True, + '--pypi': None, + '--skip-changelog': False, + '--test-command': None, + '--tox': False, + '--version-prefix': None, + '': 'changes', + 'bump_version': False, + 'changelog': True, + 'install': False, + 'pypi': False, + 'release': False, + 'tag': False, + 'test': False, + 'upload': False + } + + def setUp(self): + config.arguments = self.arguments + + def test_common_arguments(self): + expected_arguments = ( + 'changes', + False, + '0.0.1', + ) + self.assertEquals( + expected_arguments, + config.common_arguments() + ) diff --git a/tests/test_packaging.py b/tests/test_packaging.py new file mode 100644 index 0000000..91d1bca --- /dev/null +++ b/tests/test_packaging.py @@ -0,0 +1,20 @@ +from changes import config, packaging +from . import BaseTestCase + + +class PackagingTestCase(BaseTestCase): + + def test_install(self): + config.arguments['--dry-run'] = True + packaging.install() + + def test_make_virtualenv(self): + packaging.make_virtualenv() + + def test_upload(self): + config.arguments['--dry-run'] = True + packaging.upload() + + def test_pypi(self): + config.arguments['--dry-run'] = True + packaging.pypi() diff --git a/tests/test_shell.py b/tests/test_shell.py new file mode 100644 index 0000000..a952cbb --- /dev/null +++ b/tests/test_shell.py @@ -0,0 +1,26 @@ +import sh +from unittest2 import TestCase + +from changes import config, shell + + +class ShellTestCase(TestCase): + + def test_handle_dry_run(self): + config.arguments['--dry-run'] = False + self.assertEquals( + '', + shell.handle_dry_run( + sh.diff, + ('README.md', 'README.md') + ) + ) + + def test_handle_dry_run_true(self): + config.arguments['--dry-run'] = True + self.assertTrue( + shell.handle_dry_run( + sh.diff, + ('README.md', 'README.md') + ) + ) diff --git a/tests/test_util.py b/tests/test_util.py index 30768c8..463b7c4 100644 --- a/tests/test_util.py +++ b/tests/test_util.py @@ -12,3 +12,20 @@ def test_extract(self): ['a', 'b'] ) ) + + def test_extract_arguments(self): + self.assertEquals( + { + 'major': True, + 'minor': False, + 'patch': False, + }, + util.extract_arguments( + { + '--major': True, + '--minor': False, + '--patch': False, + }, + ['--major', '--minor', '--patch'] + ), + ) diff --git a/tests/test_vcs.py b/tests/test_vcs.py new file mode 100644 index 0000000..5d86234 --- /dev/null +++ b/tests/test_vcs.py @@ -0,0 +1,14 @@ +from changes import config, vcs +from . import BaseTestCase + + +class VcsTestCase(BaseTestCase): + + def setUp(self): + config.arguments['--dry-run'] = True + + def test_commit_version_change(self): + vcs.commit_version_change() + + def test_tag(self): + vcs.tag() diff --git a/tests/test_version.py b/tests/test_version.py index ff27c9c..f00c480 100644 --- a/tests/test_version.py +++ b/tests/test_version.py @@ -23,20 +23,6 @@ def test_increment(self): version.increment('1.0.0', patch=True) ) - def test_extract_version_arguments(self): - self.assertEquals( - { - 'major': True, - 'minor': False, - 'patch': False, - }, - version.extract_version_arguments({ - '--major': True, - '--minor': False, - '--patch': False, - }) - ) - class VersionApplicationTestCase(BaseTestCase): @@ -54,6 +40,7 @@ def test_get_new_version(self): version.get_new_version( self.module_name, '0.0.1', - minor=True + True, + minor=True, ) )