Skip to content

Commit

Permalink
Merge pull request #48 from michaeljoseph/support-package-module-mism…
Browse files Browse the repository at this point in the history
…atch

Doesn't work well when package name doesn't match module name
  • Loading branch information
michaeljoseph committed Nov 15, 2013
2 parents e42c815 + beffa15 commit a74d1a6
Show file tree
Hide file tree
Showing 14 changed files with 111 additions and 86 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,5 @@ nosetests.xml

/docs/_build
.idea
*.iml
*.iml
.noseids
25 changes: 14 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ An application wanting to use `changes` must meet these requirements:
* `CHANGELOG.md`
* `<app_name>/__init__.py` with `__version__` and `__url__`
* supports executing tests with [`nosetests`][2] or [`tox`][3]
* we expect `<app_name>` to be the package and module name

Install `changes`:

Expand All @@ -42,14 +43,14 @@ Run the cli:
changes.
Usage:
changes [options] <app_name> changelog
changes [options] <app_name> release
changes [options] <app_name> bump_version
changes [options] <app_name> run_tests
changes [options] <app_name> install
changes [options] <app_name> upload
changes [options] <app_name> pypi
changes [options] <app_name> tag
changes [options] <module_name> changelog
changes [options] <module_name> release
changes [options] <module_name> bump_version
changes [options] <module_name> run_tests
changes [options] <module_name> install
changes [options] <module_name> upload
changes [options] <module_name> pypi
changes [options] <module_name> tag
changes -h | --help
Expand All @@ -71,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=<module> If your module and package aren't the same
--requirements=<reqfile> Requirements file name (defaults to requirements.txt)
--debug Debug output.
The commands do the following:
Expand All @@ -94,15 +97,15 @@ 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
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.
Expand All @@ -121,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

Expand Down
12 changes: 6 additions & 6 deletions changes/attributes.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -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()]
Expand Down
14 changes: 7 additions & 7 deletions changes/changelog.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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)
Expand All @@ -94,7 +94,7 @@ def changelog():
]

write_new_changelog(
app_name,
module_name,
config.CHANGELOG,
changelog_content,
dry_run=dry_run
Expand Down
27 changes: 14 additions & 13 deletions changes/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@
changes.
Usage:
changes [options] <app_name> changelog
changes [options] <app_name> release
changes [options] <app_name> bump_version
changes [options] <app_name> run_tests
changes [options] <app_name> install
changes [options] <app_name> upload
changes [options] <app_name> pypi
changes [options] <app_name> tag
changes [options] <module_name> changelog
changes [options] <module_name> release
changes [options] <module_name> bump_version
changes [options] <module_name> run_tests
changes [options] <module_name> install
changes [options] <module_name> upload
changes [options] <module_name> pypi
changes [options] <module_name> tag
changes -h | --help
Expand All @@ -31,6 +31,8 @@
--noinput To be used in conjuction with one of the version
increment options above, this option stops
`changes` from confirming the new version number.
--package-name=<package> If your module and package aren't the same
--requirements=<req> Requirements file name (default: requirements.txt)
--debug Debug output.
The commands do the following:
Expand All @@ -50,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
Expand Down Expand Up @@ -95,17 +96,17 @@ def main():
if arguments['--new-version']:
arguments['new_version'] = arguments['--new-version']

app_name = config.arguments['<app_name>']
module_name = config.arguments['<module_name>']

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)
)
Expand Down
6 changes: 3 additions & 3 deletions changes/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,16 @@ def common_arguments():
"""
Return common arguments
:return: tuple of <app_name>, --dry-run, new_version
:return: tuple of <module_name>, --dry-run, new_version
"""

app_name = arguments['<app_name>']
module_name = arguments['<module_name>']

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,
)
Expand Down
32 changes: 18 additions & 14 deletions changes/packaging.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,29 +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['<app_name>'],
'dist/%s-%s.tar.gz' % (app_name, new_version),
config.arguments['<module_name>'],
'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(' ')
Expand All @@ -50,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']
Expand All @@ -69,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))
36 changes: 20 additions & 16 deletions changes/probe.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,20 @@

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(
[dependency in requirement for requirement in requirements_contents]
)


def probe_project(app_name):
def probe_project(module_name):
"""
Check if the project meets `changes` requirements
"""
Expand All @@ -29,29 +31,31 @@ def probe_project(app_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')
log.info('CHANGELOG.md? %s', has_changelog)

# `<app_name>/__init__.py` with `__version__` and `__url__`
init_path = '%s/__init__.py' % app_name
# `<module_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)

# 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)
4 changes: 2 additions & 2 deletions changes/vcs.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
Loading

0 comments on commit a74d1a6

Please sign in to comment.