sky-api-client 3.3.0__tar.gz → 3.3.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. {sky_api_client-3.3.0 → sky_api_client-3.3.2}/PKG-INFO +3 -3
  2. {sky_api_client-3.3.0 → sky_api_client-3.3.2}/setup.py +3 -3
  3. sky_api_client-3.3.2/sky_api_client/common/tasks/asyncio.py +71 -0
  4. sky_api_client-3.3.2/sky_api_client/entity/__init__.py +0 -0
  5. sky_api_client-3.3.2/sky_api_client/entity/constituent_education.py +60 -0
  6. sky_api_client-3.3.2/sky_api_client/entity/education.py +59 -0
  7. sky_api_client-3.3.2/sky_api_client/exceptions/__init__.py +0 -0
  8. {sky_api_client-3.3.0 → sky_api_client-3.3.2}/sky_api_client/exceptions/exception.py +1 -11
  9. {sky_api_client-3.3.0 → sky_api_client-3.3.2}/sky_api_client.egg-info/PKG-INFO +3 -3
  10. {sky_api_client-3.3.0 → sky_api_client-3.3.2}/sky_api_client.egg-info/SOURCES.txt +3 -0
  11. sky_api_client-3.3.0/sky_api_client/entity/constituent_education.py +0 -7
  12. sky_api_client-3.3.0/sky_api_client/entity/education.py +0 -24
  13. {sky_api_client-3.3.0 → sky_api_client-3.3.2}/README.md +0 -0
  14. {sky_api_client-3.3.0 → sky_api_client-3.3.2}/pyproject.toml +0 -0
  15. {sky_api_client-3.3.0 → sky_api_client-3.3.2}/setup.cfg +0 -0
  16. {sky_api_client-3.3.0 → sky_api_client-3.3.2}/sky_api_client/__init__.py +0 -0
  17. {sky_api_client-3.3.0 → sky_api_client-3.3.2}/sky_api_client/client.py +0 -0
  18. {sky_api_client-3.3.0/sky_api_client/entity → sky_api_client-3.3.2/sky_api_client/common}/__init__.py +0 -0
  19. {sky_api_client-3.3.0/sky_api_client/exceptions → sky_api_client-3.3.2/sky_api_client/common/tasks}/__init__.py +0 -0
  20. {sky_api_client-3.3.0 → sky_api_client-3.3.2}/sky_api_client/entity/address.py +0 -0
  21. {sky_api_client-3.3.0 → sky_api_client-3.3.2}/sky_api_client/entity/base.py +0 -0
  22. {sky_api_client-3.3.0 → sky_api_client-3.3.2}/sky_api_client/entity/code_table.py +0 -0
  23. {sky_api_client-3.3.0 → sky_api_client-3.3.2}/sky_api_client/entity/constituent.py +0 -0
  24. {sky_api_client-3.3.0 → sky_api_client-3.3.2}/sky_api_client/entity/constituent_address.py +0 -0
  25. {sky_api_client-3.3.0 → sky_api_client-3.3.2}/sky_api_client/entity/constituent_code.py +0 -0
  26. {sky_api_client-3.3.0 → sky_api_client-3.3.2}/sky_api_client/entity/constituent_custom_field.py +0 -0
  27. {sky_api_client-3.3.0 → sky_api_client-3.3.2}/sky_api_client/entity/constituent_email_address.py +0 -0
  28. {sky_api_client-3.3.0 → sky_api_client-3.3.2}/sky_api_client/entity/constituent_online_presence.py +0 -0
  29. {sky_api_client-3.3.0 → sky_api_client-3.3.2}/sky_api_client/entity/constituent_phone.py +0 -0
  30. {sky_api_client-3.3.0 → sky_api_client-3.3.2}/sky_api_client/entity/constituent_relationship.py +0 -0
  31. {sky_api_client-3.3.0 → sky_api_client-3.3.2}/sky_api_client/entity/constituent_solicit_code.py +0 -0
  32. {sky_api_client-3.3.0 → sky_api_client-3.3.2}/sky_api_client/entity/custom_field.py +0 -0
  33. {sky_api_client-3.3.0 → sky_api_client-3.3.2}/sky_api_client/entity/custom_field_categories.py +0 -0
  34. {sky_api_client-3.3.0 → sky_api_client-3.3.2}/sky_api_client/entity/email_addresses.py +0 -0
  35. {sky_api_client-3.3.0 → sky_api_client-3.3.2}/sky_api_client/entity/event.py +0 -0
  36. {sky_api_client-3.3.0 → sky_api_client-3.3.2}/sky_api_client/entity/event_fee.py +0 -0
  37. {sky_api_client-3.3.0 → sky_api_client-3.3.2}/sky_api_client/entity/event_participant.py +0 -0
  38. {sky_api_client-3.3.0 → sky_api_client-3.3.2}/sky_api_client/entity/event_participant_donation.py +0 -0
  39. {sky_api_client-3.3.0 → sky_api_client-3.3.2}/sky_api_client/entity/event_participant_fee.py +0 -0
  40. {sky_api_client-3.3.0 → sky_api_client-3.3.2}/sky_api_client/entity/event_participant_fee_payment.py +0 -0
  41. {sky_api_client-3.3.0 → sky_api_client-3.3.2}/sky_api_client/entity/event_participant_levels.py +0 -0
  42. {sky_api_client-3.3.0 → sky_api_client-3.3.2}/sky_api_client/entity/event_participation_levels.py +0 -0
  43. {sky_api_client-3.3.0 → sky_api_client-3.3.2}/sky_api_client/entity/fundraising_appeal.py +0 -0
  44. {sky_api_client-3.3.0 → sky_api_client-3.3.2}/sky_api_client/entity/fundraising_campaign.py +0 -0
  45. {sky_api_client-3.3.0 → sky_api_client-3.3.2}/sky_api_client/entity/fundraising_fund.py +0 -0
  46. {sky_api_client-3.3.0 → sky_api_client-3.3.2}/sky_api_client/entity/fundraising_package.py +0 -0
  47. {sky_api_client-3.3.0 → sky_api_client-3.3.2}/sky_api_client/entity/gender.py +0 -0
  48. {sky_api_client-3.3.0 → sky_api_client-3.3.2}/sky_api_client/entity/gift.py +0 -0
  49. {sky_api_client-3.3.0 → sky_api_client-3.3.2}/sky_api_client/entity/gift_aid.py +0 -0
  50. {sky_api_client-3.3.0 → sky_api_client-3.3.2}/sky_api_client/entity/gift_batch.py +0 -0
  51. {sky_api_client-3.3.0 → sky_api_client-3.3.2}/sky_api_client/entity/gift_batch_gift.py +0 -0
  52. {sky_api_client-3.3.0 → sky_api_client-3.3.2}/sky_api_client/entity/gift_custom_field_values.py +0 -0
  53. {sky_api_client-3.3.0 → sky_api_client-3.3.2}/sky_api_client/entity/gift_custom_fields.py +0 -0
  54. {sky_api_client-3.3.0 → sky_api_client-3.3.2}/sky_api_client/entity/gift_subtype.py +0 -0
  55. {sky_api_client-3.3.0 → sky_api_client-3.3.2}/sky_api_client/entity/list.py +0 -0
  56. {sky_api_client-3.3.0 → sky_api_client-3.3.2}/sky_api_client/entity/online_presence.py +0 -0
  57. {sky_api_client-3.3.0 → sky_api_client-3.3.2}/sky_api_client/entity/phone.py +0 -0
  58. {sky_api_client-3.3.0 → sky_api_client-3.3.2}/sky_api_client/entity/registry.py +0 -0
  59. {sky_api_client-3.3.0 → sky_api_client-3.3.2}/sky_api_client/entity/relationship.py +0 -0
  60. {sky_api_client-3.3.0 → sky_api_client-3.3.2}/sky_api_client/entity/solicit_code.py +0 -0
  61. {sky_api_client-3.3.0 → sky_api_client-3.3.2}/sky_api_client/entity/suffix.py +0 -0
  62. {sky_api_client-3.3.0 → sky_api_client-3.3.2}/sky_api_client/entity/table_entry.py +0 -0
  63. {sky_api_client-3.3.0 → sky_api_client-3.3.2}/sky_api_client/entity/title.py +0 -0
  64. {sky_api_client-3.3.0 → sky_api_client-3.3.2}/sky_api_client/entity/webhook_subscription.py +0 -0
  65. {sky_api_client-3.3.0 → sky_api_client-3.3.2}/sky_api_client.egg-info/dependency_links.txt +0 -0
  66. {sky_api_client-3.3.0 → sky_api_client-3.3.2}/sky_api_client.egg-info/top_level.txt +0 -0
