python-sdk-local 0.0.51__tar.gz → 0.0.126__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 (30) hide show
  1. {python-sdk-local-0.0.51 → python_sdk_local-0.0.126}/PKG-INFO +7 -3
  2. python_sdk_local-0.0.126/README.md +11 -0
  3. python_sdk_local-0.0.126/pyproject.toml +12 -0
  4. {python-sdk-local-0.0.51 → python_sdk_local-0.0.126}/python_sdk_local.egg-info/PKG-INFO +7 -3
  5. python_sdk_local-0.0.126/python_sdk_local.egg-info/SOURCES.txt +18 -0
  6. python_sdk_local-0.0.126/python_sdk_local.egg-info/requires.txt +4 -0
  7. python_sdk_local-0.0.126/python_sdk_local.egg-info/top_level.txt +1 -0
  8. python_sdk_local-0.0.126/python_sdk_remote/src/constants.py +28 -0
  9. python_sdk_local-0.0.126/python_sdk_remote/src/http_response.py +139 -0
  10. {python-sdk-local-0.0.51/sdk → python_sdk_local-0.0.126/python_sdk_remote}/src/item.py +1 -2
  11. python_sdk_local-0.0.126/python_sdk_remote/src/mini_logger.py +131 -0
  12. {python-sdk-local-0.0.51/sdk → python_sdk_local-0.0.126/python_sdk_remote}/src/our_object.py +11 -12
  13. python_sdk_local-0.0.126/python_sdk_remote/src/unified_json.py +28 -0
  14. python_sdk_local-0.0.126/python_sdk_remote/src/utilities.py +441 -0
  15. python_sdk_local-0.0.126/python_sdk_remote/src/valid_json_versions.py +4 -0
  16. python_sdk_local-0.0.126/python_sdk_remote/src/validate_environment.py +48 -0
  17. python_sdk_local-0.0.126/setup.py +31 -0
  18. python-sdk-local-0.0.51/README.md +0 -21
  19. python-sdk-local-0.0.51/pyproject.toml +0 -18
  20. python-sdk-local-0.0.51/python_sdk_local.egg-info/SOURCES.txt +0 -15
  21. python-sdk-local-0.0.51/python_sdk_local.egg-info/top_level.txt +0 -1
  22. python-sdk-local-0.0.51/sdk/src/__init__.py +0 -0
  23. python-sdk-local-0.0.51/sdk/src/constants.py +0 -19
  24. python-sdk-local-0.0.51/sdk/src/mini_logger.py +0 -94
  25. python-sdk-local-0.0.51/sdk/src/utilities.py +0 -304
  26. python-sdk-local-0.0.51/sdk/src/validate.py +0 -18
  27. python-sdk-local-0.0.51/setup.py +0 -19
  28. {python-sdk-local-0.0.51 → python_sdk_local-0.0.126}/python_sdk_local.egg-info/dependency_links.txt +0 -0
  29. {python-sdk-local-0.0.51/sdk → python_sdk_local-0.0.126/python_sdk_remote/src}/__init__.py +0 -0
  30. {python-sdk-local-0.0.51 → python_sdk_local-0.0.126}/setup.cfg +0 -0
@@ -1,13 +1,17 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: python-sdk-local
3
- Version: 0.0.51
3
+ Version: 0.0.126
4
4
  Summary: PyPI Package for Circles Python SDK Local Python
5
- Home-page: https://github.com/circles
5
+ Home-page: https://github.com/circles-zone/python-sdk-remote-python-package
6
6
  Author: Circles
7
- Author-email: info@circles.life
7
+ Author-email: info@circlez.ai
8
8
  Classifier: Programming Language :: Python :: 3
9
9
  Classifier: License :: Other/Proprietary License
10
10
  Classifier: Operating System :: OS Independent
11
11
  Description-Content-Type: text/markdown
12
+ Requires-Dist: requests
13
+ Requires-Dist: python-dotenv
14
+ Requires-Dist: url-remote
15
+ Requires-Dist: pyjwt
12
16
 
13
17
  This is a package for sharing common functions used in different repositories
