Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Windows behavior fixed, with appveyor tests passing #33

Closed
wants to merge 21 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Expand Up @@ -105,6 +105,8 @@ venv.bak/
.spyderproject
.spyproject

.idea

# Rope project settings
.ropeproject

Expand All @@ -129,3 +131,4 @@ Session.vim

# Auto-generated tag files
tags
.pytest_cache
45 changes: 27 additions & 18 deletions bumpversion/__init__.py
Expand Up @@ -12,24 +12,32 @@
except:
from io import StringIO


import argparse
import codecs
import io
import os
import platform
import re
import sre_constants
import subprocess
import sys
import warnings
import io
from string import Formatter
from datetime import datetime
from difflib import unified_diff
from tempfile import NamedTemporaryFile

import sys
import codecs

from bumpversion.version_part import VersionPart, NumericVersionPartConfiguration, ConfiguredVersionPartConfiguration


if platform.system() == 'Windows' and sys.version_info[0] == 2:
def _command_args(args):
return [a.encode("utf-8") for a in args]
else:
def _command_args(args):
return args


if sys.version_info[0] == 2:
sys.stdout = codecs.getwriter('utf-8')(sys.stdout)

Expand Down Expand Up @@ -64,6 +72,7 @@ def __call__(self, parser, namespace, values, option_string=None):
'utcnow': datetime.utcnow(),
}


class BaseVCS(object):

@classmethod
Expand All @@ -72,7 +81,7 @@ def commit(cls, message):
f.write(message.encode('utf-8'))
f.close()
env = os.environ.copy()
env['HGENCODING'] = 'utf-8'
env[str('HGENCODING')] = str('utf-8')
try:
subprocess.check_output(cls._COMMIT_COMMAND + [f.name], env=env)
except subprocess.CalledProcessError as exc:
Expand Down Expand Up @@ -153,7 +162,7 @@ def latest_tag_info(cls):

@classmethod
def add_path(cls, path):
subprocess.check_output(["git", "add", "--update", path])
subprocess.check_output(_command_args(["git", "add", "--update", path]))

@classmethod
def tag(cls, sign, name, message):
Expand All @@ -162,7 +171,7 @@ def tag(cls, sign, name, message):
command += ['-s']
if message:
command += ['--message', message]
subprocess.check_output(command)
subprocess.check_output(_command_args(command))


class Mercurial(BaseVCS):
Expand Down Expand Up @@ -201,7 +210,7 @@ def tag(cls, sign, name, message):
)
if message:
command += ['--message', message]
subprocess.check_output(command)
subprocess.check_output(_command_args(command))

VCS = [Git, Mercurial]

Expand Down Expand Up @@ -233,12 +242,12 @@ def should_contain_version(self, version, context):
assert False, msg

def contains(self, search):
with io.open(self.path, 'rb') as f:
with io.open(self.path, 'rt', encoding='utf-8') as f:
search_lines = search.splitlines()
lookbehind = []

for lineno, line in enumerate(f.readlines()):
lookbehind.append(line.decode('utf-8').rstrip("\n"))
lookbehind.append(line.rstrip("\n"))

if len(lookbehind) > len(search_lines):
lookbehind = lookbehind[1:]
Expand All @@ -247,14 +256,14 @@ def contains(self, search):
search_lines[-1] in lookbehind[-1] and
search_lines[1:-1] == lookbehind[1:-1]):
logger.info("Found '{}' in {} at line {}: {}".format(
search, self.path, lineno - (len(lookbehind) - 1), line.decode('utf-8').rstrip()))
search, self.path, lineno - (len(lookbehind) - 1), line.rstrip()))
return True
return False

def replace(self, current_version, new_version, context, dry_run):

with io.open(self.path, 'rb') as f:
file_content_before = f.read().decode('utf-8')
with io.open(self.path, 'rt', encoding='utf-8') as f:
file_content_before = f.read()

context['current_version'] = self._versionconfig.serialize(current_version, context)
context['new_version'] = self._versionconfig.serialize(new_version, context)
Expand Down Expand Up @@ -292,8 +301,8 @@ def replace(self, current_version, new_version, context, dry_run):
))

if not dry_run:
with io.open(self.path, 'wb') as f:
f.write(file_content_after.encode('utf-8'))
with io.open(self.path, 'wt', encoding='utf-8') as f:
f.write(file_content_after)

def __str__(self):
return self.path
Expand Down Expand Up @@ -892,8 +901,8 @@ def main(original_args=None):
logger.info(new_config.getvalue())

if write_to_config_file:
with io.open(config_file, 'wb') as f:
f.write(new_config.getvalue().encode('utf-8'))
with io.open(config_file, 'wt', encoding='utf-8') as f:
f.write(new_config.getvalue())

except UnicodeEncodeError:
warnings.warn(
Expand Down
35 changes: 23 additions & 12 deletions tests/test_cli.py
Expand Up @@ -2,32 +2,35 @@

from __future__ import unicode_literals, print_function

import argparse
import bumpversion
import mock
import os
import platform
import pytest
import sys
import logging
import mock

import argparse
import six
import subprocess
from os import curdir, makedirs, chdir, environ
from os.path import join, curdir, dirname
from os import environ
from shlex import split as shlex_split
from textwrap import dedent
from functools import partial

import bumpversion

from bumpversion import main, DESCRIPTION, WorkingDirectoryIsDirtyException, \
split_args_in_optional_and_positional


def _get_subprocess_env():
env = os.environ.copy()
env['HGENCODING'] = 'utf-8'
# In python2 cast to str from unicode (note the future import).
# In python3 does nothing.
env[str('HGENCODING')] = str('utf-8')
return env

SUBPROCESS_ENV = _get_subprocess_env()

call = partial(subprocess.call, env=SUBPROCESS_ENV)
call = partial(subprocess.call, env=SUBPROCESS_ENV, shell=True)
check_call = partial(subprocess.check_call, env=SUBPROCESS_ENV)
check_output = partial(subprocess.check_output, env=SUBPROCESS_ENV)

Expand Down Expand Up @@ -150,18 +153,26 @@ def test_usage_string(tmpdir, capsys):

assert EXPECTED_USAGE in out


def test_usage_string_fork(tmpdir, capsys):
tmpdir.chdir()

if platform.system() == "Windows" and six.PY3:
# There are encoding problems on Windows with the encoding of →
tmpdir.join(".bumpversion.cfg").write("""[bumpversion]
message: Bump version: {current_version} to {new_version}
tag_message: 'Bump version: {current_version} to {new_version}""")

try:
out = check_output('bumpversion --help', shell=True, stderr=subprocess.STDOUT).decode('utf-8')
out = check_output('bumpversion --help', shell=True, stderr=subprocess.STDOUT)
except subprocess.CalledProcessError as e:
out = e.output

if not 'usage: bumpversion [-h]' in out:
if not b'usage: bumpversion [-h]' in out:
print(out)

assert 'usage: bumpversion [-h]' in out
assert b'usage: bumpversion [-h]' in out


@pytest.mark.parametrize(("vcs"), [xfail_if_no_git("git"), xfail_if_no_hg("hg")])
def test_regression_help_in_workdir(tmpdir, capsys, vcs):
Expand Down