diff --git a/README.md b/README.md index ede93cb3..276bab64 100644 --- a/README.md +++ b/README.md @@ -372,6 +372,14 @@ replace = MyProject=={new_version} Can be multiple lines, templated using [Python Format String Syntax](https://docs.python.org/3/library/string.html#format-string-syntax). +#### `encoding =` + **default:** `UTF-8` + + Encoding to be used with the file. Might need to be set for files that + contain special characters and use a different encoding than UTF-8. + + You can consult [the Python Documentation](https://docs.python.org/3/library/codecs.html#standard-encodings) for a list of possible encodings. + ## Command-line Options Most of the configuration values above can also be given as an option on the command-line. diff --git a/bumpversion/utils.py b/bumpversion/utils.py index f872f230..9aa59eb1 100644 --- a/bumpversion/utils.py +++ b/bumpversion/utils.py @@ -75,7 +75,7 @@ def contains(self, search): if not search: return False - with open(self.path, "rt", encoding="utf-8") as f: + with open(self.path, "rt", encoding=self._versionconfig.encoding) as f: search_lines = search.splitlines() lookbehind = [] @@ -102,7 +102,7 @@ def contains(self, search): def replace(self, current_version, new_version, context, dry_run): - with open(self.path, "rt", encoding="utf-8") as f: + with open(self.path, "rt", encoding=self._versionconfig.encoding) as f: file_content_before = f.read() file_new_lines = f.newlines @@ -141,7 +141,7 @@ def replace(self, current_version, new_version, context, dry_run): logger.info("%s file %s", "Would not change" if dry_run else "Not changing", self.path) if not dry_run: - with open(self.path, "wt", encoding="utf-8", newline=file_new_lines) as f: + with open(self.path, "wt", encoding=self._versionconfig.encoding, newline=file_new_lines) as f: f.write(file_content_after) def __str__(self): diff --git a/bumpversion/version_part.py b/bumpversion/version_part.py index ae34895c..0f5ad32a 100644 --- a/bumpversion/version_part.py +++ b/bumpversion/version_part.py @@ -137,7 +137,7 @@ class VersionConfig: Holds a complete representation of a version string """ - def __init__(self, parse, serialize, search, replace, part_configs=None): + def __init__(self, parse, serialize, search, replace, part_configs=None, encoding="utf-8"): try: self.parse_regex = re.compile(parse, re.VERBOSE) @@ -154,6 +154,7 @@ def __init__(self, parse, serialize, search, replace, part_configs=None): self.part_configs = part_configs self.search = search self.replace = replace + self.encoding = encoding def order(self): diff --git a/tests/test_cli.py b/tests/test_cli.py index 748d4860..99ff4c74 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -1,3 +1,4 @@ +# -*- coding: utf-8 -*- import argparse import logging import os @@ -2234,6 +2235,33 @@ def test_retain_newline(tmpdir, configfile, newline): # and that it is of the right type assert new_config.endswith(b"[bumpversion:file:file.py]" + newline) +@pytest.mark.parametrize("encoding", [None, "utf-8", "latin1"]) +def test_file_encoding(tmpdir, configfile, encoding): + tmpdir.join("file.py").write_binary(dedent(""" + 0.7.2 + Some encoded Content: äöüß + """).strip().encode(encoding=encoding or "utf-8")) + tmpdir.chdir() + + if encoding is None: + configstring = "" + else: + configstring = "encoding = %s" % encoding + + tmpdir.join(configfile).write_binary(dedent((""" + [bumpversion] + current_version = 0.7.2 + search = {current_version} + replace = {new_version} + [bumpversion:file:file.py] + %s + """) % configstring).strip().encode(encoding='UTF-8')) + + # Ensure the program works (without any exceptions or errors) + # regardless of encoding if the encoding is configured + # correctly + main(["major"]) + def test_no_configured_files(tmpdir, vcs): tmpdir.join("please_ignore_me.txt").write("0.5.5") @@ -2260,7 +2288,6 @@ def test_no_configured_files_still_file_args_work(tmpdir, vcs): assert "0.5.5" == tmpdir.join("please_ignore_me.txt").read() assert "1.1.2" == tmpdir.join("please_update_me.txt").read() - class TestSplitArgsInOptionalAndPositional: def test_all_optional(self):