diff -Nru transifex-client-0.11.1+git15~g655c5e9/appveyor.yml transifex-client-0.12.2/appveyor.yml --- transifex-client-0.11.1+git15~g655c5e9/appveyor.yml 2016-01-26 15:55:25.000000000 +0000 +++ transifex-client-0.12.2/appveyor.yml 1970-01-01 00:00:00.000000000 +0000 @@ -1,75 +0,0 @@ -environment: - global: - # SDK v7.0 MSVC Express 2008's SetEnv.cmd script will fail if the - # /E:ON and /V:ON options are not enabled in the batch script intepreter - # See: http://stackoverflow.com/a/13751649/163740 - CMD_IN_ENV: "cmd /E:ON /V:ON /C .\\appveyor\\run_with_env.cmd" - - matrix: - - - PYTHON: "C:\\Python27" - PYTHON_VERSION: "2.7.x" - PYTHON_ARCH: "32" - - - PYTHON: "C:\\Python27-x64" - PYTHON_VERSION: "2.7.x" - PYTHON_ARCH: "64" - - - PYTHON: "C:\\Python35" - PYTHON_VERSION: "3.5.x" - PYTHON_ARCH: "32" - - - PYTHON: "C:\\Python35-x64" - PYTHON_VERSION: "3.5.x" - PYTHON_ARCH: "64" - - -install: - - ECHO "Filesystem root:" - - ps: "ls \"C:/\"" - - # Prepend newly installed Python to the PATH of this build (this cannot be - # done from inside the powershell script as it would require to restart - # the parent CMD process). - - "SET PATH=%PYTHON%;%PYTHON%\\Scripts;%PATH%" - - # Check that we have the expected version and architecture for Python - - "python --version" - - "python -c \"import struct; print(struct.calcsize('P') * 8)\"" - - # Upgrade to the latest version of pip to avoid it displaying warnings - # about it being out of date. - - "pip install --disable-pip-version-check --user --upgrade pip" - - "pip install pyinstaller" - - # Set up the project in develop mode. If some dependencies contain - # compiled extensions and are not provided as pre-built wheel packages, - # pip will build them from source using the MSVC compiler matching the - # target Python version and architecture - - pip install -e . - -build_script: - # Build the compiled extension - #- "%CMD_IN_ENV% python setup.py build" - - pyinstaller contrib/tx.spec - -test_script: - # Run the project tests - #- "%CMD_IN_ENV% python setup.py nosetests" - - bash contrib/test_win_build.sh - -after_test: - # If tests are successful, create binary packages for the project. - #- "%CMD_IN_ENV% python setup.py bdist_wheel" - #- "%CMD_IN_ENV% python setup.py bdist_wininst" - #- "%CMD_IN_ENV% python setup.py bdist_msi" - - ps: "ls dist" - -artifacts: - # Archive the generated packages in the ci.appveyor.com build report. - - path: dist\* - -#on_success: -# - TODO: upload the content of dist/*.whl to a public wheelhouse -# - diff -Nru transifex-client-0.11.1+git15~g655c5e9/circle.yml transifex-client-0.12.2/circle.yml --- transifex-client-0.11.1+git15~g655c5e9/circle.yml 2016-01-26 15:55:25.000000000 +0000 +++ transifex-client-0.12.2/circle.yml 1970-01-01 00:00:00.000000000 +0000 @@ -1,17 +0,0 @@ -machine: - environment: - TOX_PY27: '2.7.10' - TOX_PY35: '3.5.0' - -dependencies: - override: - - pip -V - - pip install -U pip - - pip install -U ipdb - - pip install -U tox - - pip install -U tox-pyenv - - pyenv local $TOX_PY27 $TOX_PY35 - -test: - override: - - tox -v --recreate diff -Nru transifex-client-0.11.1+git15~g655c5e9/contrib/test_build.sh transifex-client-0.12.2/contrib/test_build.sh --- transifex-client-0.11.1+git15~g655c5e9/contrib/test_build.sh 2016-01-26 15:55:25.000000000 +0000 +++ transifex-client-0.12.2/contrib/test_build.sh 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" -BRANCH="linux_osx" -TX=`which tx` -echo $TX -source "$DIR/tx_commands.sh" diff -Nru transifex-client-0.11.1+git15~g655c5e9/contrib/test_win_build.sh transifex-client-0.12.2/contrib/test_win_build.sh --- transifex-client-0.11.1+git15~g655c5e9/contrib/test_win_build.sh 2016-01-26 15:55:25.000000000 +0000 +++ transifex-client-0.12.2/contrib/test_win_build.sh 1970-01-01 00:00:00.000000000 +0000 @@ -1,11 +0,0 @@ -DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" -BRANCH="win-${PYTHON//C:\\/}" - -# Test the PyInstaller executable: -TX="$DIR/../dist/tx.exe" -source "$DIR/tx_commands.sh" - -# Test the Setuptools script: -TX="tx" -source "$DIR/tx_commands.sh" - diff -Nru transifex-client-0.11.1+git15~g655c5e9/contrib/tx_commands.sh transifex-client-0.12.2/contrib/tx_commands.sh --- transifex-client-0.11.1+git15~g655c5e9/contrib/tx_commands.sh 2016-01-26 15:55:25.000000000 +0000 +++ transifex-client-0.12.2/contrib/tx_commands.sh 1970-01-01 00:00:00.000000000 +0000 @@ -1,17 +0,0 @@ -if [[ -z "$TRANSIFEX_USER" ]] ; then - echo "NB: Skipping tests of $TX since TRANSIFEX_USER is undefined or empty" - exit 0 -fi - -# Exit on fail -set -e - -rm -rf txci -git clone https://github.com/diegobz/txci.git -cd txci -rm -rf .tx -$TX init --host="https://www.transifex.com" --user=$TRANSIFEX_USER --pass=$TRANSIFEX_PASSWORD -$TX set --auto-local -r txci.$BRANCH -s en 'locale//LC_MESSAGES/django.po' -t PO --execute -$TX --traceback push -s -$TX --traceback pull -l pt_BR -f -$TX --traceback delete -f Binary files /tmp/tmp1Xhz7z/baeP0Ngzec/transifex-client-0.11.1+git15~g655c5e9/contrib/tx.ico and /tmp/tmp1Xhz7z/zCwtOvCwqU/transifex-client-0.12.2/contrib/tx.ico differ diff -Nru transifex-client-0.11.1+git15~g655c5e9/contrib/tx.spec transifex-client-0.12.2/contrib/tx.spec --- transifex-client-0.11.1+git15~g655c5e9/contrib/tx.spec 2016-01-26 15:55:25.000000000 +0000 +++ transifex-client-0.12.2/contrib/tx.spec 1970-01-01 00:00:00.000000000 +0000 @@ -1,29 +0,0 @@ -# -*- mode: python -*- - -block_cipher = None -added_files = [ - ('../txclib/cacert.pem', 'txclib'), -] - -a = Analysis(['../txclib/cmdline.py'], - binaries=None, - datas=added_files, - hiddenimports=[], - hookspath=None, - runtime_hooks=None, - excludes=None, - win_no_prefer_redirects=None, - win_private_assemblies=None, - cipher=block_cipher) -pyz = PYZ(a.pure, a.zipped_data, - cipher=block_cipher) -exe = EXE(pyz, - a.scripts, - a.binaries, - a.zipfiles, - a.datas, - name='tx', - debug=False, - strip=None, - upx=False, - console=True , icon='contrib/tx.ico') diff -Nru transifex-client-0.11.1+git15~g655c5e9/debian/changelog transifex-client-0.12.2/debian/changelog --- transifex-client-0.11.1+git15~g655c5e9/debian/changelog 2016-02-17 22:33:55.000000000 +0000 +++ transifex-client-0.12.2/debian/changelog 2018-05-04 16:58:29.000000000 +0000 @@ -1,3 +1,24 @@ +transifex-client (0.12.2-2~xenial1) xenial; urgency=medium + + * Build for PPA. + + -- Ricardo Villalba Fri, 04 May 2018 18:57:15 +0200 + +transifex-client (0.12.2-1) unstable; urgency=medium + + * New upstream release + + -- Hans-Christoph Steiner Tue, 13 Sep 2016 10:57:30 +0200 + +transifex-client (0.11.1+git15~g655c5e9-1.1) unstable; urgency=medium + + * Non-maintainer upload. + * Use the six library instead of the one embedded in urllib3. + - Backport upstream commits. + - Closes: #817038 + + -- Felix Geyer Sat, 03 Sep 2016 22:17:45 +0200 + transifex-client (0.11.1+git15~g655c5e9-1) unstable; urgency=low * New upstream release diff -Nru transifex-client-0.11.1+git15~g655c5e9/debian/control transifex-client-0.12.2/debian/control --- transifex-client-0.11.1+git15~g655c5e9/debian/control 2016-02-17 22:31:26.000000000 +0000 +++ transifex-client-0.12.2/debian/control 2016-09-13 08:57:30.000000000 +0000 @@ -6,14 +6,14 @@ Hans-Christoph Steiner Build-Depends: debhelper (>= 9), python-all, python-setuptools, python-mock, bash-completion -Standards-Version: 3.9.6 +Standards-Version: 3.9.8 Homepage: https://www.transifex.com/ Vcs-Git: https://anonscm.debian.org/git/python-modules/packages/transifex-client.git Vcs-Browser: https://anonscm.debian.org/cgit/python-modules/packages/transifex-client.git Package: transifex-client Architecture: all -Depends: ${misc:Depends}, ${python:Depends}, python-pkg-resources +Depends: ${misc:Depends}, ${python:Depends}, python-pkg-resources, python-openssl Provides: ${python:Provides} Description: Command line interface for Transifex Transifex Command-line Client is a command line tool that enables you to diff -Nru transifex-client-0.11.1+git15~g655c5e9/debian/watch transifex-client-0.12.2/debian/watch --- transifex-client-0.11.1+git15~g655c5e9/debian/watch 2016-02-17 22:14:19.000000000 +0000 +++ transifex-client-0.12.2/debian/watch 2016-09-13 08:57:30.000000000 +0000 @@ -1,2 +1,3 @@ version=3 -https://pypi.python.org/packages/source/t/transifex-client/transifex-client-(.*).tar.gz +opts=uversionmangle=s/\.RC/~RC/ \ +http://pypi.debian.net/transifex-client/transifex-client-(.*)\.tar\.gz diff -Nru transifex-client-0.11.1+git15~g655c5e9/DEVELOPMENT.rst transifex-client-0.12.2/DEVELOPMENT.rst --- transifex-client-0.11.1+git15~g655c5e9/DEVELOPMENT.rst 2016-01-26 15:55:25.000000000 +0000 +++ transifex-client-0.12.2/DEVELOPMENT.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,21 +0,0 @@ -Releasing -========= - -To create a new release: - -1. Update local rep and update the version in ``setup.py``:: - - $ hg pull -u - $ vim setup.py - -2. Test:: - - $ python setup.py clean sdist - $ cd dist - $ tar zxf ... - $ cd transifex-client - ...test - -3. Package and upload on PyPI:: - - $ python setup.py clean sdist bdist_egg upload diff -Nru transifex-client-0.11.1+git15~g655c5e9/.gitignore transifex-client-0.12.2/.gitignore --- transifex-client-0.11.1+git15~g655c5e9/.gitignore 2016-01-26 15:55:25.000000000 +0000 +++ transifex-client-0.12.2/.gitignore 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -.tx -*pyc -*pyo -*~ -*egg-info* -/build -/dist diff -Nru transifex-client-0.11.1+git15~g655c5e9/PKG-INFO transifex-client-0.12.2/PKG-INFO --- transifex-client-0.11.1+git15~g655c5e9/PKG-INFO 1970-01-01 00:00:00.000000000 +0000 +++ transifex-client-0.12.2/PKG-INFO 2016-08-09 15:02:59.000000000 +0000 @@ -0,0 +1,86 @@ +Metadata-Version: 1.1 +Name: transifex-client +Version: 0.12.2 +Summary: A command line interface for Transifex +Home-page: https://www.transifex.com +Author: Transifex +Author-email: admin@transifex.com +License: GPLv2 +Description: .. image:: https://circleci.com/gh/transifex/transifex-client/tree/master.svg?style=shield&circle-token=33aafd984726261eff1b73278a0cf761382c478a + :target: https://circleci.com/gh/transifex/transifex-client/tree/master + .. image:: https://ci.appveyor.com/api/projects/status/github/transifex/transifex-client?branch=master&svg=true + :target: https://ci.appveyor.com/project/transifex/transifex-client/branch/master + .. image:: https://codecov.io/gh/transifex/transifex-client/branch/master/graph/badge.svg +    :target: https://codecov.io/gh/transifex/transifex-client + + + + ============================= + Transifex Command-Line Tool + ============================= + + The Transifex Command-line Tool enables you to manage your translations within a project without the need of an elaborate UI system. + + You can use the command line tool to create new resources, map locale files to translations, and synchronize your Transifex project with your local repository. Translators and localization managers can use it to handle large volumes of translation files. The Transifex Command-line Tool can help to enable continuous integration workflows and can be run from CI servers like Jenkins and Bamboo. + + Check the full documentation at http://docs.transifex.com/client/ + + Installing + ========== + + You can install the latest version of transifex-client running ``pip + install transifex-client`` or ``easy_install transifex-client``. + + + Build transifex-client for Windows + ================================== + + 1. Download transifex-client sources via git or github archive. + + a. ``git clone https://github.com/transifex/transifex-client.git`` + b. Download and unpack https://github.com/transifex/transifex-client/archive/master.zip + + 2. Download and install Python_. + + At this step choose right version of python: 2 or 3 and x86 or x86-64 instruction set. + + Make sure pip marked for installation(default for latest installers). + + 3. Install PyInstaller_. + + Suppose that Python installed to ``C:\\Program Files\\Python35-32`` + + Make ``python.exe`` accessible via PATH environment variable or cd to directory containing python.exe. + + :: + + python -m pip install pyinstaller + + This command will install ``PyInstaller`` package and its dependencies. + + 4. Build ``transifex-client`` distribution. + + Change directory to transifex-client folder and run command: + + :: + + python -m PyInstaller contrib/tx.spec + # or + pyinstaller contrib/tx.spec + + 5. ``tx.exe`` + + ``dist/tx.exe`` will be created as the result of build process. + + + .. _Python: https://www.python.org/downloads/windows/ + .. _PyInstaller: http://www.pyinstaller.org + +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 diff -Nru transifex-client-0.11.1+git15~g655c5e9/README.rst transifex-client-0.12.2/README.rst --- transifex-client-0.11.1+git15~g655c5e9/README.rst 2016-01-26 15:55:25.000000000 +0000 +++ transifex-client-0.12.2/README.rst 2016-07-21 10:15:27.000000000 +0000 @@ -2,25 +2,20 @@ :target: https://circleci.com/gh/transifex/transifex-client/tree/master .. image:: https://ci.appveyor.com/api/projects/status/github/transifex/transifex-client?branch=master&svg=true :target: https://ci.appveyor.com/project/transifex/transifex-client/branch/master +.. image:: https://codecov.io/gh/transifex/transifex-client/branch/master/graph/badge.svg +   :target: https://codecov.io/gh/transifex/transifex-client + ============================= Transifex Command-Line Tool ============================= -The Transifex Command-line Client is a command line tool that enables -you to easily manage your translations within a project without the need -of an elaborate UI system. - -You can use the command line client to easily create new resources, map -locale files to translations and synchronize your Transifex project with -your local repository and vice verca. Translators and localization -managers can also use it to handle large volumes of translation files -easily and without much hassle. +The Transifex Command-line Tool enables you to manage your translations within a project without the need of an elaborate UI system. -Check the full documentation at -http://docs.transifex.com/client/ +You can use the command line tool to create new resources, map locale files to translations, and synchronize your Transifex project with your local repository. Translators and localization managers can use it to handle large volumes of translation files. The Transifex Command-line Tool can help to enable continuous integration workflows and can be run from CI servers like Jenkins and Bamboo. +Check the full documentation at http://docs.transifex.com/client/ Installing ========== diff -Nru transifex-client-0.11.1+git15~g655c5e9/requirements.txt transifex-client-0.12.2/requirements.txt --- transifex-client-0.11.1+git15~g655c5e9/requirements.txt 2016-01-26 15:55:25.000000000 +0000 +++ transifex-client-0.12.2/requirements.txt 2016-07-21 10:15:27.000000000 +0000 @@ -1 +1,2 @@ urllib3 +six diff -Nru transifex-client-0.11.1+git15~g655c5e9/setup.cfg transifex-client-0.12.2/setup.cfg --- transifex-client-0.11.1+git15~g655c5e9/setup.cfg 1970-01-01 00:00:00.000000000 +0000 +++ transifex-client-0.12.2/setup.cfg 2016-08-09 15:02:59.000000000 +0000 @@ -0,0 +1,5 @@ +[egg_info] +tag_build = +tag_date = 0 +tag_svn_revision = 0 + diff -Nru transifex-client-0.11.1+git15~g655c5e9/tests/test_utils.py transifex-client-0.12.2/tests/test_utils.py --- transifex-client-0.11.1+git15~g655c5e9/tests/test_utils.py 1970-01-01 00:00:00.000000000 +0000 +++ transifex-client-0.12.2/tests/test_utils.py 2016-08-09 14:34:13.000000000 +0000 @@ -0,0 +1,163 @@ +import unittest +from mock import patch, MagicMock +from urllib3.exceptions import SSLError + +from txclib import utils, exceptions + + +class MakeRequestTestCase(unittest.TestCase): + + @patch('urllib3.PoolManager') + def test_makes_request(self, mock_manager): + response_mock = MagicMock() + response_mock.status = 200 + response_mock.data = 'test_data' + + mock_connection = MagicMock() + mock_connection.request.return_value = response_mock + mock_manager.return_value = mock_connection + + host = 'http://whynotestsforthisstuff.com' + url = '/my_test_url/' + utils.make_request( + 'GET', + host, + url, + 'a_user', + 'a_pass' + ) + mock_manager.assert_called_once_with(num_pools=1) + mock_connection.request.assert_called_once() + + @patch('urllib3.PoolManager') + @patch('txclib.utils.logger') + def test_catches_ssl_error(self, mock_logger, mock_manager): + mock_connection = MagicMock() + mock_connection.request.side_effect = SSLError('Boom!') + mock_manager.return_value = mock_connection + + host = 'https://whynotestsforthisstuff.com' + url = '/my_test_url/' + self.assertRaises( + SSLError, + utils.make_request, + 'GET', + host, + url, + 'a_user', + 'a_pass' + ) + mock_logger.error.assert_called_once_with("Invalid SSL certificate") + + @patch('txclib.utils.determine_charset') + @patch('urllib3.PoolManager') + def test_makes_request_skip_decode(self, mock_conn, mock_determine): + response_mock = MagicMock() + response_mock.status = 200 + response_mock.data = 'test_data' + + mock_connection = MagicMock() + mock_connection.request.return_value = response_mock + mock_conn.return_value = mock_connection + + host = 'http://whynotestsforthisstuff.com' + url = '/my_test_url/' + utils.make_request( + 'GET', + host, + url, + 'a_user', + 'a_pass', + skip_decode=True + ) + mock_conn.assert_called_once_with(num_pools=1) + mock_connection.request.assert_called_once() + mock_determine.assert_not_called() + + @patch('urllib3.PoolManager') + def test_makes_request_404(self, mock_manager): + response_mock = MagicMock() + response_mock.status = 404 + response_mock.data = 'test_data' + + mock_connection = MagicMock() + mock_connection.request.return_value = response_mock + mock_manager.return_value = mock_connection + + host = 'http://whynotestsforthisstuff.com' + url = '/my_test_url/' + self.assertRaises( + exceptions.HttpNotFound, + utils.make_request, + 'GET', + host, + url, + 'a_user', + 'a_pass' + ) + + @patch('urllib3.PoolManager') + def test_makes_request_403(self, mock_manager): + response_mock = MagicMock() + response_mock.status = 403 + response_mock.data = 'test_data' + + mock_connection = MagicMock() + mock_connection.request.return_value = response_mock + mock_manager.return_value = mock_connection + + host = 'http://whynotestsforthisstuff.com' + url = '/my_test_url/' + self.assertRaises( + Exception, + utils.make_request, + 'GET', + host, + url, + 'a_user', + 'a_pass' + ) + + @patch('urllib3.PoolManager') + def test_makes_request_401(self, mock_manager): + response_mock = MagicMock() + response_mock.status = 401 + response_mock.data = 'test_data' + + mock_connection = MagicMock() + mock_connection.request.return_value = response_mock + mock_manager.return_value = mock_connection + + host = 'http://whynotestsforthisstuff.com' + url = '/my_test_url/' + self.assertRaises( + exceptions.HttpNotAuthorized, + utils.make_request, + 'GET', + host, + url, + 'a_user', + 'a_pass' + ) + + @patch('urllib3.PoolManager') + def test_makes_request_None(self, mock_manager): + response_mock = MagicMock() + response_mock.status = 200 + response_mock.data = None + + mock_connection = MagicMock() + mock_connection.request.return_value = response_mock + mock_manager.return_value = mock_connection + + host = 'http://whynotestsforthisstuff.com' + url = '/my_test_url/' + utils.make_request( + 'GET', + host, + url, + 'a_user', + 'a_pass' + ) + mock_manager.assert_called_once_with(num_pools=1) + mock_connection.request.assert_called_once() diff -Nru transifex-client-0.11.1+git15~g655c5e9/tox.ini transifex-client-0.12.2/tox.ini --- transifex-client-0.11.1+git15~g655c5e9/tox.ini 2016-01-26 15:55:25.000000000 +0000 +++ transifex-client-0.12.2/tox.ini 1970-01-01 00:00:00.000000000 +0000 @@ -1,12 +0,0 @@ -[tox] -envlist = py27,py35 - -[testenv] -whitelist_externals = source - bash -install_command = pip install -U {opts} {packages} -setenv = TOX_ENV_NAME={envname} -passenv = TOX_* TRANSIFEX_USER TRANSIFEX_PASSWORD CI_* APPVEYOR_* -commands = python -V - python setup.py test - bash ./contrib/test_build.sh diff -Nru transifex-client-0.11.1+git15~g655c5e9/transifex_client.egg-info/dependency_links.txt transifex-client-0.12.2/transifex_client.egg-info/dependency_links.txt --- transifex-client-0.11.1+git15~g655c5e9/transifex_client.egg-info/dependency_links.txt 1970-01-01 00:00:00.000000000 +0000 +++ transifex-client-0.12.2/transifex_client.egg-info/dependency_links.txt 2016-08-09 15:02:59.000000000 +0000 @@ -0,0 +1 @@ + diff -Nru transifex-client-0.11.1+git15~g655c5e9/transifex_client.egg-info/entry_points.txt transifex-client-0.12.2/transifex_client.egg-info/entry_points.txt --- transifex-client-0.11.1+git15~g655c5e9/transifex_client.egg-info/entry_points.txt 1970-01-01 00:00:00.000000000 +0000 +++ transifex-client-0.12.2/transifex_client.egg-info/entry_points.txt 2016-08-09 15:02:59.000000000 +0000 @@ -0,0 +1,3 @@ +[console_scripts] +tx = txclib.cmdline:main + diff -Nru transifex-client-0.11.1+git15~g655c5e9/transifex_client.egg-info/not-zip-safe transifex-client-0.12.2/transifex_client.egg-info/not-zip-safe --- transifex-client-0.11.1+git15~g655c5e9/transifex_client.egg-info/not-zip-safe 1970-01-01 00:00:00.000000000 +0000 +++ transifex-client-0.12.2/transifex_client.egg-info/not-zip-safe 2016-06-03 11:56:55.000000000 +0000 @@ -0,0 +1 @@ + diff -Nru transifex-client-0.11.1+git15~g655c5e9/transifex_client.egg-info/PKG-INFO transifex-client-0.12.2/transifex_client.egg-info/PKG-INFO --- transifex-client-0.11.1+git15~g655c5e9/transifex_client.egg-info/PKG-INFO 1970-01-01 00:00:00.000000000 +0000 +++ transifex-client-0.12.2/transifex_client.egg-info/PKG-INFO 2016-08-09 15:02:59.000000000 +0000 @@ -0,0 +1,86 @@ +Metadata-Version: 1.1 +Name: transifex-client +Version: 0.12.2 +Summary: A command line interface for Transifex +Home-page: https://www.transifex.com +Author: Transifex +Author-email: admin@transifex.com +License: GPLv2 +Description: .. image:: https://circleci.com/gh/transifex/transifex-client/tree/master.svg?style=shield&circle-token=33aafd984726261eff1b73278a0cf761382c478a + :target: https://circleci.com/gh/transifex/transifex-client/tree/master + .. image:: https://ci.appveyor.com/api/projects/status/github/transifex/transifex-client?branch=master&svg=true + :target: https://ci.appveyor.com/project/transifex/transifex-client/branch/master + .. image:: https://codecov.io/gh/transifex/transifex-client/branch/master/graph/badge.svg +    :target: https://codecov.io/gh/transifex/transifex-client + + + + ============================= + Transifex Command-Line Tool + ============================= + + The Transifex Command-line Tool enables you to manage your translations within a project without the need of an elaborate UI system. + + You can use the command line tool to create new resources, map locale files to translations, and synchronize your Transifex project with your local repository. Translators and localization managers can use it to handle large volumes of translation files. The Transifex Command-line Tool can help to enable continuous integration workflows and can be run from CI servers like Jenkins and Bamboo. + + Check the full documentation at http://docs.transifex.com/client/ + + Installing + ========== + + You can install the latest version of transifex-client running ``pip + install transifex-client`` or ``easy_install transifex-client``. + + + Build transifex-client for Windows + ================================== + + 1. Download transifex-client sources via git or github archive. + + a. ``git clone https://github.com/transifex/transifex-client.git`` + b. Download and unpack https://github.com/transifex/transifex-client/archive/master.zip + + 2. Download and install Python_. + + At this step choose right version of python: 2 or 3 and x86 or x86-64 instruction set. + + Make sure pip marked for installation(default for latest installers). + + 3. Install PyInstaller_. + + Suppose that Python installed to ``C:\\Program Files\\Python35-32`` + + Make ``python.exe`` accessible via PATH environment variable or cd to directory containing python.exe. + + :: + + python -m pip install pyinstaller + + This command will install ``PyInstaller`` package and its dependencies. + + 4. Build ``transifex-client`` distribution. + + Change directory to transifex-client folder and run command: + + :: + + python -m PyInstaller contrib/tx.spec + # or + pyinstaller contrib/tx.spec + + 5. ``tx.exe`` + + ``dist/tx.exe`` will be created as the result of build process. + + + .. _Python: https://www.python.org/downloads/windows/ + .. _PyInstaller: http://www.pyinstaller.org + +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 diff -Nru transifex-client-0.11.1+git15~g655c5e9/transifex_client.egg-info/requires.txt transifex-client-0.12.2/transifex_client.egg-info/requires.txt --- transifex-client-0.11.1+git15~g655c5e9/transifex_client.egg-info/requires.txt 1970-01-01 00:00:00.000000000 +0000 +++ transifex-client-0.12.2/transifex_client.egg-info/requires.txt 2016-08-09 15:02:59.000000000 +0000 @@ -0,0 +1,2 @@ +urllib3 +six diff -Nru transifex-client-0.11.1+git15~g655c5e9/transifex_client.egg-info/SOURCES.txt transifex-client-0.12.2/transifex_client.egg-info/SOURCES.txt --- transifex-client-0.11.1+git15~g655c5e9/transifex_client.egg-info/SOURCES.txt 1970-01-01 00:00:00.000000000 +0000 +++ transifex-client-0.12.2/transifex_client.egg-info/SOURCES.txt 2016-08-09 15:02:59.000000000 +0000 @@ -0,0 +1,32 @@ +LICENSE +MANIFEST.in +README.rst +requirements.txt +setup.py +tests/__init__.py +tests/test_paths.py +tests/test_processors.py +tests/test_project.py +tests/test_utils.py +transifex_client.egg-info/PKG-INFO +transifex_client.egg-info/SOURCES.txt +transifex_client.egg-info/dependency_links.txt +transifex_client.egg-info/entry_points.txt +transifex_client.egg-info/not-zip-safe +transifex_client.egg-info/requires.txt +transifex_client.egg-info/top_level.txt +txclib/__init__.py +txclib/__main__.py +txclib/cacert.pem +txclib/cmdline.py +txclib/commands.py +txclib/config.py +txclib/exceptions.py +txclib/log.py +txclib/parsers.py +txclib/paths.py +txclib/processors.py +txclib/project.py +txclib/urls.py +txclib/utils.py +txclib/web.py \ No newline at end of file diff -Nru transifex-client-0.11.1+git15~g655c5e9/transifex_client.egg-info/top_level.txt transifex-client-0.12.2/transifex_client.egg-info/top_level.txt --- transifex-client-0.11.1+git15~g655c5e9/transifex_client.egg-info/top_level.txt 1970-01-01 00:00:00.000000000 +0000 +++ transifex-client-0.12.2/transifex_client.egg-info/top_level.txt 2016-08-09 15:02:59.000000000 +0000 @@ -0,0 +1 @@ +txclib diff -Nru transifex-client-0.11.1+git15~g655c5e9/txclib/cmdline.py transifex-client-0.12.2/txclib/cmdline.py --- transifex-client-0.11.1+git15~g655c5e9/txclib/cmdline.py 2016-01-26 15:55:25.000000000 +0000 +++ transifex-client-0.12.2/txclib/cmdline.py 2016-07-21 10:15:27.000000000 +0000 @@ -11,6 +11,14 @@ from txclib.log import set_log_level, logger +# use pyOpenSSL if available +try: + import urllib3.contrib.pyopenssl + urllib3.contrib.pyopenssl.inject_into_urllib3() +except ImportError: + pass + + # This block ensures that ^C interrupts are handled quietly. try: import signal diff -Nru transifex-client-0.11.1+git15~g655c5e9/txclib/commands.py transifex-client-0.12.2/txclib/commands.py --- transifex-client-0.11.1+git15~g655c5e9/txclib/commands.py 2016-01-26 15:55:25.000000000 +0000 +++ transifex-client-0.12.2/txclib/commands.py 2016-07-21 10:15:27.000000000 +0000 @@ -25,7 +25,7 @@ except ImportError: import ConfigParser as configparser -from urllib3.packages.six.moves import input +from six.moves import input from txclib import utils, project from txclib.utils import parse_json, compile_json, files_in_project @@ -278,7 +278,7 @@ prj = project.Project(path_to_tx) username, password = prj.getset_host_credentials(vars['hostname']) - if type == 'project': + if type.startswith('project'): logger.info("Getting details for project %s" % vars['project']) proj_info = utils.get_details( 'project_details', @@ -303,7 +303,7 @@ else: resources.append('.'.join([vars['project'], r['slug']])) logger.info("%s resources found. Configuring..." % len(resources)) - elif type == 'resource': + elif type.startswith('resource'): logger.info("Getting details for resource %s" % vars['resource']) resources = ['.'.join([vars['project'], vars['resource']])] else: diff -Nru transifex-client-0.11.1+git15~g655c5e9/txclib/config.py transifex-client-0.12.2/txclib/config.py --- transifex-client-0.11.1+git15~g655c5e9/txclib/config.py 2016-01-26 15:55:25.000000000 +0000 +++ transifex-client-0.12.2/txclib/config.py 2016-07-21 10:15:27.000000000 +0000 @@ -3,7 +3,7 @@ except ImportError: import ConfigParser as configparser -from urllib3.packages import six +import six class OrderedRawConfigParser(configparser.RawConfigParser): @@ -118,3 +118,9 @@ def clear(self): dict.clear(self) dict.clear(self._flip) + + +import os +import ssl + +CERT_REQUIRED = getattr(ssl, os.environ.get('TX_CERT_MODE', 'CERT_REQUIRED')) diff -Nru transifex-client-0.11.1+git15~g655c5e9/txclib/exceptions.py transifex-client-0.12.2/txclib/exceptions.py --- transifex-client-0.11.1+git15~g655c5e9/txclib/exceptions.py 2016-01-26 15:55:25.000000000 +0000 +++ transifex-client-0.12.2/txclib/exceptions.py 2016-06-21 11:33:12.000000000 +0000 @@ -11,3 +11,14 @@ class UnknownCommandError(Exception): """The provided command is not supported.""" + + +# HTTP exceptions + + +class HttpNotFound(Exception): + pass + + +class HttpNotAuthorized(Exception): + pass diff -Nru transifex-client-0.11.1+git15~g655c5e9/txclib/__init__.py transifex-client-0.12.2/txclib/__init__.py --- transifex-client-0.11.1+git15~g655c5e9/txclib/__init__.py 2016-01-26 15:55:25.000000000 +0000 +++ transifex-client-0.12.2/txclib/__init__.py 2016-08-09 14:37:00.000000000 +0000 @@ -1,4 +1,4 @@ # -*- coding: utf-8 -*- # https://www.python.org/dev/peps/pep-0440/#examples-of-compliant-version-schemes -__version__ = '0.11' +__version__ = '0.12.2' diff -Nru transifex-client-0.11.1+git15~g655c5e9/txclib/project.py transifex-client-0.12.2/txclib/project.py --- transifex-client-0.11.1+git15~g655c5e9/txclib/project.py 2016-01-26 15:55:25.000000000 +0000 +++ transifex-client-0.12.2/txclib/project.py 2016-07-21 10:15:27.000000000 +0000 @@ -6,9 +6,9 @@ import fnmatch import datetime import time -import ssl import sys import urllib3 +import six try: import configparser @@ -18,14 +18,16 @@ from txclib import web from txclib import utils from urllib3.exceptions import SSLError -from urllib3.packages import six +from six.moves import input from txclib.urls import API_URLS -from txclib.config import OrderedRawConfigParser, Flipdict +from txclib.config import OrderedRawConfigParser, Flipdict, CERT_REQUIRED from txclib.log import logger from txclib.processors import visit_hostname from txclib.paths import posix_path, native_path, posix_sep + + class ProjectNotInit(Exception): pass @@ -35,6 +37,9 @@ remote project instances. """ + SKIP_DECODE_I18N_TYPES = ['DOCX', 'XLSX'] + FILE_FILTER = "translations%(proj)s.%(res)s.%(extension)s" + def __init__(self, path_to_tx=None, init=True): """Initialize the Project attributes.""" if init: @@ -60,7 +65,7 @@ if host.lower().startswith('https://'): self.conn = urllib3.connection_from_url( host, - cert_reqs=ssl.CERT_REQUIRED, + cert_reqs=CERT_REQUIRED, ca_certs=web.certs_file() ) else: @@ -174,9 +179,11 @@ return username, passwd def set_remote_resource(self, resource, source_lang, i18n_type, host, - file_filter="translations%(proj)s.%(res)s\ - .%(extension)s"): + file_filter=None): """Method to handle the add/conf of a remote resource.""" + if file_filter is None: + file_filter = self.FILE_FILTER + if not self.config.has_section(resource): self.config.add_section(resource) @@ -377,6 +384,7 @@ """Pull all translations file from transifex server.""" self.minimum_perc = minimum_perc resource_list = self.get_chosen_resources(resources) + skip_decode = False if mode == 'reviewed': url = 'pull_reviewed_file' @@ -411,7 +419,10 @@ logger.debug("URL data are: %s" % self.url_info) stats = self._get_stats_for_resource() - + details_response, _ = self.do_url_request('resource_details') + details = utils.parse_json(details_response) + if details['i18n_type'] in self.SKIP_DECODE_I18N_TYPES: + skip_decode = True try: file_filter = self.config.get(resource, 'file_filter') except configparser.NoOptionError: @@ -500,18 +511,16 @@ local_file) ) try: - r, charset = self.do_url_request(url, language=remote_lang) + r, charset = self.do_url_request( + url, language=remote_lang, skip_decode=skip_decode + ) except Exception as e: if isinstance(e, SSLError) or not skip: raise else: logger.error(e) continue - base_dir = os.path.split(local_file)[0] - utils.mkdir_p(base_dir) - fd = open(local_file, 'wb') - fd.write(r.encode(charset)) - fd.close() + self._save_file(local_file, charset, r) if new_translations: msg = "Pulling new translations for resource %s (source: %s)" @@ -552,12 +561,10 @@ local_file) ) - r, charset = self.do_url_request(url, language=remote_lang) - base_dir = os.path.split(local_file)[0] - utils.mkdir_p(base_dir) - fd = open(local_file, 'wb') - fd.write(r.encode(charset)) - fd.close() + r, charset = self.do_url_request( + url, language=remote_lang, skip_decode=skip_decode + ) + self._save_file(local_file, charset, r) def push(self, source=False, translations=False, force=False, resources=[], languages=[], skip=False, no_interactive=False): @@ -630,6 +637,9 @@ if isinstance(e, SSLError): raise code = getattr(e, 'code', None) + if code == 401: + logger.error("Request is not authorized.") + continue if code == 404: msg = "Resource %s doesn't exist on the server." logger.error(msg % resource) @@ -720,7 +730,6 @@ logger.debug("URL data are: %s" % self.url_info) json, _ = self.do_url_request('project_details', project=self) project_details = utils.parse_json(json) - teams = project_details['teams'] stats = self._get_stats_for_resource() delete_func(project_details, resource, stats, languages) @@ -809,14 +818,13 @@ raise def do_url_request(self, api_call, multipart=False, data=None, - files=[], method="GET", **kwargs): + files=[], method="GET", skip_decode=False, **kwargs): """Issues a url request.""" # Read the credentials from the config file (.transifexrc) host = self.url_info['host'] try: username = self.txrc.get(host, 'username') passwd = self.txrc.get(host, 'password') - token = self.txrc.get(host, 'token') hostname = self.txrc.get(host, 'hostname') except configparser.NoSectionError: raise Exception( @@ -840,8 +848,10 @@ "language": info.split(';')[1], "uploaded_file": (name, open(filename, 'rb').read()) } - return utils.make_request(method, hostname, - url, username, passwd, data) + return utils.make_request( + method, hostname, url, username, passwd, data, + skip_decode=skip_decode + ) def _should_update_translation(self, lang, stats, local_file, force=False, mode=None): @@ -1073,7 +1083,6 @@ new to the local installation. """ new_translations = [] - timestamp = time.time() langs = list(stats.keys()) logger.debug("Available languages are: %s" % langs) @@ -1196,7 +1205,6 @@ Raises: URLError, in case of a problem. """ - multipart = True method = "POST" api_call = 'create_resource' @@ -1204,7 +1212,6 @@ try: username = self.txrc.get(host, 'username') passwd = self.txrc.get(host, 'password') - token = self.txrc.get(host, 'token') hostname = self.txrc.get(host, 'hostname') except configparser.NoSectionError: raise Exception("No user credentials found for host %s. Edit " @@ -1278,3 +1285,13 @@ return for r in resources: self.config.set(r, key, value) + + @staticmethod + def _save_file(local_file, charset, file_content): + base_dir = os.path.split(local_file)[0] + utils.mkdir_p(base_dir) + fd = open(local_file, 'wb') + if charset is not None: + file_content = file_content.encode(charset) + fd.write(file_content) + fd.close() diff -Nru transifex-client-0.11.1+git15~g655c5e9/txclib/utils.py transifex-client-0.12.2/txclib/utils.py --- transifex-client-0.11.1+git15~g655c5e9/txclib/utils.py 2016-01-26 15:55:25.000000000 +0000 +++ transifex-client-0.12.2/txclib/utils.py 2016-08-09 14:34:13.000000000 +0000 @@ -3,8 +3,10 @@ import sys import re import errno -import ssl import urllib3 +import collections +import six +import ssl try: from json import loads as parse_json, dumps as compile_json @@ -13,17 +15,13 @@ from email.parser import Parser from urllib3.exceptions import SSLError -from urllib3.packages import six -from urllib3.packages.six.moves import input +from six.moves import input from txclib.urls import API_URLS -from txclib.exceptions import UnknownCommandError +from txclib.exceptions import UnknownCommandError, HttpNotFound, HttpNotAuthorized from txclib.paths import posix_path, native_path, posix_sep from txclib.web import user_agent_identifier, certs_file from txclib.log import logger - - -class HttpNotFound(Exception): - pass +from txclib.config import CERT_REQUIRED def get_base_dir(): @@ -72,10 +70,12 @@ return "^%s$" % expr_re -TX_URLS = { - 'resource': '(?Phttps?://(\w|\.|:|-)+)/projects/p/(?P(\w|-)+)/resource/(?P(\w|-)+)/?$', # noqa - 'project': '(?Phttps?://(\w|\.|:|-)+)/projects/p/(?P(\w|-)+)/?$', # noqa -} +TX_URLS = collections.OrderedDict([ + ('resource', '(?Phttps?://(\w|\.|:|-)+)/projects/p/(?P(\w|-)+)/resource/(?P(\w|-)+)/?$'), # noqa + ('project', '(?Phttps?://(\w|\.|:|-)+)/projects/p/(?P(\w|-)+)/?$'), # noqa + ('project2', '(?Phttps?://(\w|\.|:|-)+)/(\w|-)+/(?P(\w|-)+)(/(dashboard|settings))?/?'), # noqa + ('resource2', '(?Phttps?://(\w|\.|:|-)+)/(\w|-)+/(?P(\w|-)+)/(?P(\w|-)+)/?'), # noqa +]) def parse_tx_url(url): @@ -104,30 +104,70 @@ return "utf-8" -def make_request(method, host, url, username, password, fields=None): - if host.lower().startswith('https://'): - connection = urllib3.connection_from_url( - host, - cert_reqs=ssl.CERT_REQUIRED, - ca_certs=certs_file() - ) +def make_request(method, host, url, username, password, fields=None, + skip_decode=False): + + # Initialize http and https pool managers + num_pools = 1 + managers = {} + + if host.lower().startswith("http://"): + scheme = "http" + if "http_proxy" in os.environ: + proxy_url = os.environ["http_proxy"] + managers["http"] = urllib3.ProxyManager( + proxy_url=proxy_url, + proxy_headers={"User-Agent": user_agent_identifier()}, + num_pools=num_pools + ) + else: + managers["http"] = urllib3.PoolManager(num_pools=num_pools) + elif host.lower().startswith("https://"): + scheme = "https" + if "https_proxy" in os.environ: + proxy_url = os.environ["https_proxy"] + managers["https"] = urllib3.ProxyManager( + proxy_url=proxy_url, + proxy_headers={"User-Agent": user_agent_identifier()}, + num_pools=num_pools, + cert_reqs=CERT_REQUIRED, + ca_certs=certs_file() + ) + else: + managers["https"] = urllib3.PoolManager( + num_pools=num_pools, + cert_reqs=CERT_REQUIRED, + ca_certs=certs_file() + ) else: - connection = urllib3.connection_from_url(host) + raise Exception("Unknown scheme") + + charset = None headers = urllib3.util.make_headers( basic_auth='{0}:{1}'.format(username, password), accept_encoding=True, user_agent=user_agent_identifier(), keep_alive=True ) - r = None + + response = None try: - r = connection.request(method, url, headers=headers, fields=fields) - data = r.data - charset = determine_charset(r) - if isinstance(data, bytes): - data = data.decode(charset) - if r.status < 200 or r.status >= 400: - if r.status == 404: + manager = managers[scheme] + response = manager.request( + method, + host + url, + headers=dict(headers), + fields=fields + ) + data = response.data + if not skip_decode: + charset = determine_charset(response) + if isinstance(data, bytes): + data = data.decode(charset) + if response.status < 200 or response.status >= 400: + if response.status == 401: + raise HttpNotAuthorized(data) + elif response.status == 404: raise HttpNotFound(data) else: raise Exception(data) @@ -136,14 +176,14 @@ logger.error("Invalid SSL certificate") raise finally: - if r is not None: - r.close() + if response is not None: + response.close() def get_details(api_call, username, password, *args, **kwargs): """ Get the tx project info through the API. - + This function can also be used to check the existence of a project. """ url = API_URLS[api_call] % kwargs @@ -160,7 +200,7 @@ def valid_slug(slug): """ Check if a slug contains only valid characters. - + Valid chars include [-_\w] """ try: @@ -218,7 +258,7 @@ def confirm(prompt='Continue?', default=True): """ Prompt the user for a Yes/No answer. - + Args: prompt: The text displayed to the user ([Y/n] will be appended) default: If the default value will be yes or no @@ -254,7 +294,7 @@ This command can be used to colorify command line output. If the shell doesn't support this or the --disable-colors options has been set, it just returns the plain text. - + Usage: print "%s" % color_text("This text is red", "RED") """ @@ -268,7 +308,7 @@ def files_in_project(curpath): """ Iterate over the files in the project. - + Return each file under ``curpath`` with its absolute name. """ visited = set()