@@ -1,10 +1,10 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: sky_api_client
3
- Version: 3.3.0
3
+ Version: 3.3.2
4
4
  Summary: Python client for RENXT APIs
5
5
  Home-page: https://bitbucket.org/kalyanvarma/skyapi
6
- Author: Uddesh Jain
7
- Author-email: uddesh@almabase.com
6
+ Author: Rajeev K L
7
+ Author-email: rajeev@almabase.com
8
8
  License: UNKNOWN
9
9
  Description: # Sky Api Client
10
10
 
@@ -5,9 +5,9 @@ with open('README.md', 'r', encoding='utf-8') as fh:
5
5
 
6
6
  setuptools.setup(
7
7
  name='sky_api_client',
8
- version='3.3.0',
9
- author='Uddesh Jain',
10
- author_email='uddesh@almabase.com',
8
+ version='3.3.2',
9
+ author='Rajeev K L',
10
+ author_email='rajeev@almabase.com',
11
11
  description='Python client for RENXT APIs',
12
12
  long_description=long_description,
13
13
  long_description_content_type='text/markdown',
@@ -0,0 +1,71 @@
1
+ import abc
2
+ import asyncio
3
+ import functools
4
+ from typing import Any, Dict, List, Tuple
5
+
6
+
7
+ class BaseAsyncIOTask:
8
+ @classmethod
9
+ async def execute(cls, data: Dict = {}) -> Any:
10
+ """
11
+ Executes the async logic by awaiting the task logic
12
+ This function is mainly used by all async application logic to execute async logic
13
+ """
14
+ task = cls()
15
+ return await task.perform_task(**data)
16
+
17
+ @classmethod
18
+ def execute_sync(cls, data: Dict = {}) -> Any:
19
+ """This is used to run the asyncio task if any inside a synchronous code"""
20
+ task = cls()
21
+ # If there is an event loop already running, get it otherwise create a new event loop.
22
+ try:
23
+ loop = asyncio.get_event_loop()
24
+ result = loop.run_until_complete(task.perform_task(**data))
25
+ loop.close()
26
+ except RuntimeError:
27
+ loop = asyncio.new_event_loop()
28
+ asyncio.set_event_loop(loop)
29
+ result = loop.run_until_complete(task.perform_task(**data))
30
+ loop.close()
31
+ return result
32
+
33
+ @abc.abstractmethod
34
+ async def perform_task(self, **data) -> Any:
35
+ """
36
+ This function holds the logic of the async task which will be run on the event loop
37
+ """
38
+
39
+ raise NotImplementedError('Implement the logic for {}.'.format(self.__class__.__name__))
40
+
41
+
42
+ class BulkTaskExecutor(BaseAsyncIOTask):
43
+ @classmethod
44
+ def execute_sync(cls, data: Dict = {}) -> Any:
45
+ task = cls()
46
+
47
+ loop = asyncio.new_event_loop()
48
+ asyncio.set_event_loop(loop)
49
+ result = loop.run_until_complete(task.perform_task(**data))
50
+ loop.close()
51
+
52
+ return result
53
+
54
+ async def perform_task(self, task_list: List[Tuple] = None) -> List:
55
+ loop = asyncio.get_event_loop()
56
+ results = await asyncio.gather(
57
+ *[
58
+ asyncio.ensure_future(loop.run_in_executor(None, functools.partial(*task[0], **task[1])), loop=loop)
59
+ for task in task_list
60
+ ],
61
+ loop=loop,
62
+ return_exceptions=True,
63
+ )
64
+
65
+ # If there is exception in performing any task
66
+ # we pass that exception to the parent function instead of returning the results
67
+ for result in results:
68
+ if isinstance(result, Exception):
69
+ raise result
70
+
71
+ return [result for result in results]
File without changes
@@ -0,0 +1,60 @@
1
+ import re
2
+
3
+ import six
4
+ from sky_api_client.entity.base import Entity
5
+ from sky_api_client.entity.education import EducationCustomField
6
+ from sky_api_client.entity.registry import EntityRegistry
7
+ from sky_api_client.common.tasks.asyncio import BulkTaskExecutor
8
+
9
+
10
+ def slugify_underscore(name):
11
+ """Return slug for the given name i.e. replace any non alphanumeric character with underscore."""
12
+ if name is None or not isinstance(name, six.text_type):
13
+ return None
14
+
15
+ name = name.strip().lower()
16
+ # Any non word characters (letters, digits, and underscores) are replaced by '-'
17
+ name = re.sub(r'\W+', '_', name)
18
+ # Removing any trailing or leading dash
19
+ name = re.sub(r'^[-_]|[-_]$', '', name)
20
+ # Replace multiple continuous hipens with one
21
+ name = re.sub('[-_]+', '_', name)
22
+ return name
23
+
24
+
25
+ @EntityRegistry.register('constituent_education')
26
+ class ConstituentEducation(Entity):
27
+ LIST_URL = '/constituent/v1/constituents/{id}/educations'
28
+
29
+ def list(self, id=None, parent_id=None, params=None):
30
+ data = super().list(id=id, parent_id=parent_id, params=params)
31
+
32
+ pull_education_custom_fields = params.pop('pull_education_custom_fields', False)
33
+ if not pull_education_custom_fields:
34
+ return data
35
+
36
+ self.add_custom_fields_async(data)
37
+
38
+ return data
39
+
40
+ def add_custom_fields(self, education):
41
+ education_custom_fields = EducationCustomField(self._api).custom_fields(education_id=education['id'])
42
+ custom_fields = {}
43
+ for custom_field in education_custom_fields:
44
+ default_value = []
45
+ field_value = custom_fields.setdefault(slugify_underscore(custom_field['category']), default_value)
46
+ field_value.append(custom_field['value'])
47
+
48
+ for key, value in custom_fields.items():
49
+ education[key] = value if len(value) > 1 else value[0]
50
+
51
+ def add_custom_fields_async(self, data):
52
+ task_list = []
53
+ for education in data.get('value', []):
54
+ task_list.append(((self.add_custom_fields, education), {}))
55
+
56
+ return BulkTaskExecutor.execute_sync(
57
+ {
58
+ 'task_list': task_list,
59
+ }
60
+ )
@@ -0,0 +1,59 @@
1
+ from sky_api_client.entity.base import Entity
2
+ from sky_api_client.entity.registry import EntityRegistry
3
+ from sky_api_client.exceptions.exception import MethodNotDefined
4
+
5
+
6
+ @EntityRegistry.register('education')
7
+ class Education(Entity):
8
+ LIST_URL = '/constituent/v1/educations/'
9
+ CREATE_URL = '/constituent/v1/educations/'
10
+ GET_URL = '/constituent/v1/constituents/educations/{id}'
11
+ UPDATE_URL = '/constituent/v1/educations/{id}'
12
+ DELETE_URL = '/constituent/v1/educations/{id}'
13
+ SUBJECTS_URL = '/constituent/v1/educations/subjects'
14
+ DEGREES_URL = '/constituent/v1/educations/degrees'
15
+
16
+ def subjects(self):
17
+ if self.SUBJECTS_URL:
18
+ return self._api.request(method='GET', path=self.SUBJECTS_URL).get('value', [])
19
+ raise MethodNotDefined('subjects')
20
+
21
+ def degrees(self):
22
+ if self.DEGREES_URL:
23
+ return self._api.request(method='GET', path=self.DEGREES_URL).get('value', [])
24
+ raise MethodNotDefined('degrees')
25
+
26
+
27
+ @EntityRegistry.register('education_custom_field')
28
+ class EducationCustomField(Entity):
29
+ LIST_URL = 'constituent/v1/educations/customfields/categories/details?limit=5000'
30
+ CREATE_URL = 'constituent/v1/educations/customfields'
31
+ DELETE_URL = 'constituent/v1/educations/customfields/{custom_field_id}'
32
+ UPDATE_URL = 'constituent/v1/educations/customfields/{custom_field_id}'
33
+ CUSTOM_FIELDS_URL = 'constituent/v1/educations/{education_id}/customfields'
34
+ CUSTOM_FIELD_CATEGORIES_CODE_TABLE_URL = 'constituent/v1/educations/customfields/categories/values?category_name={}'
35
+
36
+ def list(self, id=None, parent_id=None, params=None, all=False):
37
+ data = super().list(id=id, parent_id=parent_id, params=params)
38
+ if not all:
39
+ return data
40
+ count = data['count']
41
+ while count > 5000:
42
+ params['offset'] = params.get('offset', 0) + 5000
43
+ data['value'] += super().list(id=id, parent_id=parent_id, params=params)['value']
44
+ count -= 5000
45
+ return data
46
+
47
+ def custom_fields(self, education_id):
48
+ if self.CUSTOM_FIELDS_URL:
49
+ return self._api.request(method='GET', path=self.CUSTOM_FIELDS_URL.format(education_id=education_id)).get(
50
+ 'value', []
51
+ )
52
+ raise MethodNotDefined('custom_fields')
53
+
54
+ def custom_field_categories_code_table(self, category_name):
55
+ if self.CUSTOM_FIELD_CATEGORIES_CODE_TABLE_URL:
56
+ return self._api.request(
57
+ method='GET', path=self.CUSTOM_FIELD_CATEGORIES_CODE_TABLE_URL.format(category_name)
58
+ ).get('value', [])
59
+ raise MethodNotDefined('custom_field_categories_code_table')
@@ -1,15 +1,5 @@
1
- import json
2
-
3
-
4
1
  class GeneralError(Exception):
5
- def __init__(self, text: str) -> None:
6
- try:
7
- json.loads(self.text)
8
- super().__init__(text)
9
- except json.JSONDecodeError as exc:
10
- super().__init__(
11
- [{'error_code': 500, 'error_name': 'JSONDecodeError', 'message': text, 'raw_message': exc.msg}]
12
- )
2
+ pass
13
3
 
14
4
 
15
5
  class MethodNotDefined(Exception):
@@ -1,10 +1,10 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: sky-api-client
3
- Version: 3.3.0
3
+ Version: 3.3.2
4
4
  Summary: Python client for RENXT APIs
5
5
  Home-page: https://bitbucket.org/kalyanvarma/skyapi
6
- Author: Uddesh Jain
7
- Author-email: uddesh@almabase.com
6
+ Author: Rajeev K L
7
+ Author-email: rajeev@almabase.com
8
8
  License: UNKNOWN
9
9
  Description: # Sky Api Client
10
10
 
@@ -7,6 +7,9 @@ sky_api_client.egg-info/PKG-INFO
7
7
  sky_api_client.egg-info/SOURCES.txt
8
8
  sky_api_client.egg-info/dependency_links.txt
9
9
  sky_api_client.egg-info/top_level.txt
10
+ sky_api_client/common/__init__.py
11
+ sky_api_client/common/tasks/__init__.py
12
+ sky_api_client/common/tasks/asyncio.py
10
13
  sky_api_client/entity/__init__.py
11
14
  sky_api_client/entity/address.py
12
15
  sky_api_client/entity/base.py
@@ -1,7 +0,0 @@
1
- from sky_api_client.entity.base import Entity
2
- from sky_api_client.entity.registry import EntityRegistry
3
-
4
-
5
- @EntityRegistry.register('constituent_education')
6
- class ConstituentEducation(Entity):
7
- LIST_URL = '/constituent/v1/constituents/{id}/educations'
@@ -1,24 +0,0 @@
1
- from sky_api_client.entity.base import Entity
2
- from sky_api_client.entity.registry import EntityRegistry
3
- from sky_api_client.exceptions.exception import MethodNotDefined
4
-
5
-
6
- @EntityRegistry.register('education')
7
- class Education(Entity):
8
- LIST_URL = '/constituent/v1/educations/'
9
- CREATE_URL = '/constituent/v1/educations/'
10
- GET_URL = '/constituent/v1/constituents/educations/{id}'
11
- UPDATE_URL = '/constituent/v1/educations/{id}'
12
- DELETE_URL = '/constituent/v1/educations/{id}'
13
- SUBJECTS_URL = '/constituent/v1/educations/subjects'
14
- DEGREES_URL = '/constituent/v1/educations/degrees'
15
-
16
- def subjects(self):
17
- if self.SUBJECTS_URL:
18
- return self._api.request(method='GET', path=self.SUBJECTS_URL).get('value', [])
19
- raise MethodNotDefined('subjects')
20
-
21
- def degrees(self):
22
- if self.DEGREES_URL:
23
- return self._api.request(method='GET', path=self.DEGREES_URL).get('value', [])
24
- raise MethodNotDefined('degrees')
File without changes
File without changes