@@ -0,0 +1,11 @@
1
+ # TODO: rewrite with more example
2
+
3
+ In serverless, use this decorator:
4
+ ```py
5
+ from python_sdk_remote.http_response import handler_decorator
6
+ from logger_local.Logger import Logger
7
+ logger = Logger.create_logger(object=your_logger_object)
8
+ @handler_decorator(logger=logger)
9
+ def my_handler(request_parameters: dict) -> dict:
10
+ # here you can use both camelCase and snake_case keys from request_parameters
11
+ ```
@@ -0,0 +1,12 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61.0"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [tool.poetry]
6
+ name = "python-sdk-local"
7
+ version = "0.0.76" # https://pypi.org/project/python-sdk-local
8
+ description = "python-sdk-local Python Package"
9
+ readme = "README.md"
10
+ authors = [
11
+ "Circlez.ai <info@circlez.ai>",
12
+ ]
@@ -1,13 +1,17 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: python-sdk-local
3
- Version: 0.0.51
3
+ Version: 0.0.126
4
4
  Summary: PyPI Package for Circles Python SDK Local Python
5
- Home-page: https://github.com/circles
5
+ Home-page: https://github.com/circles-zone/python-sdk-remote-python-package
6
6
  Author: Circles
7
- Author-email: info@circles.life
7
+ Author-email: info@circlez.ai
8
8
  Classifier: Programming Language :: Python :: 3
9
9
  Classifier: License :: Other/Proprietary License
10
10
  Classifier: Operating System :: OS Independent
11
11
  Description-Content-Type: text/markdown
12
+ Requires-Dist: requests
13
+ Requires-Dist: python-dotenv
14
+ Requires-Dist: url-remote
15
+ Requires-Dist: pyjwt
12
16
 
13
17
  This is a package for sharing common functions used in different repositories
