MambuPy 2.1.0__tar.gz → 2.2.1__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 (132) hide show
  1. {mambupy-2.1.0 → mambupy-2.2.1}/MambuPy/__init__.py +2 -4
  2. {mambupy-2.1.0/mambupy → mambupy-2.2.1/MambuPy}/api/connector/rest.py +81 -23
  3. {mambupy-2.1.0/mambupy → mambupy-2.2.1/MambuPy}/mambuconfig.py +12 -13
  4. {mambupy-2.1.0/mambupy → mambupy-2.2.1/MambuPy}/mambuutil.py +16 -62
  5. {mambupy-2.1.0/mambupy → mambupy-2.2.1/MambuPy}/orm/schema_groups.py +3 -4
  6. {mambupy-2.1.0/mambupy → mambupy-2.2.1/MambuPy}/orm/schema_orm.py +0 -2
  7. mambupy-2.2.1/MambuPy/rest/__init__.py +31 -0
  8. mambupy-2.2.1/MambuPy/rest/mambuactivity.py +744 -0
  9. {mambupy-2.1.0 → mambupy-2.2.1}/MambuPy.egg-info/PKG-INFO +5 -4
  10. {mambupy-2.1.0 → mambupy-2.2.1}/MambuPy.egg-info/SOURCES.txt +0 -34
  11. {mambupy-2.1.0 → mambupy-2.2.1}/MambuPy.egg-info/requires.txt +1 -1
  12. {mambupy-2.1.0 → mambupy-2.2.1}/PKG-INFO +5 -4
  13. {mambupy-2.1.0 → mambupy-2.2.1}/mambupy/__init__.py +2 -4
  14. {mambupy-2.1.0/MambuPy → mambupy-2.2.1/mambupy}/api/connector/rest.py +81 -23
  15. {mambupy-2.1.0/MambuPy → mambupy-2.2.1/mambupy}/mambuconfig.py +12 -13
  16. {mambupy-2.1.0/MambuPy → mambupy-2.2.1/mambupy}/mambuutil.py +16 -62
  17. {mambupy-2.1.0/MambuPy → mambupy-2.2.1/mambupy}/orm/schema_groups.py +3 -4
  18. {mambupy-2.1.0/MambuPy → mambupy-2.2.1/mambupy}/orm/schema_orm.py +0 -2
  19. mambupy-2.2.1/mambupy/rest/__init__.py +31 -0
  20. mambupy-2.2.1/mambupy/rest/mambuactivity.py +744 -0
  21. {mambupy-2.1.0 → mambupy-2.2.1}/pyproject.toml +8 -3
  22. mambupy-2.1.0/MambuPy/rest/__init__.py +0 -49
  23. mambupy-2.1.0/MambuPy/rest/mambuactivity.py +0 -87
  24. mambupy-2.1.0/MambuPy/rest/mambubranch.py +0 -122
  25. mambupy-2.1.0/MambuPy/rest/mambucentre.py +0 -104
  26. mambupy-2.1.0/MambuPy/rest/mambuclient.py +0 -317
  27. mambupy-2.1.0/MambuPy/rest/mambugroup.py +0 -372
  28. mambupy-2.1.0/MambuPy/rest/mambuloan.py +0 -687
  29. mambupy-2.1.0/MambuPy/rest/mambuproduct.py +0 -180
  30. mambupy-2.1.0/MambuPy/rest/mamburepayment.py +0 -99
  31. mambupy-2.1.0/MambuPy/rest/mamburestutils.py +0 -119
  32. mambupy-2.1.0/MambuPy/rest/mamburoles.py +0 -98
  33. mambupy-2.1.0/MambuPy/rest/mambusaving.py +0 -114
  34. mambupy-2.1.0/MambuPy/rest/mambusavingfundingrepayment.py +0 -94
  35. mambupy-2.1.0/MambuPy/rest/mambusavingtransaction.py +0 -163
  36. mambupy-2.1.0/MambuPy/rest/mambustruct.py +0 -1066
  37. mambupy-2.1.0/MambuPy/rest/mambutask.py +0 -163
  38. mambupy-2.1.0/MambuPy/rest/mambutransaction.py +0 -103
  39. mambupy-2.1.0/MambuPy/rest/mambutransactionchannel.py +0 -101
  40. mambupy-2.1.0/MambuPy/rest/mambuuser.py +0 -229
  41. mambupy-2.1.0/mambupy/rest/__init__.py +0 -49
  42. mambupy-2.1.0/mambupy/rest/mambuactivity.py +0 -87
  43. mambupy-2.1.0/mambupy/rest/mambubranch.py +0 -122
  44. mambupy-2.1.0/mambupy/rest/mambucentre.py +0 -104
  45. mambupy-2.1.0/mambupy/rest/mambuclient.py +0 -317
  46. mambupy-2.1.0/mambupy/rest/mambugroup.py +0 -372
  47. mambupy-2.1.0/mambupy/rest/mambuloan.py +0 -687
  48. mambupy-2.1.0/mambupy/rest/mambuproduct.py +0 -180
  49. mambupy-2.1.0/mambupy/rest/mamburepayment.py +0 -99
  50. mambupy-2.1.0/mambupy/rest/mamburestutils.py +0 -119
  51. mambupy-2.1.0/mambupy/rest/mamburoles.py +0 -98
  52. mambupy-2.1.0/mambupy/rest/mambusaving.py +0 -114
  53. mambupy-2.1.0/mambupy/rest/mambusavingfundingrepayment.py +0 -94
  54. mambupy-2.1.0/mambupy/rest/mambusavingtransaction.py +0 -163
  55. mambupy-2.1.0/mambupy/rest/mambustruct.py +0 -1066
  56. mambupy-2.1.0/mambupy/rest/mambutask.py +0 -163
  57. mambupy-2.1.0/mambupy/rest/mambutransaction.py +0 -103
  58. mambupy-2.1.0/mambupy/rest/mambutransactionchannel.py +0 -101
  59. mambupy-2.1.0/mambupy/rest/mambuuser.py +0 -229
  60. {mambupy-2.1.0 → mambupy-2.2.1}/LICENSE +0 -0
  61. {mambupy-2.1.0 → mambupy-2.2.1}/MambuPy/api/__init__.py +0 -0
  62. {mambupy-2.1.0 → mambupy-2.2.1}/MambuPy/api/classes.py +0 -0
  63. {mambupy-2.1.0 → mambupy-2.2.1}/MambuPy/api/connector/__init__.py +0 -0
  64. {mambupy-2.1.0 → mambupy-2.2.1}/MambuPy/api/connector/mambuconnector.py +0 -0
  65. {mambupy-2.1.0 → mambupy-2.2.1}/MambuPy/api/entities.py +0 -0
  66. {mambupy-2.1.0 → mambupy-2.2.1}/MambuPy/api/interfaces.py +0 -0
  67. {mambupy-2.1.0 → mambupy-2.2.1}/MambuPy/api/mambubranch.py +0 -0
  68. {mambupy-2.1.0 → mambupy-2.2.1}/MambuPy/api/mambucentre.py +0 -0
  69. {mambupy-2.1.0 → mambupy-2.2.1}/MambuPy/api/mambuclient.py +0 -0
  70. {mambupy-2.1.0 → mambupy-2.2.1}/MambuPy/api/mambucustomfield.py +0 -0
  71. {mambupy-2.1.0 → mambupy-2.2.1}/MambuPy/api/mambugroup.py +0 -0
  72. {mambupy-2.1.0 → mambupy-2.2.1}/MambuPy/api/mambuloan.py +0 -0
  73. {mambupy-2.1.0 → mambupy-2.2.1}/MambuPy/api/mambuproduct.py +0 -0
  74. {mambupy-2.1.0 → mambupy-2.2.1}/MambuPy/api/mamburole.py +0 -0
  75. {mambupy-2.1.0 → mambupy-2.2.1}/MambuPy/api/mambustruct.py +0 -0
  76. {mambupy-2.1.0 → mambupy-2.2.1}/MambuPy/api/mambutask.py +0 -0
  77. {mambupy-2.1.0 → mambupy-2.2.1}/MambuPy/api/mambutransaction.py +0 -0
  78. {mambupy-2.1.0 → mambupy-2.2.1}/MambuPy/api/mambuuser.py +0 -0
  79. {mambupy-2.1.0 → mambupy-2.2.1}/MambuPy/api/vos.py +0 -0
  80. {mambupy-2.1.0 → mambupy-2.2.1}/MambuPy/mambugeturl.py +0 -0
  81. {mambupy-2.1.0 → mambupy-2.2.1}/MambuPy/orm/__init__.py +0 -0
  82. {mambupy-2.1.0 → mambupy-2.2.1}/MambuPy/orm/schema_activities.py +0 -0
  83. {mambupy-2.1.0 → mambupy-2.2.1}/MambuPy/orm/schema_addresses.py +0 -0
  84. {mambupy-2.1.0 → mambupy-2.2.1}/MambuPy/orm/schema_branches.py +0 -0
  85. {mambupy-2.1.0 → mambupy-2.2.1}/MambuPy/orm/schema_centres.py +0 -0
  86. {mambupy-2.1.0 → mambupy-2.2.1}/MambuPy/orm/schema_clients.py +0 -0
  87. {mambupy-2.1.0 → mambupy-2.2.1}/MambuPy/orm/schema_customfields.py +0 -0
  88. {mambupy-2.1.0 → mambupy-2.2.1}/MambuPy/orm/schema_dummies.py +0 -0
  89. {mambupy-2.1.0 → mambupy-2.2.1}/MambuPy/orm/schema_loans.py +0 -0
  90. {mambupy-2.1.0 → mambupy-2.2.1}/MambuPy/orm/schema_mambu.py +0 -0
  91. {mambupy-2.1.0 → mambupy-2.2.1}/MambuPy/orm/schema_tasks.py +0 -0
  92. {mambupy-2.1.0 → mambupy-2.2.1}/MambuPy/orm/schema_users.py +0 -0
  93. {mambupy-2.1.0 → mambupy-2.2.1}/MambuPy/utils/__init__.py +0 -0
  94. {mambupy-2.1.0 → mambupy-2.2.1}/MambuPy/utils/userdeactivate.py +0 -0
  95. {mambupy-2.1.0 → mambupy-2.2.1}/MambuPy.egg-info/dependency_links.txt +0 -0
  96. {mambupy-2.1.0 → mambupy-2.2.1}/MambuPy.egg-info/top_level.txt +0 -0
  97. {mambupy-2.1.0 → mambupy-2.2.1}/README.md +0 -0
  98. {mambupy-2.1.0 → mambupy-2.2.1}/mambupy/api/__init__.py +0 -0
  99. {mambupy-2.1.0 → mambupy-2.2.1}/mambupy/api/classes.py +0 -0
  100. {mambupy-2.1.0 → mambupy-2.2.1}/mambupy/api/connector/__init__.py +0 -0
  101. {mambupy-2.1.0 → mambupy-2.2.1}/mambupy/api/connector/mambuconnector.py +0 -0
  102. {mambupy-2.1.0 → mambupy-2.2.1}/mambupy/api/entities.py +0 -0
  103. {mambupy-2.1.0 → mambupy-2.2.1}/mambupy/api/interfaces.py +0 -0
  104. {mambupy-2.1.0 → mambupy-2.2.1}/mambupy/api/mambubranch.py +0 -0
  105. {mambupy-2.1.0 → mambupy-2.2.1}/mambupy/api/mambucentre.py +0 -0
  106. {mambupy-2.1.0 → mambupy-2.2.1}/mambupy/api/mambuclient.py +0 -0
  107. {mambupy-2.1.0 → mambupy-2.2.1}/mambupy/api/mambucustomfield.py +0 -0
  108. {mambupy-2.1.0 → mambupy-2.2.1}/mambupy/api/mambugroup.py +0 -0
  109. {mambupy-2.1.0 → mambupy-2.2.1}/mambupy/api/mambuloan.py +0 -0
  110. {mambupy-2.1.0 → mambupy-2.2.1}/mambupy/api/mambuproduct.py +0 -0
  111. {mambupy-2.1.0 → mambupy-2.2.1}/mambupy/api/mamburole.py +0 -0
  112. {mambupy-2.1.0 → mambupy-2.2.1}/mambupy/api/mambustruct.py +0 -0
  113. {mambupy-2.1.0 → mambupy-2.2.1}/mambupy/api/mambutask.py +0 -0
  114. {mambupy-2.1.0 → mambupy-2.2.1}/mambupy/api/mambutransaction.py +0 -0
  115. {mambupy-2.1.0 → mambupy-2.2.1}/mambupy/api/mambuuser.py +0 -0
  116. {mambupy-2.1.0 → mambupy-2.2.1}/mambupy/api/vos.py +0 -0
  117. {mambupy-2.1.0 → mambupy-2.2.1}/mambupy/mambugeturl.py +0 -0
  118. {mambupy-2.1.0 → mambupy-2.2.1}/mambupy/orm/__init__.py +0 -0
  119. {mambupy-2.1.0 → mambupy-2.2.1}/mambupy/orm/schema_activities.py +0 -0
  120. {mambupy-2.1.0 → mambupy-2.2.1}/mambupy/orm/schema_addresses.py +0 -0
  121. {mambupy-2.1.0 → mambupy-2.2.1}/mambupy/orm/schema_branches.py +0 -0
  122. {mambupy-2.1.0 → mambupy-2.2.1}/mambupy/orm/schema_centres.py +0 -0
  123. {mambupy-2.1.0 → mambupy-2.2.1}/mambupy/orm/schema_clients.py +0 -0
  124. {mambupy-2.1.0 → mambupy-2.2.1}/mambupy/orm/schema_customfields.py +0 -0
  125. {mambupy-2.1.0 → mambupy-2.2.1}/mambupy/orm/schema_dummies.py +0 -0
  126. {mambupy-2.1.0 → mambupy-2.2.1}/mambupy/orm/schema_loans.py +0 -0
  127. {mambupy-2.1.0 → mambupy-2.2.1}/mambupy/orm/schema_mambu.py +0 -0
  128. {mambupy-2.1.0 → mambupy-2.2.1}/mambupy/orm/schema_tasks.py +0 -0
  129. {mambupy-2.1.0 → mambupy-2.2.1}/mambupy/orm/schema_users.py +0 -0
  130. {mambupy-2.1.0 → mambupy-2.2.1}/mambupy/utils/__init__.py +0 -0
  131. {mambupy-2.1.0 → mambupy-2.2.1}/mambupy/utils/userdeactivate.py +0 -0
  132. {mambupy-2.1.0 → mambupy-2.2.1}/setup.cfg +0 -0
