From 3970e4bfd12b8ed3b617b340f0bdfc87579f5455 Mon Sep 17 00:00:00 2001 From: Michael Joseph Date: Fri, 15 Nov 2013 18:01:22 +0200 Subject: [PATCH 1/9] Document package=module expectation --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 55aa1fc..c6d7d1b 100644 --- a/README.md +++ b/README.md @@ -31,6 +31,7 @@ An application wanting to use `changes` must meet these requirements: * `CHANGELOG.md` * `/__init__.py` with `__version__` and `__url__` * supports executing tests with [`nosetests`][2] or [`tox`][3] +* we expect `` to be the package and module name Install `changes`: From 7c59ed0de8704e3b39eb72967fec2aafca1b8003 Mon Sep 17 00:00:00 2001 From: Michael Joseph Date: Fri, 15 Nov 2013 18:03:04 +0200 Subject: [PATCH 2/9] Use the module name for tarball installation, if specified, with a test. Fixes #48 --- changes/cli.py | 1 + changes/packaging.py | 3 ++- tests/test_packaging.py | 5 +++++ 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/changes/cli.py b/changes/cli.py index 74c8423..0091f92 100644 --- a/changes/cli.py +++ b/changes/cli.py @@ -31,6 +31,7 @@ --noinput To be used in conjuction with one of the version increment options above, this option stops `changes` from confirming the new version number. + --module-name= If your module and package aren't the same --debug Debug output. The commands do the following: diff --git a/changes/packaging.py b/changes/packaging.py index 74e4ef8..b66b995 100644 --- a/changes/packaging.py +++ b/changes/packaging.py @@ -22,10 +22,11 @@ def install(): result = shell.handle_dry_run(sh.python, ('setup.py', 'clean', 'sdist')) if result: tmp_dir = make_virtualenv() + module_name = config.arguments.get('--module-name') or app_name try: virtualenv.install_sdist( config.arguments[''], - 'dist/%s-%s.tar.gz' % (app_name, new_version), + 'dist/%s-%s.tar.gz' % (module_name, new_version), '%s/bin/python' % tmp_dir ) log.info('Successfully installed %s sdist', app_name) diff --git a/tests/test_packaging.py b/tests/test_packaging.py index 91d1bca..13aeb92 100644 --- a/tests/test_packaging.py +++ b/tests/test_packaging.py @@ -8,6 +8,11 @@ def test_install(self): config.arguments['--dry-run'] = True packaging.install() + def test_install_with_module_name(self): + config.arguments['--dry-run'] = True + config.arguments['--module-name'] = 'thing' + packaging.install() + def test_make_virtualenv(self): packaging.make_virtualenv() From b5e02d6a3cbfc61ccb6fca677055551ad1a11e36 Mon Sep 17 00:00:00 2001 From: Michael Joseph Date: Fri, 15 Nov 2013 19:50:55 +0200 Subject: [PATCH 3/9] s/module/package/ --- changes/packaging.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/changes/packaging.py b/changes/packaging.py index b66b995..f3f4b52 100644 --- a/changes/packaging.py +++ b/changes/packaging.py @@ -22,7 +22,7 @@ def install(): result = shell.handle_dry_run(sh.python, ('setup.py', 'clean', 'sdist')) if result: tmp_dir = make_virtualenv() - module_name = config.arguments.get('--module-name') or app_name + package_name = config.arguments.get('--package-name') or module_name try: virtualenv.install_sdist( config.arguments[''], From ef055e09741894d39ebcec82eff6b3b264427751 Mon Sep 17 00:00:00 2001 From: Michael Joseph Date: Fri, 15 Nov 2013 19:52:36 +0200 Subject: [PATCH 4/9] s/app_name/module_name/g --- changes/attributes.py | 12 ++++++------ changes/changelog.py | 14 +++++++------- changes/cli.py | 24 ++++++++++++------------ changes/config.py | 6 +++--- changes/packaging.py | 31 +++++++++++++++++-------------- changes/probe.py | 10 +++++----- changes/vcs.py | 4 ++-- changes/version.py | 12 ++++++------ tests/__init__.py | 7 +++++++ tests/test_config.py | 2 +- tests/test_packaging.py | 6 +----- 11 files changed, 67 insertions(+), 61 deletions(-) diff --git a/changes/attributes.py b/changes/attributes.py index ee2e352..82d75d7 100644 --- a/changes/attributes.py +++ b/changes/attributes.py @@ -9,16 +9,16 @@ log = logging.getLogger(__name__) -def extract_attribute(app_name, attribute_name): +def extract_attribute(module_name, attribute_name): """Extract metatdata property from a module""" - with open('%s/__init__.py' % app_name) as input_file: + with open('%s/__init__.py' % module_name) as input_file: for line in input_file: if line.startswith(attribute_name): return ast.literal_eval(line.split('=')[1].strip()) -def replace_attribute(app_name, attribute_name, new_value, dry_run=True): - init_file = '%s/__init__.py' % app_name +def replace_attribute(module_name, attribute_name, new_value, dry_run=True): + init_file = '%s/__init__.py' % module_name _, tmp_file = tempfile.mkstemp() with open(init_file) as input_file: @@ -35,8 +35,8 @@ def replace_attribute(app_name, attribute_name, new_value, dry_run=True): log.debug(sh.diff(tmp_file, init_file, _ok_code=1)) -def has_attribute(app_name, attribute_name): - init_file = '%s/__init__.py' % app_name +def has_attribute(module_name, attribute_name): + init_file = '%s/__init__.py' % module_name return any( [attribute_name in init_line for init_line in open(init_file).readlines()] diff --git a/changes/changelog.py b/changes/changelog.py index 9b96567..f61ea95 100644 --- a/changes/changelog.py +++ b/changes/changelog.py @@ -7,10 +7,10 @@ log = logging.getLogger(__name__) -def write_new_changelog(app_name, filename, content_lines, dry_run=True): +def write_new_changelog(module_name, filename, content_lines, dry_run=True): heading_and_newline = ( '# [Changelog](%s/releases)\n' % - attributes.extract_attribute(app_name, '__url__') + attributes.extract_attribute(module_name, '__url__') ) with open(filename, 'r+') as f: @@ -56,19 +56,19 @@ def replace_sha_with_commit_link(git_log_content): def changelog(): - app_name, dry_run, new_version = config.common_arguments() + module_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, + new_version, attributes.extract_attribute(module_name, '__url__'), + version.current_version(module_name), new_version, ) ] git_log_content = sh.git.log( '--oneline', '--no-merges', - '%s..master' % version.current_version(app_name), + '%s..master' % version.current_version(module_name), _tty_out=False ).split('\n') log.debug('content: %s' % git_log_content) @@ -94,7 +94,7 @@ def changelog(): ] write_new_changelog( - app_name, + module_name, config.CHANGELOG, changelog_content, dry_run=dry_run diff --git a/changes/cli.py b/changes/cli.py index 0091f92..a3fe5ba 100644 --- a/changes/cli.py +++ b/changes/cli.py @@ -2,14 +2,14 @@ changes. Usage: - changes [options] changelog - changes [options] release - changes [options] bump_version - changes [options] run_tests - changes [options] install - changes [options] upload - changes [options] pypi - changes [options] tag + changes [options] changelog + changes [options] release + changes [options] bump_version + changes [options] run_tests + changes [options] install + changes [options] upload + changes [options] pypi + changes [options] tag changes -h | --help @@ -96,17 +96,17 @@ def main(): if arguments['--new-version']: arguments['new_version'] = arguments['--new-version'] - app_name = config.arguments[''] + module_name = config.arguments[''] - if not probe.probe_project(app_name): + if not probe.probe_project(module_name): raise Exception('Project does not meet `changes` requirements') for command in commands: if arguments[command]: if command not in suppress_version_prompt_for: arguments['new_version'] = version.get_new_version( - app_name, - version.current_version(app_name), + module_name, + version.current_version(module_name), arguments.get('--noinput', False), **util.extract_arguments(arguments, version_arguments) ) diff --git a/changes/config.py b/changes/config.py index eb2164c..2ddece3 100644 --- a/changes/config.py +++ b/changes/config.py @@ -6,16 +6,16 @@ def common_arguments(): """ Return common arguments - :return: tuple of , --dry-run, new_version + :return: tuple of , --dry-run, new_version """ - app_name = arguments[''] + module_name = arguments[''] version_prefix = arguments.get('--version-prefix') new_version = arguments['new_version'] common_arguments = ( - app_name, + module_name, arguments['--dry-run'], version_prefix + new_version if version_prefix else new_version, ) diff --git a/changes/packaging.py b/changes/packaging.py index f3f4b52..1090ac4 100644 --- a/changes/packaging.py +++ b/changes/packaging.py @@ -17,30 +17,29 @@ def make_virtualenv(): def install(): - app_name, dry_run, new_version = config.common_arguments() - + module_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() package_name = config.arguments.get('--package-name') or module_name try: virtualenv.install_sdist( - config.arguments[''], - 'dist/%s-%s.tar.gz' % (module_name, new_version), + config.arguments[''], + 'dist/%s-%s.tar.gz' % (package_name, new_version), '%s/bin/python' % tmp_dir ) - log.info('Successfully installed %s sdist', app_name) + log.info('Successfully installed %s sdist', module_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) + raise Exception('Error installing %s sdist', module_name) path(tmp_dir).rmtree(path(tmp_dir)) def upload(): - app_name, dry_run, new_version = config.common_arguments() + module_name, dry_run, new_version = config.common_arguments() pypi = config.arguments['--pypi'] upload_args = 'setup.py clean sdist upload'.split(' ') @@ -51,14 +50,14 @@ def upload(): if not upload_result: raise Exception('Error uploading') else: - log.info('Succesfully uploaded %s %s', app_name, new_version) + log.info('Succesfully uploaded %s %s', module_name, new_version) def pypi(): - app_name, dry_run, _ = config.common_arguments() + module_name, dry_run, _ = config.common_arguments() tmp_dir = make_virtualenv() - install_cmd = '%s/bin/pip install %s' % (tmp_dir, app_name) + install_cmd = '%s/bin/pip install %s' % (tmp_dir, module_name) package_index = 'pypi' pypi = config.arguments['--pypi'] @@ -70,14 +69,18 @@ def pypi(): result = shell.execute(install_cmd, dry_run=dry_run) if result: log.info('Successfully installed %s from %s', - app_name, package_index) + module_name, package_index) else: log.error('Failed to install %s from %s', - app_name, package_index) + module_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) + log.exception( + 'error installing %s from %s', module_name, package_index + ) + raise Exception( + 'Error installing %s from %s', module_name, package_index + ) path(tmp_dir).rmtree(path(tmp_dir)) diff --git a/changes/probe.py b/changes/probe.py index 3a40dd4..0783700 100644 --- a/changes/probe.py +++ b/changes/probe.py @@ -14,7 +14,7 @@ def has_requirement(dependency, requirements_contents): ) -def probe_project(app_name): +def probe_project(module_name): """ Check if the project meets `changes` requirements """ @@ -37,12 +37,12 @@ def probe_project(app_name): has_changelog = exists('CHANGELOG.md') log.info('CHANGELOG.md? %s', has_changelog) - # `/__init__.py` with `__version__` and `__url__` - init_path = '%s/__init__.py' % app_name + # `/__init__.py` with `__version__` and `__url__` + init_path = '%s/__init__.py' % module_name has_metadata = ( exists(init_path) and - attributes.has_attribute(app_name, '__version__') and - attributes.has_attribute(app_name, '__url__') + attributes.has_attribute(module_name, '__version__') and + attributes.has_attribute(module_name, '__url__') ) log.info('Has module metadata? %s', has_metadata) diff --git a/changes/vcs.py b/changes/vcs.py index 4465eb6..d1f2f3d 100644 --- a/changes/vcs.py +++ b/changes/vcs.py @@ -8,11 +8,11 @@ def commit_version_change(): - app_name, dry_run, new_version = config.common_arguments() + module_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) + ('-m', new_version, '%s/__init__.py' % module_name, config.CHANGELOG) ) if commit_result: diff --git a/changes/version.py b/changes/version.py index 8674620..5537559 100644 --- a/changes/version.py +++ b/changes/version.py @@ -8,20 +8,20 @@ def bump_version(): - app_name, dry_run, new_version = config.common_arguments() + module_name, dry_run, new_version = config.common_arguments() attributes.replace_attribute( - app_name, + module_name, '__version__', new_version, dry_run=dry_run) -def current_version(app_name): - return attributes.extract_attribute(app_name, '__version__') +def current_version(module_name): + return attributes.extract_attribute(module_name, '__version__') -def get_new_version(app_name, current_version, no_input, +def get_new_version(module_name, current_version, no_input, major=False, minor=False, patch=False): proposed_new_version = increment( @@ -37,7 +37,7 @@ def get_new_version(app_name, current_version, no_input, new_version = raw_input( 'What is the release version for "%s" ' '[Default: %s]: ' % ( - app_name, proposed_new_version + module_name, proposed_new_version ) ) diff --git a/tests/__init__.py b/tests/__init__.py index 9a9c083..70b60c3 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -3,6 +3,8 @@ from unittest2 import TestCase +from changes import config + class BaseTestCase(TestCase): module_name = 'test_app' @@ -23,6 +25,11 @@ def setUp(self): with open(self.tmp_file, 'w') as init_file: init_file.write('\n'.join(self.initial_init_content)) + config.arguments.update({ + '': 'test_app', + '--dry-run': True, + }) + def tearDown(self): if os.path.exists(self.tmp_file): shutil.rmtree(self.module_name) diff --git a/tests/test_config.py b/tests/test_config.py index 2c177fa..88b2f9c 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -18,7 +18,7 @@ class ConfigTestCase(BaseTestCase): '--test-command': None, '--tox': False, '--version-prefix': None, - '': 'changes', + '': 'changes', 'bump_version': False, 'changelog': True, 'install': False, diff --git a/tests/test_packaging.py b/tests/test_packaging.py index 13aeb92..49fba8d 100644 --- a/tests/test_packaging.py +++ b/tests/test_packaging.py @@ -5,21 +5,17 @@ class PackagingTestCase(BaseTestCase): def test_install(self): - config.arguments['--dry-run'] = True packaging.install() def test_install_with_module_name(self): - config.arguments['--dry-run'] = True - config.arguments['--module-name'] = 'thing' + config.arguments['--package-name'] = 'thing' 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() From 73323c26bca6c13cbca5fc54386822b21058788d Mon Sep 17 00:00:00 2001 From: Michael Joseph Date: Fri, 15 Nov 2013 20:23:34 +0200 Subject: [PATCH 5/9] Ignore .noseids --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 7522dba..cbae8d3 100644 --- a/.gitignore +++ b/.gitignore @@ -36,4 +36,5 @@ nosetests.xml /docs/_build .idea -*.iml \ No newline at end of file +*.iml +.noseids \ No newline at end of file From 8b0e4a9bab10c4f461058b3ce16f3020f010455c Mon Sep 17 00:00:00 2001 From: Michael Joseph Date: Fri, 15 Nov 2013 20:25:52 +0200 Subject: [PATCH 6/9] Add alternate requirements option --- changes/cli.py | 2 +- changes/probe.py | 26 +++++++++++++++----------- tests/test_probe.py | 6 +++++- 3 files changed, 21 insertions(+), 13 deletions(-) diff --git a/changes/cli.py b/changes/cli.py index 09c0fd1..7c87f47 100644 --- a/changes/cli.py +++ b/changes/cli.py @@ -32,6 +32,7 @@ increment options above, this option stops `changes` from confirming the new version number. --module-name= If your module and package aren't the same + --requirements= Requirements file name (default: requirements.txt) --debug Debug output. The commands do the following: @@ -51,7 +52,6 @@ import changes 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 diff --git a/changes/probe.py b/changes/probe.py index 0783700..6faa7f3 100644 --- a/changes/probe.py +++ b/changes/probe.py @@ -3,10 +3,12 @@ import sh -from changes import attributes +from changes import attributes, config log = logging.getLogger(__name__) +REQUIREMENTS = 'requirements.txt' + def has_requirement(dependency, requirements_contents): return any( @@ -29,9 +31,18 @@ def probe_project(module_name): log.info('setup.py? %s', setup) # `requirements.txt` - has_requirements = exists('requirements.txt') - log.info('requirements.txt? %s', setup) - requirements_contents = open('requirements.txt').readlines() + requirements = config.arguments.get('--requirements') or REQUIREMENTS + has_requirements = exists(requirements) + log.info('%s? %s', requirements, has_requirements) + if has_requirements: + requirements_contents = open(requirements).readlines() + + # supports executing tests with `nosetests` or `tox` + runs_tests = ( + has_requirement('nose', requirements_contents) or + has_requirement('tox', requirements_contents) + ) + log.info('Runs tests? %s' % runs_tests) # `CHANGELOG.md` has_changelog = exists('CHANGELOG.md') @@ -46,12 +57,5 @@ def probe_project(module_name): ) log.info('Has module metadata? %s', has_metadata) - # supports executing tests with `nosetests` or `tox` - runs_tests = ( - has_requirement('nose', requirements_contents) or - has_requirement('tox', requirements_contents) - ) - log.info('Runs tests? %s' % runs_tests) - return (on_github and setup and has_changelog and has_metadata and has_requirements and runs_tests) diff --git a/tests/test_probe.py b/tests/test_probe.py index 78cc8f2..0881138 100644 --- a/tests/test_probe.py +++ b/tests/test_probe.py @@ -1,4 +1,4 @@ -from changes import probe +from changes import config, probe from . import BaseTestCase @@ -6,3 +6,7 @@ class ProbeTestCase(BaseTestCase): def test_probe_project(self): self.assertTrue(probe.probe_project(self.module_name)) + + def test_probe_with_alt_requirements(self): + config.arguments['--requirements'] = 'test-requirements.txt' + self.assertFalse(probe.probe_project(self.module_name)) From c4333dcde1c9dc69e00dbe677ebaac4128175e51 Mon Sep 17 00:00:00 2001 From: Michael Joseph Date: Fri, 15 Nov 2013 20:26:11 +0200 Subject: [PATCH 7/9] Update readme --- README.md | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index c6d7d1b..198d5c7 100644 --- a/README.md +++ b/README.md @@ -43,14 +43,14 @@ Run the cli: changes. Usage: - changes [options] changelog - changes [options] release - changes [options] bump_version - changes [options] run_tests - changes [options] install - changes [options] upload - changes [options] pypi - changes [options] tag + changes [options] changelog + changes [options] release + changes [options] bump_version + changes [options] run_tests + changes [options] install + changes [options] upload + changes [options] pypi + changes [options] tag changes -h | --help @@ -72,6 +72,8 @@ Options: --noinput To be used in conjuction with one of the version increment options above, this option stops `changes` from confirming the new version number. + --module-name= If your module and package aren't the same + --requirements= Requirements file name (defaults to requirements.txt) --debug Debug output. The commands do the following: @@ -95,7 +97,7 @@ The remaining tasks can be automated with the `release` command (the `--skip-changelog` option prevents `release` from regenerating the automatic changelog) ```python -(changes)$ changes changes -p changes changelog +(changes)$ changes changes -p changes changelog What is the release version for "changes" [Default: 0.1.1]: INFO:changes.cli:Added content to CHANGELOG.md Everything up-to-date @@ -103,7 +105,7 @@ INFO:changes.cli:Committed changelog update << changelog pruning >> -(changes)$ changes -p changes release --skip-changelog +(changes)$ changes -p changes release --skip-changelog What is the release version for "changes" [Default: 0.1.1]: Counting objects: 7, done. Delta compression using up to 8 threads. @@ -122,7 +124,7 @@ warning: sdist: standard file not found: should have one of README, README.rst, Or you can do it all in one step (if your commit messages are good enough): ```python -(changes)$ changes -m changes release +(changes)$ changes -m changes release What is the release version for "changes" [Default: 0.2.0]: INFO:changes.cli:Added content to CHANGELOG.md From 4c68326684e3a86b5602d27aa99954f07f8d9f37 Mon Sep 17 00:00:00 2001 From: Michael Joseph Date: Fri, 15 Nov 2013 21:16:15 +0200 Subject: [PATCH 8/9] Use the default --- changes/version.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/changes/version.py b/changes/version.py index 5537559..8c41696 100644 --- a/changes/version.py +++ b/changes/version.py @@ -32,14 +32,14 @@ def get_new_version(module_name, current_version, no_input, ) if no_input: - new_version = proposed_new_version.strip() + new_version = proposed_new_version else: new_version = raw_input( 'What is the release version for "%s" ' '[Default: %s]: ' % ( module_name, proposed_new_version ) - ) + ) or proposed_new_version return new_version.strip() From beffa15c9da057f8cc4f45afe4116d69ad844222 Mon Sep 17 00:00:00 2001 From: Michael Joseph Date: Fri, 15 Nov 2013 21:26:39 +0200 Subject: [PATCH 9/9] s/module/package --- changes/cli.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/changes/cli.py b/changes/cli.py index 7c87f47..9fb0358 100644 --- a/changes/cli.py +++ b/changes/cli.py @@ -31,7 +31,7 @@ --noinput To be used in conjuction with one of the version increment options above, this option stops `changes` from confirming the new version number. - --module-name= If your module and package aren't the same + --package-name= If your module and package aren't the same --requirements= Requirements file name (default: requirements.txt) --debug Debug output.