@@ -0,0 +1,18 @@
1
+ README.md
2
+ pyproject.toml
3
+ setup.py
4
+ python_sdk_local.egg-info/PKG-INFO
5
+ python_sdk_local.egg-info/SOURCES.txt
6
+ python_sdk_local.egg-info/dependency_links.txt
7
+ python_sdk_local.egg-info/requires.txt
8
+ python_sdk_local.egg-info/top_level.txt
9
+ python_sdk_remote/src/__init__.py
10
+ python_sdk_remote/src/constants.py
11
+ python_sdk_remote/src/http_response.py
12
+ python_sdk_remote/src/item.py
13
+ python_sdk_remote/src/mini_logger.py
14
+ python_sdk_remote/src/our_object.py
15
+ python_sdk_remote/src/unified_json.py
16
+ python_sdk_remote/src/utilities.py
17
+ python_sdk_remote/src/valid_json_versions.py
18
+ python_sdk_remote/src/validate_environment.py
@@ -0,0 +1,4 @@
1
+ requests
2
+ python-dotenv
3
+ url-remote
4
+ pyjwt
@@ -0,0 +1 @@
1
+ python_sdk_remote
@@ -0,0 +1,28 @@
1
+ import os
2
+
3
+ from logger_local.LoggerComponentEnum import LoggerComponentEnum
4
+
5
+ PYTHON_SDK_REMOTE_COMPONENT_ID = 184
6
+ PYTHON_SDK_REMOTE_COMPONENT_NAME = 'python_sdk_remote'
7
+
8
+ ENVIRONMENT_NAME = os.getenv("ENVIRONMENT_NAME")
9
+ BRAND_NAME = os.getenv("BRAND_NAME")
10
+ LOGZIO_TOKEN = os.getenv("LOGZIO_TOKEN")
11
+ # TODO Shall Can we use python-sdk function to get the value from Environment?
12
+ # TODO Shall we get the value from environment here of send the value to the function as @akiva-skolnik did?
13
+ GOOGLE_PORT_FOR_AUTHENTICATION = os.getenv("PORT_FOR_AUTHENTICATION")
14
+
15
+ OBJECT_TO_INSERT_CODE = {
16
+ 'component_id': PYTHON_SDK_REMOTE_COMPONENT_ID,
17
+ 'component_name': PYTHON_SDK_REMOTE_COMPONENT_NAME,
18
+ 'component_category': LoggerComponentEnum.ComponentCategory.Code.value,
19
+ 'developer_email': 'sahar.g@circ.zone'
20
+ }
21
+
22
+ OBJECT_TO_INSERT_TEST = {
23
+ 'component_id': PYTHON_SDK_REMOTE_COMPONENT_ID,
24
+ 'component_name': PYTHON_SDK_REMOTE_COMPONENT_NAME,
25
+ 'component_category': LoggerComponentEnum.ComponentCategory.Unit_Test.value,
26
+ 'testing_framework': LoggerComponentEnum.testingFramework.pytest.value,
27
+ 'developer_email': 'sahar.g@circ.zone'
28
+ }
@@ -0,0 +1,139 @@
1
+ import traceback
2
+ from functools import wraps
3
+ from http import HTTPStatus
4
+ from typing import Any
5
+
6
+ from .mini_logger import MiniLogger as logger
7
+ from .utilities import camel_to_snake, snake_to_camel, to_dict, to_json
8
+
9
+ HEADERS_KEY = 'headers'
10
+ AUTHORIZATION_KEY = 'authorization'
11
+ AUTHORIZATION_PREFIX = 'Bearer '
12
+
13
+
14
+ # TODO Align those methods with typescript-sdk https://github.com/circles-zone/typescript-sdk-remote-typescript-package/blob/dev/typescript-sdk/src/utils/index.ts
15
+ # TODO Shall we create also createInternalServerErrorHttpResponse(), createOkHttpResponse() like we have in TypeScript?
16
+
17
+ # TODO: add handler wrapper?
18
+
19
+ def get_payload_dict_from_event(event: dict) -> dict:
20
+ """Extracts params sent with payload"""
21
+ return to_dict(event.get('body'))
22
+
23
+
24
+ def get_path_parameters_dict_from_event(event: dict) -> dict:
25
+ """Extracts params sent implicitly: `url/param?test=5` -> param
26
+ (when the path is defined with /{param})"""
27
+ return event.get('pathParameters') or {}
28
+
29
+
30
+ def get_query_string_parameters_from_event(event: dict) -> dict:
31
+ """Extracts params sent explicitly: `url/test?a=1&b=2` -> {'a': '1', 'b': '2'}"""
32
+ return event.get("queryStringParameters") or {} # params sent with ?a=1&b=2
33
+
34
+
35
+ def get_request_parameters_from_event(event: dict) -> dict:
36
+ """Extracts all params from the event object.
37
+ The order of precedence is: payload > path > query string
38
+ returns a dictionary with all the parameters, with both camelCase and snake_case keys."""
39
+ all_params = get_payload_dict_from_event(event)
40
+ all_params.update(get_path_parameters_dict_from_event(event))
41
+ all_params.update(get_query_string_parameters_from_event(event))
42
+ all_params = {camel_to_snake(key): value for key, value in all_params.items()}
43
+ all_params.update({snake_to_camel(key): value for key, value in all_params.items()})
44
+ return all_params
45
+
46
+
47
+ # TODO: test
48
+ def handler_decorator(logger):
49
+ """Decorator for AWS Lambda handler functions. It wraps the handler function with logging and error handling.
50
+ Usage:
51
+ from python_sdk_remote.http_response import handler_decorator
52
+ logger = ...
53
+ @handler_decorator(logger=logger)
54
+ def my_handler(request_parameters: dict) -> dict:
55
+ return {"message": "Hello, World!"}"""
56
+
57
+ def decorator(handler: callable) -> callable:
58
+ @wraps(handler)
59
+ def wrapper(event, context):
60
+ handler_response = None
61
+ try:
62
+ logger.start(object={"event": event, "context": context})
63
+ request_parameters = get_request_parameters_from_event(event)
64
+ body_result: dict = handler(request_parameters)
65
+ handler_response = create_ok_http_response(body_result)
66
+ except Exception as e:
67
+ handler_response = create_error_http_response(e)
68
+ finally:
69
+ logger.end(object={"handler_response": handler_response})
70
+ return handler_response
71
+
72
+ return wrapper
73
+
74
+ return decorator
75
+
76
+
77
+ # TODO: should we auto detect user_jwt if not provided?
78
+ def create_authorization_http_headers(user_jwt: str) -> dict:
79
+ logger.start(object={"user_jwt": user_jwt})
80
+ authorization_http_headers = {
81
+ 'Content-Type': 'application/json',
82
+ 'Authorization': AUTHORIZATION_PREFIX + user_jwt,
83
+ }
84
+ logger.end(object={"authorization_http_headers": authorization_http_headers})
85
+ return authorization_http_headers
86
+
87
+
88
+ def get_user_jwt_from_event(event: dict) -> str:
89
+ logger.start(object={"event": event})
90
+ auth_header = event.get(HEADERS_KEY, {}).get(AUTHORIZATION_KEY)
91
+ if auth_header is None:
92
+ auth_header = event.get(HEADERS_KEY, {}).get(AUTHORIZATION_KEY.capitalize())
93
+ user_jwt = auth_header.split(AUTHORIZATION_PREFIX)[1]
94
+ logger.end(object={"user_jwt": user_jwt})
95
+ return user_jwt
96
+
97
+
98
+ def create_return_http_headers() -> dict:
99
+ logger.start()
100
+ return_http_headers = {
101
+ "Content-Type": "application/json",
102
+ "Access-Control-Allow-Origin": "*",
103
+ }
104
+ logger.end(object={"return_http_headers": return_http_headers})
105
+ return return_http_headers
106
+
107
+
108
+ def create_error_http_response(exception: Exception, status_code: HTTPStatus = HTTPStatus.BAD_REQUEST) -> dict:
109
+ logger.start(object={"exception": exception})
110
+ error_http_response = {
111
+ "statusCode": status_code.value,
112
+ "headers": create_return_http_headers(),
113
+ "body": create_http_body({"error": str(exception)}),
114
+ "traceback": traceback.format_exc()
115
+ }
116
+ logger.end(object={"error_http_response": error_http_response})
117
+ return error_http_response
118
+
119
+
120
+ def create_ok_http_response(body: Any) -> dict:
121
+ logger.start(object={"body": body})
122
+ # TODO: test sending statusCode/headers/body inside the body
123
+ ok_http_response = {
124
+ "statusCode": body.get("statusCode") or HTTPStatus.OK.value,
125
+ "headers": body.get("headers") or create_return_http_headers(),
126
+ "body": create_http_body(body.get("body") or body)
127
+ }
128
+ logger.end(object={"ok_http_response": ok_http_response})
129
+ return ok_http_response
130
+
131
+
132
+ # https://google.github.io/styleguide/jsoncstyleguide.xml?showone=Property_Name_Format#Property_Name_Format
133
+ def create_http_body(body: Any) -> str:
134
+ # TODO console.warning() if the body is not a valid camelCase JSON
135
+ # https://stackoverflow.com/questions/17156078/converting-identifier-naming-between-camelcase-and-underscores-during-json-seria
136
+ logger.start(object={"body": body})
137
+ http_body = to_json(body)
138
+ logger.end(object={"http_body": http_body})
139
+ return http_body
@@ -1,13 +1,12 @@
1
1
  from abc import abstractmethod