@@ -8,15 +8,13 @@
8
8
  MambuPy.api
9
9
  MambuPy.api.connector
10
10
  MambuPy.orm
11
- MambuPy.rest
12
11
 
13
12
 
14
13
  Currently, there are two different ways to access Mambu objects:
15
14
 
16
15
  1) Objects using `Mambu REST API
17
16
  <https://developer.mambu.com/customer/en/portal/articles/1162276-rest-apis-overview/>`_
18
- , they live at the :any:`MambuPy.api` package (the old-and-soon-to-be-deprecated,
19
- V1-compatible code lives at :any:`MambuPy.rest`
17
+ , they live at the :any:`MambuPy.api` package
20
18
 
21
19
  2) An ORM using a `DB backup retrieved from Mambu
22
20
  <https://support.mambu.com/docs/mambu-data-dictionary>`_
@@ -39,7 +37,7 @@ import sys
39
37
  from importlib.abc import MetaPathFinder
40
38
  from importlib.util import spec_from_file_location
41
39
 
42
- __version__ = "2.1.0"
40
+ __version__ = "2.2.1"
43
41
  """The version of this module."""
44
42
 
45
43
 
@@ -36,12 +36,82 @@ from MambuPy.mambuutil import (
36
36
  apiurl,
37
37
  apiuser,
38
38
  setup_logging,
39
+ activate_request_session_objects,
39
40
  )
