pax_global_header00006660000000000000000000000064145473242500014520gustar00rootroot0000000000000052 comment=b862a16b9d2d621e32ed26d84e75f18d21bc74e6 python-kanboard-1.1.5/000077500000000000000000000000001454732425000146245ustar00rootroot00000000000000python-kanboard-1.1.5/LICENSE000066400000000000000000000020661454732425000156350ustar00rootroot00000000000000The MIT License (MIT) Copyright (c) Frederic Guillot Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. python-kanboard-1.1.5/MANIFEST.in000066400000000000000000000000431454732425000163570ustar00rootroot00000000000000include README.rst include LICENSE python-kanboard-1.1.5/PKG-INFO000066400000000000000000000122041454732425000157200ustar00rootroot00000000000000Metadata-Version: 2.1 Name: kanboard Version: 1.1.5 Summary: Client library for Kanboard Home-page: https://github.com/kanboard/python-api-client Author: Frederic Guillot Author-email: fred@kanboard.net License: MIT Keywords: kanboard api client Classifier: Intended Audience :: Developers Classifier: Intended Audience :: Information Technology Classifier: Natural Language :: English Classifier: License :: OSI Approved :: MIT License Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 3.6 Classifier: Programming Language :: Python :: 3.7 Classifier: Programming Language :: Python :: 3.8 Classifier: Programming Language :: Python :: 3.9 Classifier: Programming Language :: Python :: 3.10 Classifier: Programming Language :: Python :: 3.11 License-File: LICENSE ============================== Python API Client for Kanboard ============================== Client library for Kanboard API. - Author: Frédéric Guillot - License: MIT Installation ============ .. code-block:: bash python3 -m pip install kanboard This library is compatible with Python >= 3.5. Note: **Support for Python 2.7 has been dropped since version 1.1.0.** On Fedora (36 and later), you can install the package using DNF: .. code-block:: bash dnf install python3-kanboard Examples ======== Methods and arguments are the same as the JSON-RPC procedures described in the `official documentation `_. Python methods are dynamically mapped to the API procedures: **You must use named arguments**. By default, calls are made synchronously, meaning that they will block the program until completed. Creating a new team project --------------------------- .. code-block:: python import kanboard kb = kanboard.Client('http://localhost/jsonrpc.php', 'jsonrpc', 'your_api_token') project_id = kb.create_project(name='My project') Authenticate as user -------------------- .. code-block:: python import kanboard kb = kanboard.Client('http://localhost/jsonrpc.php', 'admin', 'secret') kb.get_my_projects() Create a new task ----------------- .. code-block:: python import kanboard kb = kanboard.Client('http://localhost/jsonrpc.php', 'jsonrpc', 'your_api_token') project_id = kb.create_project(name='My project') task_id = kb.create_task(project_id=project_id, title='My task title') Use a personalized user agent ----------------------------- .. code-block:: python import kanboard kb = kanboard.Client(url='http://localhost/jsonrpc.php', username='admin', password='secret', user_agent='My Kanboard client') SSL connection and self-signed certificates =========================================== Example with a valid certificate: .. code-block:: python import kanboard kb = kanboard.Client('https://example.org/jsonrpc.php', 'admin', 'secret') kb.get_my_projects() Example with a custom certificate: .. code-block:: python import kanboard kb = kanboard.Client(url='https://example.org/jsonrpc.php', username='admin', password='secret', cafile='/path/to/my/cert.pem') kb.get_my_projects() Example with a custom certificate and hostname mismatch: .. code-block:: python import kanboard kb = kanboard.Client(url='https://example.org/jsonrpc.php', username='admin', password='secret', cafile='/path/to/my/cert.pem', ignore_hostname_verification=True) kb.get_my_projects() Ignore invalid/expired certificates and hostname mismatches, which will make your application vulnerable to man-in-the-middle (MitM) attacks: .. code-block:: python import kanboard kb = kanboard.Client(url='https://example.org/jsonrpc.php', username='admin', password='secret', insecure=True) kb.get_my_projects() Asynchronous I/O ================ The client also exposes async/await style method calls. Similarly to the synchronous calls (see above), the method names are mapped to the API methods. To invoke an asynchronous call, the method name must be appended with ``_async``. For example, a synchronous call to ``create_project`` can be made asynchronous by calling ``create_project_async`` instead. .. code-block:: python import asyncio import kanboard kb = kanboard.Client('http://localhost/jsonrpc.php', 'jsonrpc', 'your_api_token') loop = asyncio.get_event_loop() project_id = loop.run_until_complete(kb.create_project_async(name='My project')) .. code-block:: python import asyncio import kanboard async def call_within_function(): kb = kanboard.Client('http://localhost/jsonrpc.php', 'jsonrpc', 'your_api_token') return await kb.create_project_async(name='My project') loop = asyncio.get_event_loop() project_id = loop.run_until_complete(call_within_function()) See the `official API documentation `_ for the complete list of methods and arguments. python-kanboard-1.1.5/README.rst000066400000000000000000000105371454732425000163210ustar00rootroot00000000000000============================== Python API Client for Kanboard ============================== Client library for Kanboard API. - Author: Frédéric Guillot - License: MIT Installation ============ .. code-block:: bash python3 -m pip install kanboard This library is compatible with Python >= 3.5. Note: **Support for Python 2.7 has been dropped since version 1.1.0.** On Fedora (36 and later), you can install the package using DNF: .. code-block:: bash dnf install python3-kanboard Examples ======== Methods and arguments are the same as the JSON-RPC procedures described in the `official documentation `_. Python methods are dynamically mapped to the API procedures: **You must use named arguments**. By default, calls are made synchronously, meaning that they will block the program until completed. Creating a new team project --------------------------- .. code-block:: python import kanboard kb = kanboard.Client('http://localhost/jsonrpc.php', 'jsonrpc', 'your_api_token') project_id = kb.create_project(name='My project') Authenticate as user -------------------- .. code-block:: python import kanboard kb = kanboard.Client('http://localhost/jsonrpc.php', 'admin', 'secret') kb.get_my_projects() Create a new task ----------------- .. code-block:: python import kanboard kb = kanboard.Client('http://localhost/jsonrpc.php', 'jsonrpc', 'your_api_token') project_id = kb.create_project(name='My project') task_id = kb.create_task(project_id=project_id, title='My task title') Use a personalized user agent ----------------------------- .. code-block:: python import kanboard kb = kanboard.Client(url='http://localhost/jsonrpc.php', username='admin', password='secret', user_agent='My Kanboard client') SSL connection and self-signed certificates =========================================== Example with a valid certificate: .. code-block:: python import kanboard kb = kanboard.Client('https://example.org/jsonrpc.php', 'admin', 'secret') kb.get_my_projects() Example with a custom certificate: .. code-block:: python import kanboard kb = kanboard.Client(url='https://example.org/jsonrpc.php', username='admin', password='secret', cafile='/path/to/my/cert.pem') kb.get_my_projects() Example with a custom certificate and hostname mismatch: .. code-block:: python import kanboard kb = kanboard.Client(url='https://example.org/jsonrpc.php', username='admin', password='secret', cafile='/path/to/my/cert.pem', ignore_hostname_verification=True) kb.get_my_projects() Ignore invalid/expired certificates and hostname mismatches, which will make your application vulnerable to man-in-the-middle (MitM) attacks: .. code-block:: python import kanboard kb = kanboard.Client(url='https://example.org/jsonrpc.php', username='admin', password='secret', insecure=True) kb.get_my_projects() Asynchronous I/O ================ The client also exposes async/await style method calls. Similarly to the synchronous calls (see above), the method names are mapped to the API methods. To invoke an asynchronous call, the method name must be appended with ``_async``. For example, a synchronous call to ``create_project`` can be made asynchronous by calling ``create_project_async`` instead. .. code-block:: python import asyncio import kanboard kb = kanboard.Client('http://localhost/jsonrpc.php', 'jsonrpc', 'your_api_token') loop = asyncio.get_event_loop() project_id = loop.run_until_complete(kb.create_project_async(name='My project')) .. code-block:: python import asyncio import kanboard async def call_within_function(): kb = kanboard.Client('http://localhost/jsonrpc.php', 'jsonrpc', 'your_api_token') return await kb.create_project_async(name='My project') loop = asyncio.get_event_loop() project_id = loop.run_until_complete(call_within_function()) See the `official API documentation `_ for the complete list of methods and arguments. python-kanboard-1.1.5/kanboard.egg-info/000077500000000000000000000000001454732425000200775ustar00rootroot00000000000000python-kanboard-1.1.5/kanboard.egg-info/PKG-INFO000066400000000000000000000122041454732425000211730ustar00rootroot00000000000000Metadata-Version: 2.1 Name: kanboard Version: 1.1.5 Summary: Client library for Kanboard Home-page: https://github.com/kanboard/python-api-client Author: Frederic Guillot Author-email: fred@kanboard.net License: MIT Keywords: kanboard api client Classifier: Intended Audience :: Developers Classifier: Intended Audience :: Information Technology Classifier: Natural Language :: English Classifier: License :: OSI Approved :: MIT License Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 3.6 Classifier: Programming Language :: Python :: 3.7 Classifier: Programming Language :: Python :: 3.8 Classifier: Programming Language :: Python :: 3.9 Classifier: Programming Language :: Python :: 3.10 Classifier: Programming Language :: Python :: 3.11 License-File: LICENSE ============================== Python API Client for Kanboard ============================== Client library for Kanboard API. - Author: Frédéric Guillot - License: MIT Installation ============ .. code-block:: bash python3 -m pip install kanboard This library is compatible with Python >= 3.5. Note: **Support for Python 2.7 has been dropped since version 1.1.0.** On Fedora (36 and later), you can install the package using DNF: .. code-block:: bash dnf install python3-kanboard Examples ======== Methods and arguments are the same as the JSON-RPC procedures described in the `official documentation `_. Python methods are dynamically mapped to the API procedures: **You must use named arguments**. By default, calls are made synchronously, meaning that they will block the program until completed. Creating a new team project --------------------------- .. code-block:: python import kanboard kb = kanboard.Client('http://localhost/jsonrpc.php', 'jsonrpc', 'your_api_token') project_id = kb.create_project(name='My project') Authenticate as user -------------------- .. code-block:: python import kanboard kb = kanboard.Client('http://localhost/jsonrpc.php', 'admin', 'secret') kb.get_my_projects() Create a new task ----------------- .. code-block:: python import kanboard kb = kanboard.Client('http://localhost/jsonrpc.php', 'jsonrpc', 'your_api_token') project_id = kb.create_project(name='My project') task_id = kb.create_task(project_id=project_id, title='My task title') Use a personalized user agent ----------------------------- .. code-block:: python import kanboard kb = kanboard.Client(url='http://localhost/jsonrpc.php', username='admin', password='secret', user_agent='My Kanboard client') SSL connection and self-signed certificates =========================================== Example with a valid certificate: .. code-block:: python import kanboard kb = kanboard.Client('https://example.org/jsonrpc.php', 'admin', 'secret') kb.get_my_projects() Example with a custom certificate: .. code-block:: python import kanboard kb = kanboard.Client(url='https://example.org/jsonrpc.php', username='admin', password='secret', cafile='/path/to/my/cert.pem') kb.get_my_projects() Example with a custom certificate and hostname mismatch: .. code-block:: python import kanboard kb = kanboard.Client(url='https://example.org/jsonrpc.php', username='admin', password='secret', cafile='/path/to/my/cert.pem', ignore_hostname_verification=True) kb.get_my_projects() Ignore invalid/expired certificates and hostname mismatches, which will make your application vulnerable to man-in-the-middle (MitM) attacks: .. code-block:: python import kanboard kb = kanboard.Client(url='https://example.org/jsonrpc.php', username='admin', password='secret', insecure=True) kb.get_my_projects() Asynchronous I/O ================ The client also exposes async/await style method calls. Similarly to the synchronous calls (see above), the method names are mapped to the API methods. To invoke an asynchronous call, the method name must be appended with ``_async``. For example, a synchronous call to ``create_project`` can be made asynchronous by calling ``create_project_async`` instead. .. code-block:: python import asyncio import kanboard kb = kanboard.Client('http://localhost/jsonrpc.php', 'jsonrpc', 'your_api_token') loop = asyncio.get_event_loop() project_id = loop.run_until_complete(kb.create_project_async(name='My project')) .. code-block:: python import asyncio import kanboard async def call_within_function(): kb = kanboard.Client('http://localhost/jsonrpc.php', 'jsonrpc', 'your_api_token') return await kb.create_project_async(name='My project') loop = asyncio.get_event_loop() project_id = loop.run_until_complete(call_within_function()) See the `official API documentation `_ for the complete list of methods and arguments. python-kanboard-1.1.5/kanboard.egg-info/SOURCES.txt000066400000000000000000000002631454732425000217640ustar00rootroot00000000000000LICENSE MANIFEST.in README.rst kanboard.py setup.py kanboard.egg-info/PKG-INFO kanboard.egg-info/SOURCES.txt kanboard.egg-info/dependency_links.txt kanboard.egg-info/top_level.txtpython-kanboard-1.1.5/kanboard.egg-info/dependency_links.txt000066400000000000000000000000011454732425000241450ustar00rootroot00000000000000 python-kanboard-1.1.5/kanboard.egg-info/top_level.txt000066400000000000000000000000111454732425000226210ustar00rootroot00000000000000kanboard python-kanboard-1.1.5/kanboard.py000066400000000000000000000142151454732425000167620ustar00rootroot00000000000000# The MIT License (MIT) # # Copyright (c) Frederic Guillot # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. import json import base64 import functools import asyncio import ssl from typing import Dict, Optional from urllib import request as http DEFAULT_AUTH_HEADER = 'Authorization' ASYNC_FUNCNAME_MARKER = "_async" class ClientError(Exception): pass class Client: """ Kanboard API client Example: from kanboard import Client kb = Client(url="http://localhost/jsonrpc.php", username="jsonrpc", password="your_api_token") project_id = kb.create_project(name="My project") """ def __init__(self, url: str, username: str, password: str, auth_header: str = DEFAULT_AUTH_HEADER, cafile: Optional[str] = None, insecure: bool = False, ignore_hostname_verification: bool = False, user_agent: str = 'Kanboard Python API Client', loop: Optional[asyncio.AbstractEventLoop] = None): """ Constructor Args: url: API url endpoint username: API username or real username password: API token or user password auth_header: API HTTP header cafile: Path to a custom CA certificate insecure: Ignore SSL certificate errors and ignore hostname mismatches ignore_hostname_verification: Ignore SSL certificate hostname verification user_agent: Use a personalized user agent loop: An asyncio event loop. Default: asyncio.get_event_loop() """ self._url = url self._username = username self._password = password self._auth_header = auth_header self._cafile = cafile self._insecure = insecure self._user_agent = user_agent self._ignore_hostname_verification = ignore_hostname_verification if not loop: try: self._event_loop = asyncio.get_event_loop() except RuntimeError: self._event_loop = asyncio.new_event_loop() def __getattr__(self, name: str): if self.is_async_method_name(name): async def function(*args, **kwargs): return await self._event_loop.run_in_executor( None, functools.partial( self.execute, method=self._to_camel_case(self.get_funcname_from_async_name(name)), **kwargs)) return function else: def function(*args, **kwargs): return self.execute(method=self._to_camel_case(name), **kwargs) return function @staticmethod def is_async_method_name(funcname: str) -> bool: return funcname.endswith(ASYNC_FUNCNAME_MARKER) @staticmethod def get_funcname_from_async_name(funcname: str) -> str: return funcname[:len(funcname) - len(ASYNC_FUNCNAME_MARKER)] @staticmethod def _to_camel_case(snake_str: str) -> str: components = snake_str.split('_') return components[0] + ''.join(x.title() for x in components[1:]) @staticmethod def _parse_response(response: bytes): try: body = json.loads(response.decode(errors='ignore')) if 'error' in body: message = body.get('error').get('message') raise ClientError(message) return body.get('result') except ValueError: return None def _do_request(self, headers: Dict[str, str], body: Dict): try: request = http.Request(self._url, headers=headers, data=json.dumps(body).encode()) ssl_context = ssl.create_default_context(cafile=self._cafile) if self._insecure: ssl_context.check_hostname = False ssl_context.verify_mode = ssl.CERT_NONE if self._ignore_hostname_verification: ssl_context.check_hostname = False response = http.urlopen(request, context=ssl_context).read() except Exception as e: raise ClientError(str(e)) return self._parse_response(response) def execute(self, method: str, **kwargs): """ Call remote API procedure Args: method: Procedure name kwargs: Procedure named arguments Returns: Procedure result Raises: urllib.error.HTTPError: Any HTTP error (Python 3) """ payload = { 'id': 1, 'jsonrpc': '2.0', 'method': method, 'params': kwargs } credentials = base64.b64encode('{}:{}'.format(self._username, self._password).encode()) auth_header_prefix = 'Basic ' if self._auth_header == DEFAULT_AUTH_HEADER else '' headers = { self._auth_header: auth_header_prefix + credentials.decode(), 'Content-Type': 'application/json', 'User-Agent': self._user_agent, } return self._do_request(headers, payload) python-kanboard-1.1.5/setup.cfg000066400000000000000000000000461454732425000164450ustar00rootroot00000000000000[egg_info] tag_build = tag_date = 0 python-kanboard-1.1.5/setup.py000066400000000000000000000041361454732425000163420ustar00rootroot00000000000000# The MIT License (MIT) # # Copyright (c) Frederic Guillot # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. from setuptools import setup def readme(): with open('README.rst') as f: return f.read() setup( name='kanboard', version='1.1.5', description='Client library for Kanboard', long_description=readme(), keywords='kanboard api client', url='https://github.com/kanboard/python-api-client', author='Frederic Guillot', author_email='fred@kanboard.net', license='MIT', py_modules=['kanboard'], test_suite='test_kanboard', classifiers=[ 'Intended Audience :: Developers', 'Intended Audience :: Information Technology', 'Natural Language :: English', 'License :: OSI Approved :: MIT License', 'Programming Language :: Python', 'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.7', 'Programming Language :: Python :: 3.8', 'Programming Language :: Python :: 3.9', 'Programming Language :: Python :: 3.10', 'Programming Language :: Python :: 3.11', ] ) python-kanboard-1.1.5/test_kanboard.py000066400000000000000000000103271454732425000200210ustar00rootroot00000000000000# The MIT License (MIT) # # Copyright (c) Frederic Guillot # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. import unittest from unittest import mock import types import warnings import kanboard class TestClient(unittest.TestCase): def setUp(self): self.url = 'some api url' self.client = kanboard.Client(self.url, 'username', 'password') self.request, self.urlopen = self._create_mocks() def ignore_warnings(test_func): def do_test(self, *args, **kwargs): with warnings.catch_warnings(): warnings.simplefilter("ignore") test_func(self, *args, **kwargs) return do_test def test_api_call(self): body = b'{"jsonrpc": "2.0", "result": true, "id": 123}' self.urlopen.return_value.read.return_value = body self.assertEqual(True, self.client.remote_procedure()) self.request.assert_called_once_with(self.url, data=mock.ANY, headers=mock.ANY) def test_custom_auth_header(self): self.client._auth_header = 'X-Auth-Header' body = b'{"jsonrpc": "2.0", "result": true, "id": 123}' self.urlopen.return_value.read.return_value = body self.assertEqual(True, self.client.remote_procedure()) self.request.assert_called_once_with(self.url, data=mock.ANY, headers=mock.ANY) _, kwargs = self.request.call_args assert kwargs['headers']['X-Auth-Header'] == 'dXNlcm5hbWU6cGFzc3dvcmQ=' def test_http_error(self): self.urlopen.side_effect = Exception() with self.assertRaises(kanboard.ClientError): self.client.remote_procedure() def test_application_error(self): body = b'{"jsonrpc": "2.0", "error": {"code": -32603, "message": "Internal error"}, "id": 123}' self.urlopen.return_value.read.return_value = body with self.assertRaises(kanboard.ClientError, msg='Internal error'): self.client.remote_procedure() def test_async_method_call_recognised(self): method_name = "some_method_async" result = self.client.is_async_method_name(method_name) self.assertTrue(result) def test_standard_method_call_recognised(self): method_name = "some_method" result = self.client.is_async_method_name(method_name) self.assertFalse(result) def test_method_name_extracted_from_async_name(self): expected_method_name = "some_method" async_method_name = expected_method_name + "_async" result = self.client.get_funcname_from_async_name(async_method_name) self.assertEqual(expected_method_name, result) # suppress a RuntimeWarning because coro is not awaited # this is done on purpose @ignore_warnings def test_async_call_generates_coro(self): method = self.client.my_method_async() self.assertIsInstance(method, types.CoroutineType) @staticmethod def _create_mocks(): request_patcher = mock.patch('urllib.request.Request') urlopen_patcher = mock.patch('urllib.request.urlopen') return request_patcher.start(), urlopen_patcher.start()