2
+
2
3
  from .our_object import OurObject
3
4
 
4
5
 
5
6
  class Item(OurObject):
6
-
7
7
  def __init__(self, **kwargs):
8
8
  super().__init__(**kwargs)
9
9
 
10
10
  @abstractmethod
11
11
  def get_id(self):
12
12
  raise NotImplementedError("Subclasses must implement the 'get_id' method.")
13
-
@@ -0,0 +1,131 @@
1
+ import logging
2
+ import os
3
+ import sys
4
+
5
+ LOGGER_MINIMUM_SEVERITY = os.getenv("LOGGER_MINIMUM_SEVERITY", "INFO").upper()
6
+ # logging expects NOTSET/DEBUG/INFO/WARNING/ERROR/FATAL/CRITICAL
7
+ if LOGGER_MINIMUM_SEVERITY.isdigit():
8
+ logger_minimum_severity = int(LOGGER_MINIMUM_SEVERITY)
9
+ # Values from Logger.MessageSeverity
10
+ if logger_minimum_severity < 400:
11
+ LOGGER_MINIMUM_SEVERITY = "DEBUG"
12
+ elif logger_minimum_severity < 600:
13
+ LOGGER_MINIMUM_SEVERITY = "INFO"
14
+ elif logger_minimum_severity < 700:
15
+ LOGGER_MINIMUM_SEVERITY = "WARNING"
16
+ elif logger_minimum_severity < 800:
17
+ LOGGER_MINIMUM_SEVERITY = "ERROR"
18
+ else:
19
+ LOGGER_MINIMUM_SEVERITY = "CRITICAL"
20
+
21
+ logging.basicConfig(level=LOGGER_MINIMUM_SEVERITY, stream=sys.stdout,
22
+ format="%(asctime)s - %(message)s")
23
+ logger = logging.getLogger(__name__)
24
+
25
+
26
+ class MiniLogger:
27
+ # TODO Can we so one generic function call by all
28
+
29
+ @staticmethod
30
+ def start(message: str = "", object: dict = None):
31
+ """
32
+ Print a log message with the current time.
33
+
34
+ Parameters:
35
+ message (str): The message to be printed.
36
+ object (dict): The object to be printed.
37
+ """
38
+ if object is None:
39
+ logger.debug(f"START - {message}")
40
+ else:
41
+ logger.debug(f"START - {message} - {object}")
42
+
43
+ @staticmethod
44
+ def end(message: str = "", object: dict = None):
45
+ """
46
+ Print a log message with the current time.
47
+
48
+ Parameters:
49
+ message (str): The message to be printed.
50
+ """
51
+ if object is None:
52
+ logger.debug(f"END - {message}")
53
+ else:
54
+ logger.debug(f"END - {message} - {object}")
55
+
56
+ @staticmethod
57
+ def debug(message: str = "", object: dict = None):
58
+ """
59
+ Print a log message with the current time.
60
+
61
+ Parameters:
62
+ message (str): The message to be printed.
63
+ object (dict): The object to be printed.
64
+ """
65
+ if object is None:
66
+ logger.debug(f"DEBUG - {message}")
67
+ else:
68
+ logger.debug(f"DEBUG {message} - {object}")
69
+
70
+ @staticmethod
71
+ def info(message: str = "", object: dict = None):
72
+ """
73
+ Print a log message with the current time.
74
+
75
+ Parameters:
76
+ message (str): The message to be printed.
77
+ object (dict): The object to be printed.
78
+ """
79
+ if object is None:
80
+ logger.info(f"INFO - {message}")
81
+ else:
82
+ logger.info(f"INFO {message} - {object}")
83
+
84
+ @staticmethod
85
+ def warning(message: str = "", object: dict = None):
86
+ """
87
+ Print a log message with the current time.
88
+
89
+ Parameters:
90
+ message (str): The message to be printed.
91
+ object (dict): The object to be printed.
92
+ """
93
+ if object is None:
94
+ logger.warning(f"WARNING - {message}")
95
+ else:
96
+ logger.warning(f"WARNING {message} - {object}")
97
+
98
+ @staticmethod
99
+ def error(message: str = "", object: dict = None):
100
+ """
101
+ Print a log error message with the current time.
102
+
103
+ Parameters:
104
+ message (str): The message to be printed.
105
+ object (dict): The object to be printed.
106
+ """
107
+ if object is None:
108
+ logger.error(f"ERROR - {message}")
109
+ else:
110
+ logger.error(f"ERROR - {message} - {object}")
111
+
112
+ @staticmethod
113
+ def exception(message: str = "", object: Exception or dict = None):
114
+ """
115
+ Print a log error message with the current time.
116
+
117
+ Parameters:
118
+ message (str): The message to be printed.
119
+ object (dict / Exception): The object / Exception to be printed.
120
+ """
121
+ if isinstance(object, Exception):
122
+ exception = object
123
+ elif isinstance(object, dict):
124
+ exception = object.get("exception")
125
+ else:
126
+ exception = None
127
+
128
+ if object is None:
129
+ logger.exception(f"EXCEPTION - {message}")
130
+ else:
131
+ logger.exception(f"EXCEPTION- {message} - {object}", exc_info=exception)
@@ -1,19 +1,11 @@
1
- from __future__ import annotations
2
1
  import json