40
41
 
41
42
 
42
43
  logger = setup_logging(__name__)
43
44
 
44
45
 
46
+ def _configure_retry_strategy(session, retries=5):
47
+ """Configure retry strategy for a session.
48
+
49
+ Args:
50
+ session (requests.Session): The session to configure
51
+ retries (int, optional): Number of retries. Defaults to 5.
52
+ """
53
+ retry_strategy = Retry(
54
+ total=retries,
55
+ status_forcelist=[429, 500, 502, 503, 504],
56
+ backoff_factor=1,
57
+ allowed_methods=[
58
+ "HEAD",
59
+ "GET",
60
+ "OPTIONS",
61
+ "POST",
62
+ "PUT",
63
+ "DELETE",
64
+ "TRACE",
65
+ "PATCH",
66
+ ],
67
+ )
68
+ adapter = HTTPAdapter(max_retries=retry_strategy)
69
+ session.mount("https://", adapter)
70
+ session.mount("http://", adapter)
71
+
72
+
73
+ class SessionSingleton:
74
+ """Singleton class to manage HTTP sessions for MambuPy.
75
+
76
+ This class ensures that only one requests.Session object is created and reused
77
+ across all requests to the Mambu API. This helps improve performance by reusing
78
+ TCP connections.
79
+
80
+ Example:
81
+ >>> session = SessionSingleton()
82
+ >>> session.get_session() # Returns a requests.Session object
83
+ >>> session2 = SessionSingleton()
84
+ >>> session2.get_session() # Returns the same requests.Session object
85
+ """
86
+
87
+ __instance = None
88
+ __session = None
89
+ _RETRIES = 5
90
+
91
+ def __new__(cls):
92
+ """Create a new instance of SessionSingleton if one doesn't exist.
93
+
94
+ Returns:
95
+ SessionSingleton: The singleton instance.
96
+ """
97
+ if cls.__instance is None:
98
+ cls.__instance = super(SessionSingleton, cls).__new__(cls)
99
+ return cls.__instance
100
+
101
+ def get_session(self):
102
+ """Get the requests.Session object.
103
+
104
+ If no session exists, create a new one. Otherwise, return the existing one.
105
+
106
+ Returns:
107
+ requests.Session: The session object to use for HTTP requests.
108
+ """
109
+ if self.__session is None:
110
+ self.__session = requests.Session()
111
+ _configure_retry_strategy(self.__session, self._RETRIES)
112
+ return self.__session
113
+
114
+
45
115
  class MambuConnectorREST(MambuConnector, MambuConnectorReader, MambuConnectorWriter):
