[Python-modules-commits] [transifex-client] 01/01: New upstream version 0.13.0
Hans-Christoph Steiner
eighthave at moszumanska.debian.org
Tue Jan 9 22:33:54 UTC 2018
This is an automated email from the git hooks/post-receive script.
eighthave pushed a commit to branch upstream
in repository transifex-client.
commit 77efc152aa7627ed25eec2c9f116c846427c892a
Author: Hans-Christoph Steiner <hans at eds.org>
Date: Tue Jan 9 22:41:44 2018 +0100
New upstream version 0.13.0
---
PKG-INFO | 8 +-
requirements.txt | 2 +
setup.cfg | 1 -
setup.py | 3 +-
tests/__init__.pyc | Bin 0 -> 144 bytes
tests/project_dir/.transifexrc | 6 +
tests/project_dir/test.txt | 0
tests/project_dir/translations/en/test.txt | 0
tests/templates/config | 8 +
tests/templates/transifexrc | 4 +
tests/test_api.py | 74 ++++
tests/test_api.pyc | Bin 0 -> 2558 bytes
tests/test_commands.py | 397 +++++++++++++++++++++
tests/test_commands.pyc | Bin 0 -> 18602 bytes
tests/test_parsers.pyc | Bin 0 -> 1665 bytes
tests/test_paths.pyc | Bin 0 -> 2328 bytes
tests/test_processors.pyc | Bin 0 -> 2931 bytes
tests/test_project.py | 245 ++++++++++++-
tests/test_project.pyc | Bin 0 -> 30050 bytes
tests/test_utils.py | 98 +++++-
tests/test_utils.pyc | Bin 0 -> 8539 bytes
tests/test_wizard.py | 146 ++++++++
tests/test_wizard.pyc | Bin 0 -> 4512 bytes
transifex_client.egg-info/PKG-INFO | 8 +-
transifex_client.egg-info/SOURCES.txt | 23 +-
transifex_client.egg-info/pbr.json | 1 +
transifex_client.egg-info/requires.txt | 2 +
txclib/__init__.py | 2 +-
txclib/api.py | 77 +++++
txclib/cmdline.py | 78 ++---
txclib/commands.py | 385 +++++++++++++--------
txclib/config.py | 6 +-
txclib/exceptions.py | 25 ++
txclib/log.py | 2 +-
txclib/messages.py | 115 +++++++
txclib/parsers.py | 533 ++++++++++++++++++++---------
txclib/project.py | 493 +++++++++++++-------------
txclib/urls.py | 16 +
txclib/utils.py | 228 +++++++++++-
txclib/wizard.py | 193 +++++++++++
40 files changed, 2518 insertions(+), 661 deletions(-)
diff --git a/PKG-INFO b/PKG-INFO
index 80853f5..6eed977 100644
--- a/PKG-INFO
+++ b/PKG-INFO
@@ -1,11 +1,12 @@
-Metadata-Version: 1.1
+Metadata-Version: 1.2
Name: transifex-client
-Version: 0.12.4
+Version: 0.13.0
Summary: A command line interface for Transifex
Home-page: https://www.transifex.com
Author: Transifex
Author-email: admin at transifex.com
License: GPLv2
+Description-Content-Type: UNKNOWN
Description: Transifex Command-Line Tool
===========================
[![image](https://circleci.com/gh/transifex/transifex-client/tree/master.svg?style=shield&circle-token=33aafd984726261eff1b73278a0cf761382c478a)](https://circleci.com/gh/transifex/transifex-client/tree/master)
@@ -76,7 +77,6 @@ Keywords: translation,localization,internationalization
Platform: UNKNOWN
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 2
-Classifier: Programming Language :: Python :: 2.6
Classifier: Programming Language :: Python :: 2.7
-Classifier: Programming Language :: Python :: 3.3
Classifier: Programming Language :: Python :: 3.5
+Requires-Python: >=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,<3.6
diff --git a/requirements.txt b/requirements.txt
index 71aa090..82f4e52 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,2 +1,4 @@
urllib3
six
+requests
+python-slugify
diff --git a/setup.cfg b/setup.cfg
index 861a9f5..8bfd5a1 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -1,5 +1,4 @@
[egg_info]
tag_build =
tag_date = 0
-tag_svn_revision = 0
diff --git a/setup.py b/setup.py
index 6a27901..1370690 100755
--- a/setup.py
+++ b/setup.py
@@ -23,6 +23,7 @@ setup(
license="GPLv2",
dependency_links=[],
setup_requires=[],
+ python_requires='>=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,<3.6',
install_requires=get_file_content('requirements.txt').splitlines(),
tests_require=["mock"],
data_files=[],
@@ -35,9 +36,7 @@ setup(
classifiers=[
'Programming Language :: Python',
'Programming Language :: Python :: 2',
- 'Programming Language :: Python :: 2.6',
'Programming Language :: Python :: 2.7',
- 'Programming Language :: Python :: 3.3',
'Programming Language :: Python :: 3.5',
],
)
diff --git a/tests/__init__.pyc b/tests/__init__.pyc
new file mode 100644
index 0000000..6fb37b0
Binary files /dev/null and b/tests/__init__.pyc differ
diff --git a/tests/project_dir/.transifexrc b/tests/project_dir/.transifexrc
new file mode 100644
index 0000000..6bf92eb
--- /dev/null
+++ b/tests/project_dir/.transifexrc
@@ -0,0 +1,6 @@
+[https://www.transifex.com]
+api_hostname = https://api.transifex.com
+hostname = https://www.transifex.com
+password = foo
+username = bar
+
diff --git a/tests/project_dir/test.txt b/tests/project_dir/test.txt
new file mode 100644
index 0000000..e69de29
diff --git a/tests/project_dir/translations/en/test.txt b/tests/project_dir/translations/en/test.txt
new file mode 100644
index 0000000..e69de29
diff --git a/tests/templates/config b/tests/templates/config
new file mode 100755
index 0000000..f8d10b5
--- /dev/null
+++ b/tests/templates/config
@@ -0,0 +1,8 @@
+[main]
+host = https://fake.com
+
+[example.enpo]
+file_filter = translations/example.enpo/<lang>.po
+source_file = example.po
+source_lang = en
+type = PO
diff --git a/tests/templates/transifexrc b/tests/templates/transifexrc
new file mode 100755
index 0000000..d2719c6
--- /dev/null
+++ b/tests/templates/transifexrc
@@ -0,0 +1,4 @@
+[https://fake.com]
+hostname = https://fake.com
+password = dummy_api_token_password_12345
+username = api
diff --git a/tests/test_api.py b/tests/test_api.py
new file mode 100644
index 0000000..554da39
--- /dev/null
+++ b/tests/test_api.py
@@ -0,0 +1,74 @@
+# -*- coding: utf-8 -*-
+
+import unittest
+from mock import MagicMock, patch
+
+from txclib.api import Api
+
+
+class ApiTestCase(unittest.TestCase):
+
+ @patch('txclib.utils.get_api_domains')
+ @patch('requests.get')
+ def test_resolve_api_call(self, requests_mock, domains_mock):
+ token = 'blabla'
+ domains_mock.return_value = {
+ 'hostname': 'https://www.foo.bar',
+ 'api_hostname': 'https://api.foo.bar'
+ }
+ response_mock = MagicMock()
+ response_mock.json.return_value = {"some": "json data"}
+ response_mock.links = {}
+ requests_mock.return_value = response_mock
+ api = Api(token=token)
+ api.get('formats')
+ self.assertEqual(
+ requests_mock.call_args[0][0],
+ 'https://www.foo.bar/api/2/formats/',
+ )
+ requests_mock.reset_mock()
+ requests_mock.return_value = response_mock
+ api.get('organizations')
+ self.assertEqual(
+ requests_mock.call_args[0][0],
+ 'https://api.foo.bar/organizations/',
+ )
+
+ @patch('txclib.utils.get_api_domains')
+ @patch('requests.get')
+ def test_pagination(self, requests_mock, domains_mock):
+ token = 'blabla'
+ domains_mock.return_value = {
+ 'hostname': 'https://www.foo.bar',
+ 'api_hostname': 'https://api.foo.bar'
+ }
+ first_response_mock = MagicMock()
+ first_response_mock.json.return_value = [{"key1": "json data"}]
+ first_response_mock.links = {
+ 'next': {'url': 'https://www.foo.bar/api/2/formats/?page=2'}}
+ second_response_mock = MagicMock()
+ second_response_mock.json.return_value = [{"key2": "json data"}]
+ second_response_mock.links = {}
+ requests_mock.side_effect = [
+ first_response_mock,
+ second_response_mock
+ ]
+ api = Api(token=token)
+ data = api.get('formats')
+ self.assertEqual(
+ requests_mock.call_args_list[0][0][0],
+ 'https://www.foo.bar/api/2/formats/',
+ )
+ self.assertEqual(
+ requests_mock.call_args_list[1][0][0],
+ 'https://www.foo.bar/api/2/formats/?page=2',
+ )
+ self.assertEqual(data, [
+ {"key1": "json data"},
+ {"key2": "json data"}
+ ])
+
+ def test_invalid_call(self):
+ api = Api(token='blabla')
+ with self.assertRaises(Exception):
+ api.get('invalid')
diff --git a/tests/test_api.pyc b/tests/test_api.pyc
new file mode 100644
index 0000000..66f384d
Binary files /dev/null and b/tests/test_api.pyc differ
diff --git a/tests/test_commands.py b/tests/test_commands.py
new file mode 100644
index 0000000..4314bf6
--- /dev/null
+++ b/tests/test_commands.py
@@ -0,0 +1,397 @@
+import os
+import shutil
+import unittest
+import sys
+from StringIO import StringIO
+from mock import patch, MagicMock, call
+from txclib.commands import _set_source_file, _set_translation, cmd_pull, \
+ cmd_init, cmd_config, cmd_status, cmd_help, UnInitializedError
+from txclib.cmdline import main
+from txclib.parsers import MAPPING, MAPPINGREMOTE, MAPPINGBULK
+
+
+class TestCommands(unittest.TestCase):
+ def test_cmd_pull_return_exception_when_dir_not_initialized(self):
+ """Test when tx is not instantiated, that proper error is thrown"""
+ with self.assertRaises(UnInitializedError):
+ cmd_pull([], None)
+
+ def test_set_source_file_when_dir_not_initialized(self):
+ with self.assertRaises(UnInitializedError):
+ _set_source_file(path_to_tx=None, resource='dummy_resource.en',
+ lang='en', path_to_file='dummy')
+
+ def test_set_translation_when_dir_not_initialized(self):
+ with self.assertRaises(UnInitializedError):
+ _set_translation(path_to_tx=None, resource="dummy_resource.md",
+ lang='en', path_to_file='invalid')
+
+
+class TestStatusCommand(unittest.TestCase):
+ @patch('txclib.commands.project')
+ def test_status(self, mock_p):
+ """Test status command"""
+ mock_project = MagicMock()
+ mock_project.get_chosen_resources.return_value = ['foo.bar']
+ mock_project.get_resource_files.return_value = {
+ "fr": "translations/foo.bar/fr.po",
+ "de": "translations/foo.bar/de.po"
+ }
+ mock_p.Project.return_value = mock_project
+ cmd_status([], None)
+ mock_project.get_chosen_resources.assert_called_once_with([])
+ self.assertEqual(mock_project.get_resource_files.call_count, 1)
+
+
+class TestHelpCommand(unittest.TestCase):
+ def test_help(self):
+ out = StringIO()
+ sys.stdout = out
+ cmd_help([], None)
+ output = out.getvalue().strip()
+ self.assertTrue(
+ all(
+ c in output for c in
+ ['delete', 'help', 'init', 'pull', 'push', 'set', 'status']
+ )
+ )
+
+ # call for specific command
+ with patch('txclib.commands.cmd_pull', spec=cmd_pull) as pull_mock:
+ cmd_help(['pull'], None)
+ pull_mock.assert_called_once_with(['--help'], None)
+
+
+class TestInitCommand(unittest.TestCase):
+
+ def setUp(self):
+ self.curr_dir = os.getcwd()
+ self.config_file = '.tx/config'
+ os.chdir('./tests/project_dir/')
+
+ def tearDown(self, *args, **kwargs):
+ shutil.rmtree('.tx', ignore_errors=False, onerror=None)
+ os.chdir(self.curr_dir)
+ super(TestInitCommand, self).tearDown(*args, **kwargs)
+
+ def test_init(self):
+ argv = []
+ config_text = "[main]\nhost = https://www.transifex.com\n\n"
+ with patch('txclib.commands.project.Project') as project_mock:
+ with patch('txclib.commands.cmd_config') as set_mock:
+ cmd_init(argv, '')
+ project_mock.assert_called()
+ set_mock.assert_called_once_with([], os.getcwd())
+ self.assertTrue(os.path.exists('./.tx'))
+ self.assertTrue(os.path.exists('./.tx/config'))
+ self.assertEqual(open(self.config_file).read(), config_text)
+
+ def test_init_skipsetup(self):
+ argv = ['--skipsetup']
+ with patch('txclib.commands.project.Project') as project_mock:
+ with patch('txclib.commands.cmd_config') as set_mock:
+ cmd_init(argv, '')
+ project_mock.assert_called()
+ self.assertEqual(set_mock.call_count, 0)
+ self.assertTrue(os.path.exists('./.tx'))
+ self.assertTrue(os.path.exists('./.tx/config'))
+
+ @patch('txclib.commands.utils.confirm')
+ def test_init_save_N(self, confirm_mock):
+ os.mkdir('./.tx')
+ open('./.tx/config', 'a').close()
+ argv = []
+ confirm_mock.return_value = False
+ with patch('txclib.commands.project.Project') as project_mock:
+ cmd_init(argv, '')
+ self.assertEqual(project_mock.call_count, 0)
+ self.assertTrue(os.path.exists('./.tx'))
+ self.assertEqual(confirm_mock.call_count, 1)
+
+ @patch('txclib.commands.utils.confirm')
+ def test_init_save_y(self, confirm_mock):
+ os.mkdir('./.tx')
+ open('./.tx/config', 'a').close()
+ argv = []
+ confirm_mock.return_value = True
+ with patch('txclib.commands.project.Project') as project_mock:
+ with patch('txclib.commands.cmd_config') as set_mock:
+ cmd_init(argv, '')
+ project_mock.assert_called()
+ set_mock.assert_called()
+ self.assertTrue(os.path.exists('./.tx'))
+ self.assertEqual(confirm_mock.call_count, 1)
+
+ def test_init_force_save(self):
+ os.mkdir('./.tx')
+ argv = ['--force-save']
+ with patch('txclib.commands.project.Project') as project_mock:
+ with patch('txclib.commands.cmd_config') as set_mock:
+ cmd_init(argv, '')
+ project_mock.assert_called()
+ set_mock.assert_called()
+ self.assertTrue(os.path.exists('./.tx'))
+ self.assertTrue(os.path.exists('./.tx/config'))
+
+
+class TestPullCommand(unittest.TestCase):
+ @patch('txclib.utils.get_current_branch')
+ @patch('txclib.commands.logger')
+ @patch('txclib.commands.project.Project')
+ def test_pull_with_branch_no_git_repo(self, project_mock, log_mock, bmock):
+ bmock.return_value = None
+ pr_instance = MagicMock()
+ project_mock.return_value = pr_instance
+ with self.assertRaises(SystemExit):
+ cmd_pull(['--branch'], '.')
+ log_mock.error.assert_called_once_with(
+ "You specified the --branch option but current "
+ "directory does not seem to belong in any git repo.")
+ self.assertEqual(pr_instance.pull.call_count, 0)
+
+ @patch('txclib.utils.get_current_branch')
+ @patch('txclib.commands.logger')
+ @patch('txclib.commands.project.Project')
+ def test_pull_branch_git_repo(self, project_mock, log_mock, bmock):
+ bmock.return_value = 'a-branch'
+ pr_instance = MagicMock()
+ project_mock.return_value = pr_instance
+ cmd_pull(['--branch'], '.')
+ self.assertEqual(pr_instance.pull.call_count, 1)
+ pull_call = call(
+ branch='a-branch', fetchall=False, fetchsource=False,
+ force=False, languages=[], minimum_perc=None, mode=None,
+ overwrite=True, pseudo=False, resources=[], skip=False, xliff=False
+ )
+ pr_instance.pull.assert_has_calls([pull_call])
+
+ @patch('txclib.utils.get_current_branch')
+ @patch('txclib.commands.logger')
+ @patch('txclib.commands.project.Project')
+ def test_pull_with_branch_and_branchname_option(
+ self, project_mock, log_mock, bmock
+ ):
+ pr_instance = MagicMock()
+ project_mock.return_value = pr_instance
+ bmock.return_value = None
+ cmd_pull(['--branch', 'somebranch'], '.')
+ self.assertEqual(pr_instance.pull.call_count, 1)
+ pull_call = call(
+ branch='somebranch', fetchall=False, fetchsource=False,
+ force=False, languages=[], minimum_perc=None, mode=None,
+ overwrite=True, pseudo=False, resources=[], skip=False, xliff=False
+ )
+ pr_instance.pull.assert_has_calls([pull_call])
+
+
+class TestConfigCommand(unittest.TestCase):
+
+ def setUp(self):
+ self.curr_dir = os.getcwd()
+ os.chdir('./tests/project_dir/')
+ os.mkdir('.tx')
+ self.path_to_tx = os.getcwd()
+ self.config_file = '.tx/config'
+ open(self.config_file, "w").write('[main]\nhost = https://foo.var\n')
+
+ def tearDown(self, *args, **kwargs):
+ shutil.rmtree('.tx', ignore_errors=False, onerror=None)
+ os.chdir(self.curr_dir)
+ super(TestConfigCommand, self).tearDown(*args, **kwargs)
+
+ def test_bare_set_too_few_arguments(self):
+ with self.assertRaises(SystemExit):
+ args = ["-r", "project1.resource1"]
+ cmd_config(args, None)
+
+ def test_bare_set_source_no_file(self):
+ with self.assertRaises(SystemExit):
+ args = ["-r", "project1.resource1", '--is-source', '-l', 'en']
+ cmd_config(args, None)
+
+ with self.assertRaises(Exception):
+ args = ['-r', 'project1.resource1', '--source', '-l', 'en',
+ 'noexistent-file.txt']
+ cmd_config(args, self.path_to_tx)
+
+ def test_bare_set_source_file(self):
+ expected = ("[main]\nhost = https://foo.var\n\n[project1.resource1]\n"
+ "source_file = test.txt\nsource_lang = en\n\n")
+ args = ["-r", "project1.resource1", '--source', '-l', 'en', 'test.txt']
+ cmd_config(args, self.path_to_tx)
+ with open(self.config_file) as config:
+ self.assertEqual(config.read(), expected)
+
+ # set translation file for de
+ expected = ("[main]\nhost = https://foo.var\n\n[project1.resource1]\n"
+ "source_file = test.txt\nsource_lang = en\n"
+ "trans.de = translations/de.txt\n\n")
+ args = ["-r", "project1.resource1", '-l', 'de', 'translations/de.txt']
+ cmd_config(args, self.path_to_tx)
+ with open(self.config_file) as config:
+ self.assertEqual(config.read(), expected)
+
+ def test_auto_locale_no_expression(self):
+ with self.assertRaises(SystemExit):
+ args = [MAPPING, "-r", "project1.resource1",
+ '--source-language', 'en']
+ cmd_config(args, self.path_to_tx)
+
+ def test_auto_locale(self):
+ expected = "[main]\nhost = https://foo.var\n"
+ args = [MAPPING, "-r", "project1.resource1", '--source-language',
+ 'en', 'translations/<lang>/test.txt']
+ cmd_config(args, self.path_to_tx)
+ with open(self.config_file) as config:
+ self.assertEqual(config.read(), expected)
+
+ def test_auto_locale_is_backwards_compatible(self):
+ expected = ("[main]\nhost = https://foo.var\n\n[project1.resource1]\n"
+ "file_filter = translations/<lang>/test.txt\n"
+ "source_file = translations/en/test.txt\n"
+ "source_lang = en\n\n")
+
+ args = ["--auto-local", "-r", "project1.resource1",
+ '--source-language', 'en', '--execute',
+ 'translations/<lang>/test.txt']
+ cmd_config(args, self.path_to_tx)
+ with open(self.config_file) as config:
+ self.assertEqual(config.read(), expected)
+
+ def test_auto_locale_execute(self):
+ expected = ("[main]\nhost = https://foo.var\n\n[project1.resource1]\n"
+ "file_filter = translations/<lang>/test.txt\n"
+ "source_file = translations/en/test.txt\n"
+ "source_lang = en\n\n")
+
+ args = [MAPPING, "-r", "project1.resource1", '--source-language',
+ 'en', '--execute', 'translations/<lang>/test.txt']
+ cmd_config(args, self.path_to_tx)
+ with open(self.config_file) as config:
+ self.assertEqual(config.read(), expected)
+
+ def test_auto_remote_invalid_url(self):
+ # no project_url
+ args = [MAPPINGREMOTE]
+ with self.assertRaises(SystemExit):
+ cmd_config(args, self.path_to_tx)
+
+ # invalid project_url
+ args = [MAPPINGREMOTE, "http://some.random.url/"]
+ with self.assertRaises(Exception):
+ cmd_config(args, self.path_to_tx)
+
+ @patch('txclib.utils.get_details')
+ @patch('txclib.project.Project._extension_for')
+ def test_auto_remote_project(self, extension_mock, get_details_mock):
+ # change the host to tx
+ open(self.config_file, "w").write(
+ '[main]\nhost = https://www.transifex.com\n'
+ )
+ expected = ("[main]\nhost = https://www.transifex.com\n\n"
+ "[proj.resource_1]\n"
+ "file_filter = translations/proj.resource_1/<lang>.txt\n"
+ "source_lang = fr\ntype = TXT\n\n[proj.resource_2]\n"
+ "file_filter = translations/proj.resource_2/<lang>.txt\n"
+ "source_lang = fr\ntype = TXT\n\n")
+ extension_mock.return_value = ".txt"
+ get_details_mock.side_effect = [
+ # project details
+ {
+ 'resources': [
+ {'slug': 'resource_1', 'name': 'resource 1'},
+ {'slug': 'resource_2', 'name': 'resource 2'}
+ ]
+ },
+ # resources details
+ {
+ 'source_language_code': 'fr',
+ 'i18n_type': 'TXT',
+ 'slug': 'resource_1',
+ }, {
+ 'source_language_code': 'fr',
+ 'i18n_type': 'TXT',
+ 'slug': 'resource_2',
+ }
+ ]
+ args = [MAPPINGREMOTE, "https://www.transifex.com/test-org/proj/"]
+ cmd_config(args, self.path_to_tx)
+ with open(self.config_file) as config:
+ self.assertEqual(config.read(), expected)
+
+ @patch('txclib.utils.get_details')
+ @patch('txclib.project.Project._extension_for')
+ def test_auto_remote_is_backwards_compatible(self, extension_mock,
+ get_details_mock):
+ # change the host to tx
+ open(self.config_file, "w").write(
+ '[main]\nhost = https://www.transifex.com\n'
+ )
+ expected = ("[main]\nhost = https://www.transifex.com\n\n"
+ "[proj.resource_1]\n"
+ "file_filter = translations/proj.resource_1/<lang>.txt\n"
+ "source_lang = fr\ntype = TXT\n\n[proj.resource_2]\n"
+ "file_filter = translations/proj.resource_2/<lang>.txt\n"
+ "source_lang = fr\ntype = TXT\n\n")
+ extension_mock.return_value = ".txt"
+ get_details_mock.side_effect = [
+ # project details
+ {
+ 'resources': [
+ {'slug': 'resource_1', 'name': 'resource 1'},
+ {'slug': 'resource_2', 'name': 'resource 2'}
+ ]
+ },
+ # resources details
+ {
+ 'source_language_code': 'fr',
+ 'i18n_type': 'TXT',
+ 'slug': 'resource_1',
+ }, {
+ 'source_language_code': 'fr',
+ 'i18n_type': 'TXT',
+ 'slug': 'resource_2',
+ }
+ ]
+ args = ["--auto-remote", "https://www.transifex.com/test-org/proj/"]
+ cmd_config(args, self.path_to_tx)
+ with open(self.config_file) as config:
+ self.assertEqual(config.read(), expected)
+
+ def test_bulk_missing_options(self):
+ with self.assertRaises(SystemExit):
+ args = [MAPPINGBULK]
+ cmd_config(args, self.path_to_tx)
+
+ with self.assertRaises(SystemExit):
+ args = [MAPPINGBULK, "-p", "test-project"]
+ cmd_config(args, self.path_to_tx)
+
+ with self.assertRaises(SystemExit):
+ args = [MAPPINGBULK, "-p", "test-project", "--source-language",
+ "en", "--t", "TXT", "--file-extension", ".txt"]
+ cmd_config(args, self.path_to_tx)
+
+ def test_bulk(self):
+ expected = ("[main]\nhost = https://foo.var\n\n"
+ "[test-project.translations_en_test]\n"
+ "file_filter = translations/<lang>/en/test.txt\n"
+ "source_file = translations/en/test.txt\n"
+ "source_lang = en\ntype = TXT\n\n")
+ args = [MAPPINGBULK, "-p", "test-project", "--source-file-dir",
+ "translations", "--source-language", "en", "-t", "TXT",
+ "--file-extension", ".txt", "--execute", "--expression",
+ "translations/<lang>/{filepath}/{filename}{extension}"]
+ cmd_config(args, self.path_to_tx)
+ with open(self.config_file) as config:
+ self.assertEqual(config.read(), expected)
+
+
+class TestMainCommand(unittest.TestCase):
+ def test_call_tx_with_no_command(self):
+ with self.assertRaises(SystemExit):
+ main(['tx'])
+
+ def test_call_tx_with_invalid_command(self):
+ with self.assertRaises(SystemExit):
+ main(['tx', 'random'])
diff --git a/tests/test_commands.pyc b/tests/test_commands.pyc
new file mode 100644
index 0000000..6fdee6e
Binary files /dev/null and b/tests/test_commands.pyc differ
diff --git a/tests/test_parsers.pyc b/tests/test_parsers.pyc
new file mode 100644
index 0000000..72474f5
Binary files /dev/null and b/tests/test_parsers.pyc differ
diff --git a/tests/test_paths.pyc b/tests/test_paths.pyc
new file mode 100644
index 0000000..1956226
Binary files /dev/null and b/tests/test_paths.pyc differ
diff --git a/tests/test_processors.pyc b/tests/test_processors.pyc
new file mode 100644
index 0000000..1a05136
Binary files /dev/null and b/tests/test_processors.pyc differ
diff --git a/tests/test_project.py b/tests/test_project.py
index 823d902..3e2b91b 100644
--- a/tests/test_project.py
+++ b/tests/test_project.py
@@ -6,10 +6,22 @@ try:
import json
except ImportError:
import simplejson as json
+try:
+ import configparser
+except ImportError:
+ import ConfigParser as configparser
+
+from functools import wraps
from mock import Mock, patch
+from collections import namedtuple
+from os.path import dirname
+from sys import modules
+
+from txclib.exceptions import AuthenticationError, TXConnectionError
+from txclib.project import (Project, DEFAULT_PULL_URL)
-from txclib.project import Project, ProjectNotInit
from txclib.config import Flipdict
+from txclib import utils
class TestProject(unittest.TestCase):
@@ -19,32 +31,29 @@ class TestProject(unittest.TestCase):
"""Test _get_tx_dir_path function"""
expected_path = '/tmp/'
m_find_dot_tx.return_value = expected_path
- p = Project(init=False)
- path = p._get_tx_dir_path(path_to_tx=None)
+ path = utils.get_tx_dir_path(path_to_tx=None)
self.assertEqual(path, expected_path)
m_find_dot_tx.assert_called_once_with()
expected_path = '/opt/'
- path = p._get_tx_dir_path(path_to_tx=expected_path)
+ path = utils.get_tx_dir_path(path_to_tx=expected_path)
self.assertEqual(path, expected_path)
# make sure it has not been called twice
m_find_dot_tx.assert_called_once_with()
@patch('os.path.exists')
def test_get_config_file_path(self, m_exists):
- """Test _get_config_file_path function"""
- p = Project(init=False)
+ """Test get_config_file_path function"""
m_exists.return_value = True
- p._get_config_file_path('/tmp/')
+ utils.get_config_file_path('/tmp/')
m_exists.assert_called_once_with('/tmp/.tx/config')
m_exists.return_value = False
- with self.assertRaises(ProjectNotInit):
- p._get_config_file_path('/tmp/')
+ with self.assertRaises(utils.ProjectNotInit):
+ utils.get_config_file_path('/tmp/')
- @patch('txclib.utils.confirm')
@patch('txclib.config.configparser')
- def test_getset_host_credentials(self, m_parser, m_confirm):
+ def test_getset_host_credentials(self, m_parser):
p = Project(init=False)
# let suppose a token has been set at the config
dummy_token = 'salala'
@@ -68,6 +77,76 @@ class TestProject(unittest.TestCase):
self.assertEqual(username, 'username')
self.assertEqual(password, 'passw0rdz')
+ @patch('txclib.project.input')
+ @patch('txclib.config.configparser')
+ def test_getset_host_credentials_no_transifexrc(
+ self, m_parser, m_input):
+ p = Project(init=False)
+ # let suppose a token has been set at the config
+ dummy_token = 'salala'
+ p.txrc = m_parser
+ p.save = Mock()
+ p.validate_credentials = Mock(return_value=True)
+ p.txrc_file = '/tmp'
+ p.txrc.get.side_effect = configparser.NoSectionError('test')
+ m_input.return_value = dummy_token
+ username, password = p.getset_host_credentials('test')
+ self.assertEqual(username, 'api')
+ self.assertEqual(password, dummy_token)
+ self.assertEqual(p.txrc.set.call_count, 4)
+ self.assertEqual(m_input.call_count, 1)
+ p.save.assert_called()
+
+ @patch('txclib.project.utils.confirm')
+ @patch('txclib.config.configparser')
+ def test_getset_host_credentials_update_transifexrc(
+ self, m_parser, m_input):
+ p = Project(init=False)
+ dummy_token = 'salala'
+ p.txrc = m_parser
+ p.save = Mock()
+ p.txrc_file = '/tmp'
+ p.validate_credentials = Mock(return_value=True)
+ p.txrc.get.side_effect = [
+ 'foo', 'bar'
+ ]
+ # transifexrc does not get updated if credentials are the same
+ username, password = p.getset_host_credentials(
+ 'test', username='foo', password='bar'
+ )
+ self.assertEqual(username, 'foo')
+ self.assertEqual(password, 'bar')
+ self.assertEqual(p.txrc.set.call_count, 0)
+ self.assertEqual(m_input.call_count, 0)
+ self.assertEqual(p.save.call_count, 0)
+
+ # transifexrc is not updated if confirm is no
+ p.txrc.get.side_effect = [
+ 'foo', 'bar'
+ ]
+ m_input.return_value = False
+ username, password = p.getset_host_credentials('test',
+ token=dummy_token)
+ self.assertEqual(username, 'api')
+ self.assertEqual(password, dummy_token)
+ self.assertEqual(p.txrc.set.call_count, 0)
+ self.assertEqual(m_input.call_count, 1)
+ self.assertEqual(p.save.call_count, 0)
+
+ # transifexrc is not updated if confirm is yes
+ p.txrc.get.side_effect = [
+ 'foo', 'bar'
+ ]
+ m_input.return_value = True
+ m_input.reset_mock()
+ username, password = p.getset_host_credentials('test',
+ token=dummy_token)
+ self.assertEqual(username, 'api')
+ self.assertEqual(password, dummy_token)
+ self.assertEqual(p.txrc.set.call_count, 4)
+ self.assertEqual(m_input.call_count, 1)
+ p.save.assert_called()
+
def test_extract_fields(self):
"""Test the functions that extract a field from a stats object."""
stats = {
@@ -569,6 +648,150 @@ class TestProjectPull(unittest.TestCase):
res = self.p._should_download('pt', self.stats, None, True)
self.assertEqual(res, True)
+ def test_get_url_by_pull_mode(self):
+ self.assertEqual(
+ 'pull_sourceastranslation_file',
+ self.p._get_url_by_pull_mode(mode='sourceastranslation')
+ )
+ self.assertEqual(
+ DEFAULT_PULL_URL,
+ self.p._get_url_by_pull_mode(mode='invalid mode')
+ )
+ self.assertEqual(
+ DEFAULT_PULL_URL,
+ self.p._get_url_by_pull_mode(mode=None)
+ )
+
+ def fixture_mocked_project(func):
+ """A mock object with main os and http operations mocked"""
+ @wraps(func)
+ def wrapper(*args, **kwargs):
+ app_dir = dirname(modules['txclib'].__file__)
+ config_file = app_dir + "/../tests/templates/config"
+ transifex_file = app_dir + "/../tests/templates/transifexrc"
+ with patch("txclib.utils.encode_args") as mock_encode_args, \
+ patch("txclib.utils.determine_charset")\
+ as mock_determine_charset, \
+ patch("txclib.utils.get_transifex_file",
+ return_value=transifex_file) \
+ as mock_get_transifex_file, \
+ patch("txclib.utils.get_config_file_path",
+ return_value=config_file) \
+ as mock_get_config_file_path, \
+ patch("txclib.utils.save_txrc_file") \
+ as mock_save_txrc_file, \
+ patch("txclib.project.Project._get_stats_for_resource") \
+ as mock_get_stats_for_resource:
+
+ # Create fake https response
+ def encode_args(*args, **kwargs):
+ struct = namedtuple("response", "data status close")
+ return struct(status=401, data="mock_response", close=Mock())
+ mock_determine_charset.return_value = "utf-8"
+ mock_encode_args.return_value = encode_args
+
+ # Mock configuration files
+ p = Project(init=False)
+ p._init(path_to_tx=app_dir + "/../templates")
+
+ kwargs['mock_project'] = p
+ kwargs['mocks'] = {
+ 'mock_determine_charset': mock_determine_charset,
+ "mock_encode_args": mock_encode_args,
+ "mock_get_config_file_path": mock_get_config_file_path,
+ "mock_get_stats_for_resource": mock_get_stats_for_resource,
+ "mock_get_transifex_file": mock_get_transifex_file,
+ "mock_save_txrc_file": mock_save_txrc_file
+ }
+ return func(*args, **kwargs)
+ return wrapper
+
+ @fixture_mocked_project
+ @patch("txclib.project.logger.error")
+ def test_pull_raises_authentication_exception(self, mock_logger, **kwargs):
+ project = kwargs['mock_project']
+ with self.assertRaises(AuthenticationError):
+ project.pull()
+ mock_logger.assert_called_once_with(
+ Project.AUTHENTICATION_FAILED_MESSAGE)
+
+ @fixture_mocked_project
+ @patch('txclib.project.Project.do_url_request')
+ def test_pull_with_branch_pulls_from_right_resource(self, m, **kwargs):
+ m.return_value = ('{"i18n_type": "PO"}', '')
+ project = kwargs['mock_project']
+ project.pull(branch='somebranch')
+ self.assertDictEqual(project.url_info, {
+ 'host': 'https://fake.com',
+ 'project': 'example',
+ 'resource': 'somebranch--enpo'
+ })
+
+ @fixture_mocked_project
+ @patch('txclib.project.Project.do_url_request')
+ def test_push_with_branch_pushes_to_right_resource(self, m, **kwargs):
+ m.return_value = ('{"i18n_type": "PO"}', '')
+ project = kwargs['mock_project']
+ project.push(source=True, branch='somebranch')
+ self.assertDictEqual(project.url_info, {
+ 'host': 'https://fake.com',
+ 'project': 'example',
+ 'resource': 'somebranch--enpo'
+ })
+
+ @fixture_mocked_project
+ @patch('txclib.project.Project.do_url_request')
+ def test_push_with_branch_weird_characters_are_handled(self, m, **kwargs):
+ m.return_value = ('{"i18n_type": "PO"}', '')
+ project = kwargs['mock_project']
+ project.push(source=True, branch='some/b**r:a&n!ch')
+ self.assertDictEqual(project.url_info, {
+ 'host': 'https://fake.com',
+ 'project': 'example',
+ 'resource': 'some-b-r-a-n-ch--enpo'
+ })
+
+ @fixture_mocked_project
+ @patch("txclib.project.logger.error")
+ def test_push_raises_authentication_exception(self, mock_logger, **kwargs):
+ project = kwargs['mock_project']
+ with self.assertRaises(AuthenticationError):
+ project.push()
+
+ @fixture_mocked_project
+ @patch("txclib.project.logger.error")
+ def test_delete_raises_authentication_exception(self, mock_logger,
+ **kwargs):
+ project = kwargs['mock_project']
+ with self.assertRaises(AuthenticationError):
+ project.delete()
+
+ @fixture_mocked_project
+ @patch("txclib.project.logger.error")
+ @patch("txclib.utils.make_request")
+ def test_pull_raises_connection_exception(self, mock_request, mock_logger,
+ **kwargs):
+ """Test that all connection errors are properly handled."""
+ project = kwargs["mock_project"]
+ response = 502
+ msg = "Failed with code %d" % response
+ mock_request.side_effect = TXConnectionError(msg, code=response)
+ with self.assertRaises(TXConnectionError):
+ project.pull()
+
+ @fixture_mocked_project
+ @patch("txclib.project.logger.error")
+ @patch("txclib.utils.make_request")
+ def test_push_raises_connection_exception(self, mock_request, mock_logger,
+ **kwargs):
+ """Test that all connection errors are properly handled."""
+ project = kwargs["mock_project"]
+ response = 500
+ msg = "Failed with code %d" % response
+ mock_request.side_effect = TXConnectionError(msg, code=response)
+ with self.assertRaises(TXConnectionError):
+ project.push()
+
class TestFormats(unittest.TestCase):
"""Tests for the supported formats."""
diff --git a/tests/test_project.pyc b/tests/test_project.pyc
new file mode 100644
index 0000000..3f8fdfb
Binary files /dev/null and b/tests/test_project.pyc differ
diff --git a/tests/test_utils.py b/tests/test_utils.py
index 33ad6ab..0fc875d 100755
--- a/tests/test_utils.py
+++ b/tests/test_utils.py
@@ -1,10 +1,19 @@
import unittest
-from mock import patch, MagicMock
+from mock import patch, MagicMock, mock_open
from urllib3.exceptions import SSLError
from txclib import utils, exceptions
+# XXX: Taken from https://stackoverflow.com/a/21611963
+def Any():
+ """A method that will match any parameter."""
+ class Any(object):
+ def __eq__(self, *args):
+ return True
+ return Any()
+
+
class MakeRequestTestCase(unittest.TestCase):
@patch('urllib3.PoolManager')
@@ -109,7 +118,7 @@ class MakeRequestTestCase(unittest.TestCase):
host = 'http://whynotestsforthisstuff.com'
url = '/my_test_url/'
self.assertRaises(
- Exception,
+ exceptions.HttpNotAuthorized,
utils.make_request,
'GET',
host,
... 3310 lines suppressed ...
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/python-modules/packages/transifex-client.git
More information about the Python-modules-commits
mailing list