3
- import sys
4
- import os
5
- from dotenv import load_dotenv
6
- sys.path.append(os.getcwd())
7
- from .constants import * # noqa: E402
8
- load_dotenv()
9
- from logger_local.Logger import Logger # noqa: E402
10
- from abc import ABC, abstractmethod # noqa: E402
2
+ from abc import ABC, abstractmethod
11
3
 
12
- logger = Logger.create_logger(object=OBJECT_TO_INSERT_CODE)
4
+ from .mini_logger import MiniLogger as logger
13
5
 
14
6
 
7
+ # TODO Where are we using it? Shall we extend the usage of OurObject as the father of all our entities?
15
8
  class OurObject(ABC):
16
-
17
9
  def __init__(self, **kwargs):
18
10
  INIT_METHOD_NAME = '__init__'
19
11
  logger.start(INIT_METHOD_NAME, object={'kwargs': kwargs})
@@ -22,10 +14,12 @@ class OurObject(ABC):
22
14
 
23
15
  @abstractmethod
24
16
  def get_name(self):
17
+ """Returns the name of the object"""
25
18
  raise NotImplementedError(
26
19
  "Subclasses must implement the 'get_name' method.")
27
20
 
28
21
  def get(self, attr_name: str):
22
+ """Returns the value of the attribute with the given name"""
29
23
  GET_METHOD_NAME = 'get'
