Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
6 changes: 3 additions & 3 deletions bumpversion/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -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 = []

Expand All @@ -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

Expand Down Expand Up @@ -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):
Expand Down
3 changes: 2 additions & 1 deletion bumpversion/version_part.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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):
Expand Down
29 changes: 28 additions & 1 deletion tests/test_cli.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# -*- coding: utf-8 -*-
import argparse
import logging
import os
Expand Down Expand Up @@ -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")
Expand All @@ -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):
Expand Down