diff --git a/ckan/lib/config_tool.py b/ckan/lib/config_tool.py index 5895d531db8..6cf375ad0d6 100644 --- a/ckan/lib/config_tool.py +++ b/ckan/lib/config_tool.py @@ -1,6 +1,7 @@ # encoding: utf-8 from __future__ import print_function +import six import re INSERT_NEW_SECTIONS_BEFORE_SECTION = 'app:main' @@ -23,7 +24,7 @@ def config_edit_using_merge_file(config_filepath, merge_config_filepath): ''' # Read and parse the merge config filepath with open(merge_config_filepath, 'rb') as f: - input_lines = [line.rstrip('\n') for line in f] + input_lines = [six.ensure_str(line).rstrip('\n') for line in f] desired_options_dict = parse_config(input_lines) desired_options = desired_options_dict.values() # Make the changes @@ -34,7 +35,7 @@ def config_edit(config_filepath, desired_options, edit=False): '''Writes the desired_options to the config file.''' # Read and parse the existing config file with open(config_filepath, 'rb') as f: - input_lines = [line.rstrip('\n') for line in f] + input_lines = [six.ensure_str(line).rstrip('\n') for line in f] existing_options_dict = parse_config(input_lines) existing_options = existing_options_dict.values() @@ -45,7 +46,7 @@ def config_edit(config_filepath, desired_options, edit=False): # write the file with the changes output = make_changes(input_lines, new_sections, changes) with open(config_filepath, 'wb') as f: - f.write('\n'.join(output) + '\n') + f.write(six.ensure_binary('\n'.join(output) + '\n')) def parse_option_string(section, option_string, raise_on_error=False): diff --git a/ckan/tests/cli/test_config_tool.py b/ckan/tests/cli/test_config_tool.py index d7d22bd8a63..876d11c8317 100644 --- a/ckan/tests/cli/test_config_tool.py +++ b/ckan/tests/cli/test_config_tool.py @@ -34,7 +34,9 @@ def test_config_unset_debug(cli, config_file): assert _parse(config_file).get(u'app:main', u'debug') == u'true' result = cli.invoke( ckan, - [u'config-tool', str(config_file), u'debug=false']) + [u'config-tool', str(config_file), u'debug=false'] + + ) assert not result.exit_code assert _parse(config_file).get(u'app:main', u'debug') == u'false' diff --git a/ckan/tests/helpers.py b/ckan/tests/helpers.py index 077ce2faf0a..889a17194ee 100644 --- a/ckan/tests/helpers.py +++ b/ckan/tests/helpers.py @@ -30,6 +30,7 @@ from flask.testing import Client as FlaskClient from flask.wrappers import Response +from click.testing import CliRunner import pytest import mock import rq @@ -172,6 +173,14 @@ def body_contains(res, content): return content in body +class CKANCliRunner(CliRunner): + def invoke(self, *args, **kwargs): + # prevent cli runner from str/bytes exceptions + kwargs.setdefault(u'complete_var', u'_CKAN_COMPLETE') + return super(CKANCliRunner, self).invoke(*args, **kwargs) + + + class CKANResponse(Response): @property def body(self): diff --git a/ckan/tests/pytest_ckan/fixtures.py b/ckan/tests/pytest_ckan/fixtures.py index ae23720107b..1e2626848da 100644 --- a/ckan/tests/pytest_ckan/fixtures.py +++ b/ckan/tests/pytest_ckan/fixtures.py @@ -28,16 +28,19 @@ """ -import pytest +import functools +import smtplib + -from click.testing import CliRunner +import pytest import six import mock -import smtplib +import rq + import ckan.tests.helpers as test_helpers import ckan.plugins import ckan.lib.search as search -import rq + from ckan.common import config @@ -110,8 +113,8 @@ def test_dataset_search(self, app): def cli(ckan_config): """Provides object for invoking CLI commands from tests. - This is pure `click.testing.CliRunner`, so all examples from - `Click docs + This is subclass of `click.testing.CliRunner`, so all examples + from `Click docs `_ are valid for it. @@ -119,7 +122,7 @@ def cli(ckan_config): env = { u'CKAN_INI': ckan_config[u'__file__'] } - return CliRunner(env=env) + return test_helpers.CKANCliRunner(env=env) @pytest.fixture(scope=u"session")