30
24
  logger.start(GET_METHOD_NAME, object={'attr_name': attr_name})
31
25
  arguments = getattr(self, 'kwargs', None)
@@ -34,12 +28,15 @@ class OurObject(ABC):
34
28
  return value
35
29
 
36
30
  def get_all_arguments(self):
31
+ """Returns all the arguments passed to the constructor as a dictionary"""
37
32
  return getattr(self, 'kwargs', None)
38
33
 
39
34
  def to_json(self) -> str:
35
+ """Returns a json string representation of this object"""
40
36
  return json.dumps(self.__dict__)
41
37
 
42
- def from_json(self, json_string: str) -> OurObject:
38
+ def from_json(self, json_string: str) -> 'OurObject':
39
+ """Returns an instance of the class from a json string"""
43
40
  FROM_JSON_METHOD_NAME = 'from_json'
44
41
  logger.start(FROM_JSON_METHOD_NAME,
45
42
  object={'json_string': json_string})
@@ -49,9 +46,11 @@ class OurObject(ABC):
49
46
  return self
50
47
 
51
48
  def __eq__(self, other) -> bool:
49
+ """Checks if two objects are equal"""
52
50
  if not isinstance(other, OurObject):
53
51
  return False
54
52
  return self.__dict__ == other.__dict__
55
53
 
56
54
  def __ne__(self, other) -> bool:
55
+ """Checks if two objects are not equal"""
57
56
  return not self.__eq__(other)
@@ -0,0 +1,28 @@
1
+ from .valid_json_versions import valid_json_versions
2
+
3
+
4
+ # TODO Shall we merge it with the machine-learning-unified-json?
5
+ class UnifiedJson:
6
+ def __init__(self, data: dict, json_version: str):
7
+ if json_version not in valid_json_versions:
8
+ raise Exception(
9
+ f"version {json_version} is not in valid_json_versions {valid_json_versions}, "
10
+ f"please make sure you run sql2code."
11
+ )
12
+ self.json_version = json_version
13
+ self.data = data
14
+
15
+ def get_unified_json(self):
16
+ return {"version": self.json_version, "data": self.data}
17
+
18
+ def get_data(self):
19
+ return self.data
20
+
21
+ def get_json_version(self):
22
+ return self.json_version
23
+
24
+ def __str__(self):
25
+ return self.get_unified_json()
26
+
27
+ def __repr__(self):
28
+ return self.__str__()