From 2950cb7578b776597f0214f050cdc242f2b9dcdf Mon Sep 17 00:00:00 2001 From: Lukas Bednar Date: Fri, 25 Nov 2016 12:13:01 +0100 Subject: [PATCH 1/6] Fix JIRA(validate=True) option, issue #300 --- jira/client.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/jira/client.py b/jira/client.py index 7e175bdd2..5757c7f26 100644 --- a/jira/client.py +++ b/jira/client.py @@ -296,7 +296,12 @@ def __init__(self, server=None, options=None, basic_auth=None, oauth=None, jwt=N if validate: # This will raise an Exception if you are not allowed to login. # It's better to fail faster than later. - self.session() + user = self.session() + if user.raw is None: + auth_method = ( + oauth or basic_auth or jwt or kerberos or "anonymous" + ) + raise JIRAError("Can not log in with %s" % str(auth_method)) if get_server_info: # We need version in order to know what API calls are available or not From f35a7e77ddd9c64890053263f88a5d655462d14d Mon Sep 17 00:00:00 2001 From: William Orr Date: Tue, 27 Sep 2016 14:44:38 -0700 Subject: [PATCH 2/6] Allows users to specify timeouts for underlying requests session --- jira/client.py | 30 ++++++++++++++++-------------- jira/resilientsession.py | 5 +++-- 2 files changed, 19 insertions(+), 16 deletions(-) diff --git a/jira/client.py b/jira/client.py index fffca99b9..e78d679b8 100644 --- a/jira/client.py +++ b/jira/client.py @@ -190,7 +190,8 @@ class JIRA(object): AGILE_BASE_URL = GreenHopperResource.AGILE_BASE_URL def __init__(self, server=None, options=None, basic_auth=None, oauth=None, jwt=None, kerberos=False, - validate=False, get_server_info=True, async=False, logging=True, max_retries=3, proxies=None): + validate=False, get_server_info=True, async=False, logging=True, max_retries=3, proxies=None, + timeout=None): """Construct a JIRA client instance. Without any arguments, this client will connect anonymously to the JIRA instance @@ -235,6 +236,7 @@ def __init__(self, server=None, options=None, basic_auth=None, oauth=None, jwt=N :param get_server_info: If true it will fetch server version info first to determine if some API calls are available. :param async: To enable async requests for those actions where we implemented it, like issue update() or delete(). + :param timeout: Set a read/connect timeout for the underlying calls to JIRA (default: None) Obviously this means that you cannot rely on the return code when this is enabled. """ # force a copy of the tuple to be used in __del__() because @@ -274,17 +276,17 @@ def __init__(self, server=None, options=None, basic_auth=None, oauth=None, jwt=N self._try_magic() if oauth: - self._create_oauth_session(oauth) + self._create_oauth_session(oauth, timeout) elif basic_auth: - self._create_http_basic_session(*basic_auth) + self._create_http_basic_session(*basic_auth, timeout=timeout) self._session.headers.update(self._options['headers']) elif jwt: - self._create_jwt_session(jwt) + self._create_jwt_session(jwt, timeout) elif kerberos: - self._create_kerberos_session() + self._create_kerberos_session(timeout) else: verify = self._options['verify'] - self._session = ResilientSession() + self._session = ResilientSession(timeout=timeout) self._session.verify = verify self._session.headers.update(self._options['headers']) @@ -2032,14 +2034,14 @@ def kill_websudo(self): return self._session.delete(url) # Utilities - def _create_http_basic_session(self, username, password): + def _create_http_basic_session(self, username, password, timeout=None): verify = self._options['verify'] - self._session = ResilientSession() + self._session = ResilientSession(timeout=timeout) self._session.verify = verify self._session.auth = (username, password) self._session.cert = self._options['client_cert'] - def _create_oauth_session(self, oauth): + def _create_oauth_session(self, oauth, timeout): verify = self._options['verify'] from oauthlib.oauth1 import SIGNATURE_RSA @@ -2051,17 +2053,17 @@ def _create_oauth_session(self, oauth): signature_method=SIGNATURE_RSA, resource_owner_key=oauth['access_token'], resource_owner_secret=oauth['access_token_secret']) - self._session = ResilientSession() + self._session = ResilientSession(timeout) self._session.verify = verify self._session.auth = oauth - def _create_kerberos_session(self): + def _create_kerberos_session(self, timeout): verify = self._options['verify'] from requests_kerberos import HTTPKerberosAuth from requests_kerberos import OPTIONAL - self._session = ResilientSession() + self._session = ResilientSession(timeout=timeout) self._session.verify = verify self._session.auth = HTTPKerberosAuth(mutual_authentication=OPTIONAL) @@ -2072,7 +2074,7 @@ def _timestamp(dt=None): t += dt return calendar.timegm(t.timetuple()) - def _create_jwt_session(self, jwt): + def _create_jwt_session(self, jwt, timeout): try: jwt_auth = JWTAuth(jwt['secret'], alg='HS256') except NameError as e: @@ -2083,7 +2085,7 @@ def _create_jwt_session(self, jwt): jwt_auth.add_field("qsh", QshGenerator(self._options['context_path'])) for f in jwt['payload'].items(): jwt_auth.add_field(f[0], f[1]) - self._session = ResilientSession() + self._session = ResilientSession(timeout=timeout) self._session.verify = self._options['verify'] self._session.auth = jwt_auth diff --git a/jira/resilientsession.py b/jira/resilientsession.py index 4c192c361..2ce37f9ad 100644 --- a/jira/resilientsession.py +++ b/jira/resilientsession.py @@ -71,8 +71,9 @@ class ResilientSession(Session): At this moment it supports: 502, 503, 504 """ - def __init__(self): + def __init__(self, timeout=None): self.max_retries = 3 + self.timeout = timeout super(ResilientSession, self).__init__() # Indicate our preference for JSON to avoid https://bitbucket.org/bspeakmon/jira-python/issue/46 and https://jira.atlassian.com/browse/JRA-38551 @@ -119,7 +120,7 @@ def __verb(self, verb, url, retry_data=None, **kwargs): exception = None try: method = getattr(super(ResilientSession, self), verb.lower()) - response = method(url, **kwargs) + response = method(url, timeout=self.timeout, **kwargs) if response.status_code == 200: return response except ConnectionError as e: From 2e963eeb38f502e3714619ca15cb20fc3577edba Mon Sep 17 00:00:00 2001 From: Sorin Sbarnea Date: Sun, 22 Jan 2017 23:46:46 +0000 Subject: [PATCH 3/6] Enabled codecov.io and hidden coveralls.io Sem-Ver: patch --- .travis.yml | 1 + README.rst | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 12055213d..c569722c5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -21,6 +21,7 @@ script: - tox --installpkg ./dist/jira-*.whl --travis-after after_success: - coveralls +- bash <(curl -s https://codecov.io/bash) - requires.io update-site -t ac3bbcca32ae03237a6aae2b02eb9411045489bb -r notifications: email: diff --git a/README.rst b/README.rst index ba781869c..d07dc7fd0 100644 --- a/README.rst +++ b/README.rst @@ -25,8 +25,8 @@ JIRA Python Library .. image:: https://img.shields.io/pypi/status/jira.svg :target: https://pypi.python.org/pypi/jira/ -.. image:: https://img.shields.io/coveralls/pycontribs/jira.svg - :target: https://coveralls.io/r/pycontribs/jira +.. image:: https://codecov.io/gh/pycontribs/jira/branch/develop/graph/badge.svg + :target: https://codecov.io/gh/pycontribs/jira .. image:: https://img.shields.io/bountysource/team/pycontribs/activity.svg :target: https://www.bountysource.com/teams/pycontribs/issues?tracker_ids=3650997 From ad9ee18d9c754fe511a3ad61146b410ce62df694 Mon Sep 17 00:00:00 2001 From: Sorin Sbarnea Date: Sun, 22 Jan 2017 23:30:45 +0000 Subject: [PATCH 4/6] Fixed missing .egg_base in source distribution. Resolve #330 Sem-Ver: patch --- .gitignore | 1 + .travis.yml | 8 ++++---- setup.cfg | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/.gitignore b/.gitignore index 65ba6dab1..73124ac82 100644 --- a/.gitignore +++ b/.gitignore @@ -23,5 +23,6 @@ tests/test-reports-*/* **/*.log /.python-version /CHANGELOG +/ChangeLog /AUTHORS /tests/build diff --git a/.travis.yml b/.travis.yml index 12055213d..975cf7bab 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,7 +11,7 @@ python: - '3.6' install: - pip -q --log dist/pip.log install --upgrade pip setuptools tox-travis py wheel -- python setup.py install bdist_wheel +- python setup.py sdist bdist_wheel install - pip install ./dist/jira-*.whl - pip --version script: @@ -19,6 +19,8 @@ script: - export PACKAGE_VERSION=$(python setup.py --version) - python setup.py --version - tox --installpkg ./dist/jira-*.whl --travis-after +# validates that the build source distribution is installable using the old easy_install +- pip uninstall -y jira && easy_install ./dist/jira-*.tar.gz after_success: - coveralls - requires.io update-site -t ac3bbcca32ae03237a6aae2b02eb9411045489bb -r @@ -26,15 +28,13 @@ notifications: email: - pycontribs@googlegroups.com - sorin.sbarnea@gmail.com -before_deploy: -- echo "before deploy..." deploy: - provider: releases api_key: secure: gr9iOcQjdoAyUAim6FWKzJI9MBaJo9XKfGQGu7wdPXUFhg80Rp6GLJsowP+aU94NjXM1UQlVHDAy627WtjBlLH2SvmVEIIr7+UKBopBYuXG5jJ1m3wOZE+4f1Pqe9bqFc1DxgucqE8qF0sC24fIbNM2ToeyYrxrS6RoL2gRrX2I= file: - dist/$PACKAGE_NAME-$PACKAGE_VERSION* - - dist/CHANGELOG.md + - ChangeLog skip_cleanup: true on: tags: false diff --git a/setup.cfg b/setup.cfg index dd8f60eee..99aa1bdf5 100644 --- a/setup.cfg +++ b/setup.cfg @@ -40,7 +40,7 @@ pbr.config.drivers = plain = pbr.cfg.driver:Plain [egg_info] -egg_base = build +egg_base = . [aliases] test=pytest From 001e69f484a8b1d751d32bb9180b77a87fc3429d Mon Sep 17 00:00:00 2001 From: Sorin Sbarnea Date: Fri, 10 Feb 2017 18:11:34 +0000 Subject: [PATCH 5/6] Fixed version shield in readme --- README.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.rst b/README.rst index d07dc7fd0..76586278b 100644 --- a/README.rst +++ b/README.rst @@ -2,7 +2,7 @@ JIRA Python Library =================== -.. image:: https://img.shields.io/pypi/pyversions/jira.svg +.. image:: https://img.shields.io/pypi/v/jira.svg :target: https://pypi.python.org/pypi/jira/ .. image:: https://img.shields.io/pypi/l/jira.svg From 8f16cb82c88b2913db3fef4be2f874f3de356671 Mon Sep 17 00:00:00 2001 From: Sorin Sbarnea Date: Fri, 10 Feb 2017 18:12:08 +0000 Subject: [PATCH 6/6] Added back the jirashell command line entry point --- setup.cfg | 5 +++-- tests/tests.py | 7 +++++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/setup.cfg b/setup.cfg index 99aa1bdf5..cf8fba8bf 100644 --- a/setup.cfg +++ b/setup.cfg @@ -20,6 +20,7 @@ classifier = Programming Language :: Python :: 3 Programming Language :: Python :: 3.4 Programming Language :: Python :: 3.5 + Programming Language :: Python :: 3.6 Topic :: Software Development :: Libraries :: Python Modules Topic :: Internet :: WWW/HTTP @@ -36,8 +37,8 @@ packages = jira [entry_points] -pbr.config.drivers = - plain = pbr.cfg.driver:Plain +console_scripts = + jirashell = jira.jirashell:main [egg_info] egg_base = . diff --git a/tests/tests.py b/tests/tests.py index 3383f9840..a69906e45 100755 --- a/tests/tests.py +++ b/tests/tests.py @@ -2097,6 +2097,13 @@ def test_remove_user_from_group(self): self.jira.delete_user(self.test_username) +class JiraShellTests(unittest.TestCase): + + def test_jirashell_command_exists(self): + result = os.system('jirashell --help') + self.assertEqual(result, 0) + + if __name__ == '__main__': # when running tests we expect various errors and we don't want to display them by default