46
116
  """A connector for Mambu REST API"""
47
117
 
@@ -55,6 +125,9 @@ class MambuConnectorREST(MambuConnector, MambuConnectorReader, MambuConnectorWri
55
125
  }
56
126
  self.__set_authorization_header(user, pwd)
57
127
  self.__set_url(url)
128
+ self._session = None
129
+ if activate_request_session_objects.lower() == "true":
130
+ self._session = SessionSingleton().get_session()
58
131
 
59
132
  def __set_authorization_header(self, user, pwd):
60
133
  self._headers["Authorization"] = "Basic {}".format(
@@ -108,26 +181,6 @@ class MambuConnectorREST(MambuConnector, MambuConnectorReader, MambuConnectorWri
108
181
  params = self.__request_params(params)
109
182
  data = self.__request_data(data)
110
183
 
111
- retry_strategy = Retry(
112
- total=self._RETRIES,
113
- status_forcelist=[429, 500, 502, 503, 504],
114
- backoff_factor=1,
115
- allowed_methods=[
116
- "HEAD",
117
- "GET",
118
- "OPTIONS",
119
- "POST",
120
- "PUT",
121
- "DELETE",
122
- "TRACE",
123
- "PATCH",
124
- ],
125
- )
126
- adapter = HTTPAdapter(max_retries=retry_strategy)
127
- http = requests.Session()
128
- http.mount("https://", adapter)
129
- http.mount("http://", adapter)
130
-
131
184
  resp = ""
132
185
  try:
133
186
  logger.debug(
@@ -139,10 +192,15 @@ url %s, params %s, data %s, headers %s",
139
192
  data,
140
193
  [(k, v) for k, v in headers.items() if k != "Authorization"],
141
194
  )
142
- resp = http.request(method, url, params=params, data=data, headers=headers)
195
+ if self._session:
196
+ resp = self._session.request(method, url, params=params, data=data, headers=headers)
197
+ else:
198
+ http = requests.Session()
199
+ _configure_retry_strategy(http, self._RETRIES)
200
+ resp = http.request(method, url, params=params, data=data, headers=headers)
143
201
  resp.raise_for_status()
144
202
  except requests.exceptions.HTTPError as httperr:
145
- logger.error(
203
+ logger.warning(
146
204
  "%s on %s request: params %s, data %s, headers %s",
147
205
  str(httperr),
148
206
  method,
@@ -151,7 +209,7 @@ url %s, params %s, data %s, headers %s",
151
209
  [(k, v) for k, v in headers.items() if k != "Authorization"],
152
210
  )
153
211
  if hasattr(resp, "content"): # pragma: no cover
154
- logger.error("HTTPError, resp content: %s", resp.content)
212
+ logger.warning("HTTPError, resp content: %s", resp.content)
155
213
  try:
156
214
  content = json.loads(resp.content.decode())
157
215
  except ValueError:
@@ -24,6 +24,7 @@ RC files must have the following format:
24
24
  apiuser=API_user
25
25
  apipwd=API_password
26
26
  apipagination=API_pagination_limit
27
+ activate_request_session_objects=API_persistent_session
27
28
  [DB]
28
29
  dbname=Database_name
29
30
  dbuser=Database_user
@@ -75,6 +76,10 @@ user on your Mambu instance
75
76
 
76
77
  The db* configs refer to Database configurations which hold a backup of
77
78
  your Mambu Database on some server.
79
+
80
+ The activate_request_session_objects config enables or disables HTTP persistent sessions
81
+ for API requests. When enabled, it will reuse the same TCP connection for
82
+ multiple requests, improving performance. Default is False.
78
83
  """
79
84
 
80
85
  default_configs = {
@@ -83,6 +88,7 @@ default_configs = {
83
88
  "apiuser": "mambu_api_user",
84
89
  "apipwd": "mambu_api_password",
85
90
  "apipagination": "50",
91
+ "activate_request_session_objects": "False",
86
92
  # Mambu DB configurations
87
93
  "dbname": "mambu_db",
88
94
  "dbuser": "mambu_db_user",
@@ -99,20 +105,10 @@ You may edit this to your own liking. But beware of pricking eyes!
99
105
  """
100
106
 
101
107
  import os
108
+ import configparser
109
+ from configparser import NoSectionError
102
110
 
103
- # import ConfigParser depending on Python version
104
- import sys
105
-
106
- if sys.version_info.major < 3:
107
- import ConfigParser
108
- from ConfigParser import NoSectionError
109
-
110
- config = ConfigParser.ConfigParser(defaults=default_configs)
111
- else:
112
- import configparser
113
- from configparser import NoSectionError
114
-
115
- config = configparser.ConfigParser(defaults=default_configs)
111
+ config = configparser.ConfigParser(defaults=default_configs)
116
112
 
117
113
  # argparse for command line arguments overriding
118
114
  import argparse
@@ -123,6 +119,7 @@ argparser.add_argument("--mambupy_apiurl")
123
119
  argparser.add_argument("--mambupy_apiuser")
124
120
  argparser.add_argument("--mambupy_apipwd")
125
121
  argparser.add_argument("--mambupy_apipagination")
122
+ argparser.add_argument("--mambupy_activate_request_session_objects")
126
123
  argparser.add_argument("--mambupy_dbname")
127
124
  argparser.add_argument("--mambupy_dbuser")
128
125
  argparser.add_argument("--mambupy_dbpwd")
@@ -184,6 +181,8 @@ apipwd = get_conf(config, "API", "apipwd")
184
181
  """Password to access Mambu API"""
185
182
  apipagination = get_conf(config, "API", "apipagination")
186
183
  """Pagination default limit for requests to Mambu API"""
184
+ activate_request_session_objects = get_conf(config, "API", "activate_request_session_objects")
185
+ """Whether to use persistent HTTP sessions for API requests"""
187
186
  dbname = get_conf(config, "DB", "dbname")
188
187
  """Name of the DB with a backup of Mambu's DB"""
189
188
  dbuser = get_conf(config, "DB", "dbuser")
@@ -28,16 +28,9 @@ from codecs import open as copen
28
28
 
29
29
  import yaml
30
30
 
31
- from .mambuconfig import apipagination, apipwd, apiurl, apiuser, loggingconf
31
+ from .mambuconfig import apipagination, apipwd, apiurl, apiuser, loggingconf, activate_request_session_objects
32
32
  from .mambugeturl import getmambuurl
33
33
 
34
- try:
35
- # python2
36
- unicode
37
- except NameError:
38
- # python3
39
- unicode = str
40
-
41
34
  import json
42
35
  import sys
43
36
  from datetime import datetime, timezone
@@ -186,21 +179,23 @@ def date_format(field, formato=None, as_utc=False):
186
179
 
187
180
  if not formato:
188
181
  formato = "%Y-%m-%dT%H:%M:%S"
189
- if sys.version_info < (3, 0):
190
- return datetime.strptime(
191
- datetime.strptime(field, "%Y-%m-%dT%H:%M:%S+0000").strftime(formato),
182
+
183
+ field_with_tz = datetime.fromisoformat(field)
184
+
185
+ if as_utc and field_with_tz.tzinfo is not None:
186
+ # Convertir a UTC mientras aún tiene tzinfo
187
+ field_as_dt = field_with_tz.astimezone(timezone.utc)
188
+ field_as_dt = datetime.strptime(
189
+ field_as_dt.strftime(formato),
192
190
  formato,
193
191
  )
194
192
  else:
195
193
  field_as_dt = datetime.strptime(
196
- datetime.fromisoformat(field).strftime(formato),
194
+ field_with_tz.strftime(formato),
197
195
  formato,
198
196
  )
199
- if as_utc:
200
- field_as_dt = field_as_dt.astimezone(
201
- timezone.utc
202
- ).replace(tzinfo=None)
203
- return field_as_dt
197
+
198
+ return field_as_dt
204
199
 
205
200
 
206
201
  def strip_tags(html):
@@ -221,10 +216,7 @@ def strip_tags(html):
221
216
  """
222
217
 
223
218
  def __init__(self):
224
- try:
225
- super().__init__() # required for python3
226
- except TypeError: # pragma: no cover
227
- pass # with python2 raises TypeError
219
+ super().__init__()
228
220
  self.reset()
229
221
  self.fed = []
230
222
 
@@ -256,12 +248,7 @@ def strip_consecutive_repeated_char(s, ch):
256
248
  return sdest
257
249
 
258
250
 
259
- if sys.version_info >= (3, 0):
260
- # python3
261
- from future.moves.urllib import parse as urlparse
262
- else: # pragma: no cover
263
- # python2
264
- import urlparse
251
+ from urllib import parse as urlparse
265
252
 
266
253
 
267
254
  def iri_to_uri(iri):
@@ -277,35 +264,9 @@ def iri_to_uri(iri):
277
264
  unicode chars there. Using this I solved the problem.
278
265
  """
279
266
 
280
- def url_encode_non_ascii(b):
281
- """Encode Non ASCII chars to URL-friendly chars.
282
-
283
- Sometimes unicode gets in the way. A shame, I know. And perhaps the
284
- biggest shame is not me correctly handling it.
285
- """
286
- import re
287
-
288
- return re.sub("[\x80-\xFF]", lambda c: "%%%02x" % ord(c.group(0)), b)
289
-
290
267
  parts = urlparse.urlparse(iri)
291
- if sys.version_info < (3, 0): # pragma: no cover
292
- # python2
293
- partes = []
294
- for parti, part in enumerate(parts):
295
- try:
296
- if parti != 1:
297
- partes.append(url_encode_non_ascii(part.encode("utf-8")))
298
- else:
299
- partes.append(part.encode("idna"))
300
- except UnicodeDecodeError:
301
- partes.append(url_encode_non_ascii(part.decode("latin")))
302
- except Exception:
303
- raise Exception
304
- return urlparse.urlunparse(partes)
305
- else:
306
- # python3
307
- uri = [part.decode("utf8") for parti, part in enumerate(parts.encode("utf8"))]
308
- return urlparse.urlunparse(uri)
268
+ uri = [part.decode("utf8") for parti, part in enumerate(parts.encode("utf8"))]
269
+ return urlparse.urlunparse(uri)
309
270
 
310
271
 
311
272
  def encoded_dict(in_dict):
@@ -315,13 +276,6 @@ def encoded_dict(in_dict):
315
276
  """
316
277
  out_dict = {}
317
278
  for k, v in in_dict.items():
318
- if isinstance(v, unicode):
319
- if sys.version_info < (3, 0): # pragma: no cover
320
- v = v.encode("utf8")
321
- elif isinstance(v, str):
322
- # Must be encoded in UTF-8
323
- if sys.version_info < (3, 0): # pragma: no cover
324
- v.decode("utf8")
325
279
  out_dict[k] = v
326
280
  return out_dict
327
281
 
@@ -15,10 +15,9 @@ from .schema_users import User
15
15
 
16
16
  # technical debt, cannot import name schema_clients
17
17
  try:
18
- from . import \
19
- schema_clients # this should work for python2 and python3, but doesnt
20
- except Exception as e:
21
- import schema_clients # python 2
18
+ from . import schema_clients
19
+ except Exception:
20
+ import schema_clients
22
21
 
23
22
  from sqlalchemy import (Column, DateTime, ForeignKey, Integer, Numeric, String,
24
23
  Text)
@@ -23,8 +23,6 @@ every schema_*.py you need.
23
23
  This last requirement also applies for the Base, or for the engine and
24
24
  the sessionmaker for that matter.
25
25
  """
26
- from __future__ import absolute_import
27
-
28
26
  from sqlalchemy.ext.declarative import declarative_base
29
27
  from sqlalchemy.orm import sessionmaker, scoped_session
30
28
 
@@ -0,0 +1,31 @@
1
+ # coding: utf-8
2
+ """MambuPy REST module - DEPRECATED.
3
+
4
+ .. warning::
5
+
6
+ DEPRECATED: This module uses Mambu API v1 which is no longer supported.
7
+ This code is maintained only for backwards compatibility with legacy systems.
8
+ It will be removed in a future version of MambuPy.
9
+
10
+ Only mambuactivity is available in this legacy module.
11
+ """
12
+ import warnings
13
+
14
+ warnings.warn(
15
+ "MambuPy.rest module is deprecated and will be removed in a future version. "
16
+ "Mambu API v1 is no longer supported by Mambu.",
17
+ DeprecationWarning,
18
+ stacklevel=2,
19
+ )
20
+
21
+ from .mambuactivity import (
22
+ MambuActivity,
23
+ MambuActivities,
24
+ getactivitiesurl,
25
+ )
26
+
27
+ __all__ = [
28
+ "MambuActivity",
29
+ "MambuActivities",
30
+ "getactivitiesurl",
31
+ ]