MambuPy 2.0.0b50__tar.gz → 2.1.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.
- {MambuPy-2.0.0b50 → mambupy-2.1.1}/MambuPy/__init__.py +21 -4
- {MambuPy-2.0.0b50/mambupy → mambupy-2.1.1/MambuPy}/api/connector/rest.py +121 -31
- {MambuPy-2.0.0b50 → mambupy-2.1.1}/MambuPy/api/entities.py +14 -8
- {MambuPy-2.0.0b50/mambupy → mambupy-2.1.1/MambuPy}/mambuconfig.py +9 -0
- {MambuPy-2.0.0b50 → mambupy-2.1.1}/MambuPy/mambuutil.py +3 -3
- mambupy-2.1.1/MambuPy/rest/__init__.py +49 -0
- mambupy-2.1.1/MambuPy/rest/mambuactivity.py +87 -0
- mambupy-2.1.1/MambuPy/rest/mambubranch.py +122 -0
- mambupy-2.1.1/MambuPy/rest/mambucentre.py +104 -0
- mambupy-2.1.1/MambuPy/rest/mambuclient.py +317 -0
- mambupy-2.1.1/MambuPy/rest/mambugroup.py +372 -0
- mambupy-2.1.1/MambuPy/rest/mambuloan.py +687 -0
- mambupy-2.1.1/MambuPy/rest/mambuproduct.py +180 -0
- mambupy-2.1.1/MambuPy/rest/mamburepayment.py +99 -0
- mambupy-2.1.1/MambuPy/rest/mamburestutils.py +116 -0
- mambupy-2.1.1/MambuPy/rest/mamburoles.py +98 -0
- mambupy-2.1.1/MambuPy/rest/mambusaving.py +114 -0
- mambupy-2.1.1/MambuPy/rest/mambusavingfundingrepayment.py +94 -0
- mambupy-2.1.1/MambuPy/rest/mambusavingtransaction.py +163 -0
- mambupy-2.1.1/MambuPy/rest/mambustruct.py +1066 -0
- mambupy-2.1.1/MambuPy/rest/mambutask.py +163 -0
- mambupy-2.1.1/MambuPy/rest/mambutransaction.py +103 -0
- mambupy-2.1.1/MambuPy/rest/mambutransactionchannel.py +101 -0
- mambupy-2.1.1/MambuPy/rest/mambuuser.py +229 -0
- mambupy-2.1.1/MambuPy.egg-info/PKG-INFO +760 -0
- {MambuPy-2.0.0b50 → mambupy-2.1.1}/MambuPy.egg-info/SOURCES.txt +39 -27
- mambupy-2.1.1/MambuPy.egg-info/requires.txt +30 -0
- mambupy-2.1.1/MambuPy.egg-info/top_level.txt +3 -0
- mambupy-2.1.1/PKG-INFO +760 -0
- {MambuPy-2.0.0b50 → mambupy-2.1.1}/mambupy/__init__.py +21 -4
- {MambuPy-2.0.0b50/MambuPy → mambupy-2.1.1/mambupy}/api/connector/rest.py +121 -31
- {MambuPy-2.0.0b50 → mambupy-2.1.1}/mambupy/api/entities.py +14 -8
- {MambuPy-2.0.0b50/MambuPy → mambupy-2.1.1/mambupy}/mambuconfig.py +9 -0
- {MambuPy-2.0.0b50 → mambupy-2.1.1}/mambupy/mambuutil.py +3 -3
- mambupy-2.1.1/mambupy/rest/__init__.py +49 -0
- mambupy-2.1.1/mambupy/rest/mambuactivity.py +87 -0
- mambupy-2.1.1/mambupy/rest/mambubranch.py +122 -0
- mambupy-2.1.1/mambupy/rest/mambucentre.py +104 -0
- mambupy-2.1.1/mambupy/rest/mambuclient.py +317 -0
- mambupy-2.1.1/mambupy/rest/mambugroup.py +372 -0
- mambupy-2.1.1/mambupy/rest/mambuloan.py +687 -0
- mambupy-2.1.1/mambupy/rest/mambuproduct.py +180 -0
- mambupy-2.1.1/mambupy/rest/mamburepayment.py +99 -0
- mambupy-2.1.1/mambupy/rest/mamburestutils.py +116 -0
- mambupy-2.1.1/mambupy/rest/mamburoles.py +98 -0
- mambupy-2.1.1/mambupy/rest/mambusaving.py +114 -0
- mambupy-2.1.1/mambupy/rest/mambusavingfundingrepayment.py +94 -0
- mambupy-2.1.1/mambupy/rest/mambusavingtransaction.py +163 -0
- mambupy-2.1.1/mambupy/rest/mambustruct.py +1066 -0
- mambupy-2.1.1/mambupy/rest/mambutask.py +163 -0
- mambupy-2.1.1/mambupy/rest/mambutransaction.py +103 -0
- mambupy-2.1.1/mambupy/rest/mambutransactionchannel.py +101 -0
- mambupy-2.1.1/mambupy/rest/mambuuser.py +229 -0
- mambupy-2.1.1/pyproject.toml +49 -0
- MambuPy-2.0.0b50/MambuPy/rest1to2/__init__.py +0 -18
- MambuPy-2.0.0b50/MambuPy/rest1to2/mambubranch.py +0 -74
- MambuPy-2.0.0b50/MambuPy/rest1to2/mambucentre.py +0 -35
- MambuPy-2.0.0b50/MambuPy/rest1to2/mambuclient.py +0 -133
- MambuPy-2.0.0b50/MambuPy/rest1to2/mambugroup.py +0 -108
- MambuPy-2.0.0b50/MambuPy/rest1to2/mambuloan.py +0 -215
- MambuPy-2.0.0b50/MambuPy/rest1to2/mambuproduct.py +0 -34
- MambuPy-2.0.0b50/MambuPy/rest1to2/mamburepayment.py +0 -97
- MambuPy-2.0.0b50/MambuPy/rest1to2/mambustruct.py +0 -352
- MambuPy-2.0.0b50/MambuPy/rest1to2/mambutask.py +0 -64
- MambuPy-2.0.0b50/MambuPy/rest1to2/mambutransaction.py +0 -46
- MambuPy-2.0.0b50/MambuPy/rest1to2/mambuuser.py +0 -85
- MambuPy-2.0.0b50/MambuPy/utils/logging_config.py +0 -5
- MambuPy-2.0.0b50/MambuPy.egg-info/PKG-INFO +0 -49
- MambuPy-2.0.0b50/MambuPy.egg-info/requires.txt +0 -7
- MambuPy-2.0.0b50/MambuPy.egg-info/top_level.txt +0 -12
- MambuPy-2.0.0b50/PKG-INFO +0 -49
- MambuPy-2.0.0b50/mambupy/rest1to2/__init__.py +0 -18
- MambuPy-2.0.0b50/mambupy/rest1to2/mambubranch.py +0 -74
- MambuPy-2.0.0b50/mambupy/rest1to2/mambucentre.py +0 -35
- MambuPy-2.0.0b50/mambupy/rest1to2/mambuclient.py +0 -133
- MambuPy-2.0.0b50/mambupy/rest1to2/mambugroup.py +0 -108
- MambuPy-2.0.0b50/mambupy/rest1to2/mambuloan.py +0 -215
- MambuPy-2.0.0b50/mambupy/rest1to2/mambuproduct.py +0 -34
- MambuPy-2.0.0b50/mambupy/rest1to2/mamburepayment.py +0 -97
- MambuPy-2.0.0b50/mambupy/rest1to2/mambustruct.py +0 -352
- MambuPy-2.0.0b50/mambupy/rest1to2/mambutask.py +0 -64
- MambuPy-2.0.0b50/mambupy/rest1to2/mambutransaction.py +0 -46
- MambuPy-2.0.0b50/mambupy/rest1to2/mambuuser.py +0 -85
- MambuPy-2.0.0b50/mambupy/utils/logging_config.py +0 -5
- MambuPy-2.0.0b50/setup.py +0 -128
- {MambuPy-2.0.0b50 → mambupy-2.1.1}/LICENSE +0 -0
- {MambuPy-2.0.0b50 → mambupy-2.1.1}/MambuPy/api/__init__.py +0 -0
- {MambuPy-2.0.0b50 → mambupy-2.1.1}/MambuPy/api/classes.py +0 -0
- {MambuPy-2.0.0b50 → mambupy-2.1.1}/MambuPy/api/connector/__init__.py +0 -0
- {MambuPy-2.0.0b50 → mambupy-2.1.1}/MambuPy/api/connector/mambuconnector.py +0 -0
- {MambuPy-2.0.0b50 → mambupy-2.1.1}/MambuPy/api/interfaces.py +0 -0
- {MambuPy-2.0.0b50 → mambupy-2.1.1}/MambuPy/api/mambubranch.py +0 -0
- {MambuPy-2.0.0b50 → mambupy-2.1.1}/MambuPy/api/mambucentre.py +0 -0
- {MambuPy-2.0.0b50 → mambupy-2.1.1}/MambuPy/api/mambuclient.py +0 -0
- {MambuPy-2.0.0b50 → mambupy-2.1.1}/MambuPy/api/mambucustomfield.py +0 -0
- {MambuPy-2.0.0b50 → mambupy-2.1.1}/MambuPy/api/mambugroup.py +0 -0
- {MambuPy-2.0.0b50 → mambupy-2.1.1}/MambuPy/api/mambuloan.py +0 -0
- {MambuPy-2.0.0b50 → mambupy-2.1.1}/MambuPy/api/mambuproduct.py +0 -0
- {MambuPy-2.0.0b50 → mambupy-2.1.1}/MambuPy/api/mamburole.py +0 -0
- {MambuPy-2.0.0b50 → mambupy-2.1.1}/MambuPy/api/mambustruct.py +0 -0
- {MambuPy-2.0.0b50 → mambupy-2.1.1}/MambuPy/api/mambutask.py +0 -0
- {MambuPy-2.0.0b50 → mambupy-2.1.1}/MambuPy/api/mambutransaction.py +0 -0
- {MambuPy-2.0.0b50 → mambupy-2.1.1}/MambuPy/api/mambuuser.py +0 -0
- {MambuPy-2.0.0b50 → mambupy-2.1.1}/MambuPy/api/vos.py +0 -0
- {MambuPy-2.0.0b50 → mambupy-2.1.1}/MambuPy/mambugeturl.py +0 -0
- {MambuPy-2.0.0b50 → mambupy-2.1.1}/MambuPy/orm/__init__.py +0 -0
- {MambuPy-2.0.0b50 → mambupy-2.1.1}/MambuPy/orm/schema_activities.py +0 -0
- {MambuPy-2.0.0b50 → mambupy-2.1.1}/MambuPy/orm/schema_addresses.py +0 -0
- {MambuPy-2.0.0b50 → mambupy-2.1.1}/MambuPy/orm/schema_branches.py +0 -0
- {MambuPy-2.0.0b50 → mambupy-2.1.1}/MambuPy/orm/schema_centres.py +0 -0
- {MambuPy-2.0.0b50 → mambupy-2.1.1}/MambuPy/orm/schema_clients.py +0 -0
- {MambuPy-2.0.0b50 → mambupy-2.1.1}/MambuPy/orm/schema_customfields.py +0 -0
- {MambuPy-2.0.0b50 → mambupy-2.1.1}/MambuPy/orm/schema_dummies.py +0 -0
- {MambuPy-2.0.0b50 → mambupy-2.1.1}/MambuPy/orm/schema_groups.py +0 -0
- {MambuPy-2.0.0b50 → mambupy-2.1.1}/MambuPy/orm/schema_loans.py +0 -0
- {MambuPy-2.0.0b50 → mambupy-2.1.1}/MambuPy/orm/schema_mambu.py +0 -0
- {MambuPy-2.0.0b50 → mambupy-2.1.1}/MambuPy/orm/schema_orm.py +0 -0
- {MambuPy-2.0.0b50 → mambupy-2.1.1}/MambuPy/orm/schema_tasks.py +0 -0
- {MambuPy-2.0.0b50 → mambupy-2.1.1}/MambuPy/orm/schema_users.py +0 -0
- {MambuPy-2.0.0b50 → mambupy-2.1.1}/MambuPy/utils/__init__.py +0 -0
- {MambuPy-2.0.0b50 → mambupy-2.1.1}/MambuPy/utils/userdeactivate.py +0 -0
- {MambuPy-2.0.0b50 → mambupy-2.1.1}/MambuPy.egg-info/dependency_links.txt +0 -0
- {MambuPy-2.0.0b50 → mambupy-2.1.1}/README.md +0 -0
- {MambuPy-2.0.0b50 → mambupy-2.1.1}/mambupy/api/__init__.py +0 -0
- {MambuPy-2.0.0b50 → mambupy-2.1.1}/mambupy/api/classes.py +0 -0
- {MambuPy-2.0.0b50 → mambupy-2.1.1}/mambupy/api/connector/__init__.py +0 -0
- {MambuPy-2.0.0b50 → mambupy-2.1.1}/mambupy/api/connector/mambuconnector.py +0 -0
- {MambuPy-2.0.0b50 → mambupy-2.1.1}/mambupy/api/interfaces.py +0 -0
- {MambuPy-2.0.0b50 → mambupy-2.1.1}/mambupy/api/mambubranch.py +0 -0
- {MambuPy-2.0.0b50 → mambupy-2.1.1}/mambupy/api/mambucentre.py +0 -0
- {MambuPy-2.0.0b50 → mambupy-2.1.1}/mambupy/api/mambuclient.py +0 -0
- {MambuPy-2.0.0b50 → mambupy-2.1.1}/mambupy/api/mambucustomfield.py +0 -0
- {MambuPy-2.0.0b50 → mambupy-2.1.1}/mambupy/api/mambugroup.py +0 -0
- {MambuPy-2.0.0b50 → mambupy-2.1.1}/mambupy/api/mambuloan.py +0 -0
- {MambuPy-2.0.0b50 → mambupy-2.1.1}/mambupy/api/mambuproduct.py +0 -0
- {MambuPy-2.0.0b50 → mambupy-2.1.1}/mambupy/api/mamburole.py +0 -0
- {MambuPy-2.0.0b50 → mambupy-2.1.1}/mambupy/api/mambustruct.py +0 -0
- {MambuPy-2.0.0b50 → mambupy-2.1.1}/mambupy/api/mambutask.py +0 -0
- {MambuPy-2.0.0b50 → mambupy-2.1.1}/mambupy/api/mambutransaction.py +0 -0
- {MambuPy-2.0.0b50 → mambupy-2.1.1}/mambupy/api/mambuuser.py +0 -0
- {MambuPy-2.0.0b50 → mambupy-2.1.1}/mambupy/api/vos.py +0 -0
- {MambuPy-2.0.0b50 → mambupy-2.1.1}/mambupy/mambugeturl.py +0 -0
- {MambuPy-2.0.0b50 → mambupy-2.1.1}/mambupy/orm/__init__.py +0 -0
- {MambuPy-2.0.0b50 → mambupy-2.1.1}/mambupy/orm/schema_activities.py +0 -0
- {MambuPy-2.0.0b50 → mambupy-2.1.1}/mambupy/orm/schema_addresses.py +0 -0
- {MambuPy-2.0.0b50 → mambupy-2.1.1}/mambupy/orm/schema_branches.py +0 -0
- {MambuPy-2.0.0b50 → mambupy-2.1.1}/mambupy/orm/schema_centres.py +0 -0
- {MambuPy-2.0.0b50 → mambupy-2.1.1}/mambupy/orm/schema_clients.py +0 -0
- {MambuPy-2.0.0b50 → mambupy-2.1.1}/mambupy/orm/schema_customfields.py +0 -0
- {MambuPy-2.0.0b50 → mambupy-2.1.1}/mambupy/orm/schema_dummies.py +0 -0
- {MambuPy-2.0.0b50 → mambupy-2.1.1}/mambupy/orm/schema_groups.py +0 -0
- {MambuPy-2.0.0b50 → mambupy-2.1.1}/mambupy/orm/schema_loans.py +0 -0
- {MambuPy-2.0.0b50 → mambupy-2.1.1}/mambupy/orm/schema_mambu.py +0 -0
- {MambuPy-2.0.0b50 → mambupy-2.1.1}/mambupy/orm/schema_orm.py +0 -0
- {MambuPy-2.0.0b50 → mambupy-2.1.1}/mambupy/orm/schema_tasks.py +0 -0
- {MambuPy-2.0.0b50 → mambupy-2.1.1}/mambupy/orm/schema_users.py +0 -0
- {MambuPy-2.0.0b50 → mambupy-2.1.1}/mambupy/utils/__init__.py +0 -0
- {MambuPy-2.0.0b50 → mambupy-2.1.1}/mambupy/utils/userdeactivate.py +0 -0
- {MambuPy-2.0.0b50 → mambupy-2.1.1}/setup.cfg +0 -0
|
@@ -5,17 +5,18 @@
|
|
|
5
5
|
|
|
6
6
|
MambuPy.mambuconfig
|
|
7
7
|
MambuPy.mambuutil
|
|
8
|
-
MambuPy.rest
|
|
9
|
-
MambuPy.orm
|
|
10
8
|
MambuPy.api
|
|
11
9
|
MambuPy.api.connector
|
|
10
|
+
MambuPy.orm
|
|
11
|
+
MambuPy.rest
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
Currently, there are two different ways to access Mambu objects:
|
|
15
15
|
|
|
16
16
|
1) Objects using `Mambu REST API
|
|
17
17
|
<https://developer.mambu.com/customer/en/portal/articles/1162276-rest-apis-overview/>`_
|
|
18
|
-
, they live at the :any:`MambuPy.
|
|
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`
|
|
19
20
|
|
|
20
21
|
2) An ORM using a `DB backup retrieved from Mambu
|
|
21
22
|
<https://support.mambu.com/docs/mambu-data-dictionary>`_
|
|
@@ -34,5 +35,21 @@ TODOS
|
|
|
34
35
|
to achive TDD when implementing features or correcting bugs.
|
|
35
36
|
"""
|
|
36
37
|
|
|
37
|
-
|
|
38
|
+
import sys
|
|
39
|
+
from importlib.abc import MetaPathFinder
|
|
40
|
+
from importlib.util import spec_from_file_location
|
|
41
|
+
|
|
42
|
+
__version__ = "2.1.1"
|
|
38
43
|
"""The version of this module."""
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
class CaseInsensitiveFinder(MetaPathFinder):
|
|
47
|
+
def find_spec(self, fullname, path, target=None):
|
|
48
|
+
if fullname.lower() == "mambupy":
|
|
49
|
+
# Get the actual module file location
|
|
50
|
+
return spec_from_file_location(fullname, __file__)
|
|
51
|
+
return None
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
# Register the finder
|
|
55
|
+
sys.meta_path.insert(0, CaseInsensitiveFinder())
|
|
@@ -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
|
|
|
@@ -52,10 +122,19 @@ class MambuConnectorREST(MambuConnector, MambuConnectorReader, MambuConnectorWri
|
|
|
52
122
|
def __init__(self, user=apiuser, pwd=apipwd, url=apiurl, **kwargs):
|
|
53
123
|
self._headers = {
|
|
54
124
|
"Accept": "application/vnd.mambu.v2+json",
|
|
55
|
-
"Authorization": "Basic {}".format(
|
|
56
|
-
base64.b64encode(bytes("{}:{}".format(user, pwd), "utf-8")).decode()
|
|
57
|
-
),
|
|
58
125
|
}
|
|
126
|
+
self.__set_authorization_header(user, pwd)
|
|
127
|
+
self.__set_url(url)
|
|
128
|
+
self._session = None
|
|
129
|
+
if activate_request_session_objects.lower() == "true":
|
|
130
|
+
self._session = SessionSingleton().get_session()
|
|
131
|
+
|
|
132
|
+
def __set_authorization_header(self, user, pwd):
|
|
133
|
+
self._headers["Authorization"] = "Basic {}".format(
|
|
134
|
+
base64.b64encode(bytes("{}:{}".format(user, pwd), "utf-8")).decode()
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
def __set_url(self, url):
|
|
59
138
|
self._tenant = url
|
|
60
139
|
|
|
61
140
|
def __request_headers(self, method, content_type):
|
|
@@ -102,26 +181,6 @@ class MambuConnectorREST(MambuConnector, MambuConnectorReader, MambuConnectorWri
|
|
|
102
181
|
params = self.__request_params(params)
|
|
103
182
|
data = self.__request_data(data)
|
|
104
183
|
|
|
105
|
-
retry_strategy = Retry(
|
|
106
|
-
total=self._RETRIES,
|
|
107
|
-
status_forcelist=[429, 502, 503, 504],
|
|
108
|
-
backoff_factor=1,
|
|
109
|
-
allowed_methods=[
|
|
110
|
-
"HEAD",
|
|
111
|
-
"GET",
|
|
112
|
-
"OPTIONS",
|
|
113
|
-
"POST",
|
|
114
|
-
"PUT",
|
|
115
|
-
"DELETE",
|
|
116
|
-
"TRACE",
|
|
117
|
-
"PATCH",
|
|
118
|
-
],
|
|
119
|
-
)
|
|
120
|
-
adapter = HTTPAdapter(max_retries=retry_strategy)
|
|
121
|
-
http = requests.Session()
|
|
122
|
-
http.mount("https://", adapter)
|
|
123
|
-
http.mount("http://", adapter)
|
|
124
|
-
|
|
125
184
|
resp = ""
|
|
126
185
|
try:
|
|
127
186
|
logger.debug(
|
|
@@ -133,10 +192,15 @@ url %s, params %s, data %s, headers %s",
|
|
|
133
192
|
data,
|
|
134
193
|
[(k, v) for k, v in headers.items() if k != "Authorization"],
|
|
135
194
|
)
|
|
136
|
-
|
|
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)
|
|
137
201
|
resp.raise_for_status()
|
|
138
202
|
except requests.exceptions.HTTPError as httperr:
|
|
139
|
-
logger.
|
|
203
|
+
logger.warning(
|
|
140
204
|
"%s on %s request: params %s, data %s, headers %s",
|
|
141
205
|
str(httperr),
|
|
142
206
|
method,
|
|
@@ -145,7 +209,7 @@ url %s, params %s, data %s, headers %s",
|
|
|
145
209
|
[(k, v) for k, v in headers.items() if k != "Authorization"],
|
|
146
210
|
)
|
|
147
211
|
if hasattr(resp, "content"): # pragma: no cover
|
|
148
|
-
logger.
|
|
212
|
+
logger.warning("HTTPError, resp content: %s", resp.content)
|
|
149
213
|
try:
|
|
150
214
|
content = json.loads(resp.content.decode())
|
|
151
215
|
except ValueError:
|
|
@@ -489,36 +553,48 @@ url %s, params %s, data %s, headers %s",
|
|
|
489
553
|
|
|
490
554
|
return self.__list_request("POST", url, params=params, data=data)
|
|
491
555
|
|
|
492
|
-
def mambu_update(self, entid, prefix, attrs):
|
|
556
|
+
def mambu_update(self, entid, prefix, attrs, **kwargs):
|
|
493
557
|
"""updates a mambu entity
|
|
494
558
|
|
|
495
559
|
Args:
|
|
496
560
|
entid (str): the id or encoded key of the entity owning the document
|
|
497
561
|
prefix (str): entity's URL prefix
|
|
498
562
|
attrs (dict): entity to be updated, complying with Mambu's schemas
|
|
563
|
+
kwargs (dict): keyword arguments for this method.
|
|
564
|
+
May include a user, pwd and url to connect to Mambu.
|
|
499
565
|
|
|
500
566
|
Returns:
|
|
501
567
|
response content (str json {})
|
|
502
568
|
"""
|
|
569
|
+
if "url" in kwargs:
|
|
570
|
+
self.__set_url(kwargs["url"])
|
|
571
|
+
if "user" in kwargs and "pwd" in kwargs:
|
|
572
|
+
self.__set_authorization_header(kwargs["user"], kwargs["pwd"])
|
|
503
573
|
url = "https://{}/api/{}/{}".format(self._tenant, prefix, entid)
|
|
504
574
|
|
|
505
575
|
return self.__request("PUT", url, data=attrs)
|
|
506
576
|
|
|
507
|
-
def mambu_create(self, prefix, attrs):
|
|
577
|
+
def mambu_create(self, prefix, attrs, **kwargs):
|
|
508
578
|
"""creates a mambu entity
|
|
509
579
|
|
|
510
580
|
Args:
|
|
511
581
|
prefix (str): entity's URL prefix
|
|
512
582
|
attrs (dict): entity to be created, complying with Mambu's schemas
|
|
583
|
+
kwargs (dict): keyword arguments for this method.
|
|
584
|
+
May include a user, pwd and url to connect to Mambu.
|
|
513
585
|
|
|
514
586
|
Returns:
|
|
515
587
|
response content (str json {})
|
|
516
588
|
"""
|
|
589
|
+
if "url" in kwargs:
|
|
590
|
+
self.__set_url(kwargs["url"])
|
|
591
|
+
if "user" in kwargs and "pwd" in kwargs:
|
|
592
|
+
self.__set_authorization_header(kwargs["user"], kwargs["pwd"])
|
|
517
593
|
url = "https://{}/api/{}".format(self._tenant, prefix)
|
|
518
594
|
|
|
519
595
|
return self.__request("POST", url, data=attrs)
|
|
520
596
|
|
|
521
|
-
def mambu_patch(self, entid, prefix, fields_ops=None):
|
|
597
|
+
def mambu_patch(self, entid, prefix, fields_ops=None, **kwargs):
|
|
522
598
|
"""patches certain parts of a mambu entity
|
|
523
599
|
|
|
524
600
|
https://api.mambu.com/?python#tocspatchoperation
|
|
@@ -532,10 +608,16 @@ url %s, params %s, data %s, headers %s",
|
|
|
532
608
|
OP (str): operation ("ADD", "REPLACE", "REMOVE")
|
|
533
609
|
PATH (str): json pointer referencing the location in the target entity
|
|
534
610
|
VALUE (obj, opc): the value of the field (not for REMOVE op)
|
|
611
|
+
kwargs (dict): keyword arguments for this method.
|
|
612
|
+
May include a user, pwd and url to connect to Mambu.
|
|
535
613
|
"""
|
|
536
614
|
if not fields_ops:
|
|
537
615
|
fields_ops = []
|
|
538
616
|
|
|
617
|
+
if "url" in kwargs:
|
|
618
|
+
self.__set_url(kwargs["url"])
|
|
619
|
+
if "user" in kwargs and "pwd" in kwargs:
|
|
620
|
+
self.__set_authorization_header(kwargs["user"], kwargs["pwd"])
|
|
539
621
|
url = "https://{}/api/{}/{}".format(self._tenant, prefix, entid)
|
|
540
622
|
|
|
541
623
|
# build data from fields_ops param
|
|
@@ -549,8 +631,16 @@ url %s, params %s, data %s, headers %s",
|
|
|
549
631
|
if patch_data:
|
|
550
632
|
return self.__request("PATCH", url, data=patch_data)
|
|
551
633
|
|
|
552
|
-
def mambu_delete(self, entid, prefix):
|
|
553
|
-
"""deletes a mambu entity
|
|
634
|
+
def mambu_delete(self, entid, prefix, **kwargs):
|
|
635
|
+
"""deletes a mambu entity
|
|
636
|
+
|
|
637
|
+
kwargs (dict): keyword arguments for this method.
|
|
638
|
+
May include a user, pwd and url to connect to Mambu.
|
|
639
|
+
"""
|
|
640
|
+
if "url" in kwargs:
|
|
641
|
+
self.__set_url(kwargs["url"])
|
|
642
|
+
if "user" in kwargs and "pwd" in kwargs:
|
|
643
|
+
self.__set_authorization_header(kwargs["user"], kwargs["pwd"])
|
|
554
644
|
url = "https://{}/api/{}/{}".format(self._tenant, prefix, entid)
|
|
555
645
|
|
|
556
646
|
return self.__request("DELETE", url)
|
|
@@ -428,19 +428,22 @@ class MambuEntity(MambuStruct):
|
|
|
428
428
|
class MambuEntityWritable(MambuStruct, MambuWritable):
|
|
429
429
|
"""A Mambu object with writing capabilities."""
|
|
430
430
|
|
|
431
|
-
def update(self):
|
|
431
|
+
def update(self, **kwargs):
|
|
432
432
|
"""updates a mambu entity
|
|
433
433
|
|
|
434
434
|
Uses the current values of the _attrs to send to Mambu.
|
|
435
435
|
Pre-requires that CustomFields are updated previously.
|
|
436
436
|
Post-requires that CustomFields are extracted again.
|
|
437
|
+
|
|
438
|
+
kwargs (dict): keyword arguments for this method.
|
|
439
|
+
May include a user, pwd and url to connect to Mambu.
|
|
437
440
|
"""
|
|
438
441
|
self._updateVOs()
|
|
439
442
|
self._updateCustomFields()
|
|
440
443
|
self._serializeFields()
|
|
441
444
|
try:
|
|
442
445
|
self._connector.mambu_update(
|
|
443
|
-
self.id, self._prefix, copy.deepcopy(self._attrs)
|
|
446
|
+
self.id, self._prefix, copy.deepcopy(self._attrs), **kwargs
|
|
444
447
|
)
|
|
445
448
|
# should I refresh _attrs? (either get request from Mambu or using the response)
|
|
446
449
|
except MambuError:
|
|
@@ -450,19 +453,22 @@ class MambuEntityWritable(MambuStruct, MambuWritable):
|
|
|
450
453
|
self._extractCustomFields()
|
|
451
454
|
self._extractVOs()
|
|
452
455
|
|
|
453
|
-
def create(self):
|
|
456
|
+
def create(self, **kwargs):
|
|
454
457
|
"""creates a mambu entity
|
|
455
458
|
|
|
456
459
|
Uses the current values of the _attrs to send to Mambu.
|
|
457
460
|
Pre-requires that CustomFields are updated previously.
|
|
458
461
|
Post-requires that CustomFields are extracted again.
|
|
462
|
+
|
|
463
|
+
kwargs (dict): keyword arguments for this method.
|
|
464
|
+
May include a user, pwd and url to connect to Mambu.
|
|
459
465
|
"""
|
|
460
466
|
self._updateVOs()
|
|
461
467
|
self._updateCustomFields()
|
|
462
468
|
self._serializeFields()
|
|
463
469
|
try:
|
|
464
470
|
self._resp = self._connector.mambu_create(
|
|
465
|
-
self._prefix, copy.deepcopy(self._attrs)
|
|
471
|
+
self._prefix, copy.deepcopy(self._attrs), **kwargs
|
|
466
472
|
)
|
|
467
473
|
self._attrs.update(dict(json.loads(self._resp.decode())))
|
|
468
474
|
self._tzattrs = dict(json.loads(self._resp.decode()))
|
|
@@ -516,7 +522,7 @@ class MambuEntityWritable(MambuStruct, MambuWritable):
|
|
|
516
522
|
else:
|
|
517
523
|
raise MambuPyError("Unrecognizable field {} for patching".format(field))
|
|
518
524
|
|
|
519
|
-
def patch(self, fields=None, autodetect_remove=False):
|
|
525
|
+
def patch(self, fields=None, autodetect_remove=False, **kwargs):
|
|
520
526
|
"""patches a mambu entity
|
|
521
527
|
|
|
522
528
|
Allows patching of parts of the entity up to Mambu.
|
|
@@ -583,7 +589,7 @@ class MambuEntityWritable(MambuStruct, MambuWritable):
|
|
|
583
589
|
self._updateCustomFields()
|
|
584
590
|
self._serializeFields()
|
|
585
591
|
if fields_ops:
|
|
586
|
-
self._connector.mambu_patch(self.id, self._prefix, fields_ops)
|
|
592
|
+
self._connector.mambu_patch(self.id, self._prefix, fields_ops, **kwargs)
|
|
587
593
|
# should I refresh _attrs? (needs get request from Mambu)
|
|
588
594
|
except MambuError:
|
|
589
595
|
raise
|
|
@@ -599,7 +605,7 @@ class MambuEntityWritable(MambuStruct, MambuWritable):
|
|
|
599
605
|
Implement on entities which require further cleaning.
|
|
600
606
|
"""
|
|
601
607
|
|
|
602
|
-
def delete(self):
|
|
608
|
+
def delete(self, **kwargs):
|
|
603
609
|
"""deletes a mambu entity.
|
|
604
610
|
|
|
605
611
|
Leaves the object in a supposedly state where you can create
|
|
@@ -610,7 +616,7 @@ class MambuEntityWritable(MambuStruct, MambuWritable):
|
|
|
610
616
|
make sure we can run creation after deletion.
|
|
611
617
|
"""
|
|
612
618
|
try:
|
|
613
|
-
self._connector.mambu_delete(self.id, self._prefix)
|
|
619
|
+
self._connector.mambu_delete(self.id, self._prefix, **kwargs)
|
|
614
620
|
except MambuError:
|
|
615
621
|
raise
|
|
616
622
|
|
|
@@ -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",
|
|
@@ -123,6 +129,7 @@ argparser.add_argument("--mambupy_apiurl")
|
|
|
123
129
|
argparser.add_argument("--mambupy_apiuser")
|
|
124
130
|
argparser.add_argument("--mambupy_apipwd")
|
|
125
131
|
argparser.add_argument("--mambupy_apipagination")
|
|
132
|
+
argparser.add_argument("--mambupy_activate_request_session_objects")
|
|
126
133
|
argparser.add_argument("--mambupy_dbname")
|
|
127
134
|
argparser.add_argument("--mambupy_dbuser")
|
|
128
135
|
argparser.add_argument("--mambupy_dbpwd")
|
|
@@ -184,6 +191,8 @@ apipwd = get_conf(config, "API", "apipwd")
|
|
|
184
191
|
"""Password to access Mambu API"""
|
|
185
192
|
apipagination = get_conf(config, "API", "apipagination")
|
|
186
193
|
"""Pagination default limit for requests to Mambu API"""
|
|
194
|
+
activate_request_session_objects = get_conf(config, "API", "activate_request_session_objects")
|
|
195
|
+
"""Whether to use persistent HTTP sessions for API requests"""
|
|
187
196
|
dbname = get_conf(config, "DB", "dbname")
|
|
188
197
|
"""Name of the DB with a backup of Mambu's DB"""
|
|
189
198
|
dbuser = get_conf(config, "DB", "dbuser")
|
|
@@ -28,7 +28,7 @@ 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
34
|
try:
|
|
@@ -258,7 +258,7 @@ def strip_consecutive_repeated_char(s, ch):
|
|
|
258
258
|
|
|
259
259
|
if sys.version_info >= (3, 0):
|
|
260
260
|
# python3
|
|
261
|
-
from
|
|
261
|
+
from urllib import parse as urlparse
|
|
262
262
|
else: # pragma: no cover
|
|
263
263
|
# python2
|
|
264
264
|
import urlparse
|
|
@@ -405,7 +405,7 @@ def _backup_db_timeout_mechanism(
|
|
|
405
405
|
):
|
|
406
406
|
value_to_latest = True
|
|
407
407
|
while not justbackup and retries and not bool_func():
|
|
408
|
-
logger.
|
|
408
|
+
logger.debug("waiting...")
|
|
409
409
|
sleep(10)
|
|
410
410
|
retries -= 1
|
|
411
411
|
if retries < 0:
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"""MambuPy's REST package (SOON TO BE DEPRECATED).
|
|
2
|
+
|
|
3
|
+
Objects using `Mambu REST API
|
|
4
|
+
<https://developer.mambu.com/customer/en/portal/articles/1162276-rest-apis-overview/>`_
|
|
5
|
+
|
|
6
|
+
.. autosummary::
|
|
7
|
+
:toctree: _autosummary
|
|
8
|
+
|
|
9
|
+
MambuPy.rest.mambustruct
|
|
10
|
+
MambuPy.rest.mambuclient
|
|
11
|
+
MambuPy.rest.mambugroup
|
|
12
|
+
MambuPy.rest.mambuloan
|
|
13
|
+
MambuPy.rest.mamburepayment
|
|
14
|
+
MambuPy.rest.mambutransaction
|
|
15
|
+
MambuPy.rest.mambuproduct
|
|
16
|
+
MambuPy.rest.mambubranch
|
|
17
|
+
MambuPy.rest.mambucentre
|
|
18
|
+
MambuPy.rest.mambuactivity
|
|
19
|
+
MambuPy.rest.mambutask
|
|
20
|
+
MambuPy.rest.mambusaving
|
|
21
|
+
MambuPy.rest.mambusavingtransaction
|
|
22
|
+
MambuPy.rest.mambutransactionchannel
|
|
23
|
+
MambuPy.rest.mambuuser
|
|
24
|
+
MambuPy.rest.mamburoles
|
|
25
|
+
|
|
26
|
+
.. warning:: This package is soon to be deprecated. Use the :any:`MambuPy.api` package instead.
|
|
27
|
+
|
|
28
|
+
The REST API way is the currently most developed code on *MambuPy*.
|
|
29
|
+
|
|
30
|
+
Lives under the :any:`MambuPy.rest` package
|
|
31
|
+
|
|
32
|
+
It has a lot of objects which model some Mambu entity.
|
|
33
|
+
|
|
34
|
+
Every object inherits from the parent :any:`mambustruct.MambuStruct`
|
|
35
|
+
class. Start at the documentation there for more info on how it works.
|
|
36
|
+
|
|
37
|
+
.. todo:: Implement objects to make POST requests. The suggestion may be to use
|
|
38
|
+
MambuStruct, to default the __init__ to make a POST request (via the data
|
|
39
|
+
argument) and the attrs attribute to store the elements of the response that
|
|
40
|
+
Mambu gives when a successful POST is achieved.
|
|
41
|
+
.. todo:: Implement a lot of other Mambu entities available through GET requests on
|
|
42
|
+
Mambu.
|
|
43
|
+
.. todo:: Implement a lot of lacking GET filters on the currently available Mambu
|
|
44
|
+
objects, inside the urlfuncs on the mambuutil module.
|
|
45
|
+
.. todo:: A lot of TODO comments are inserted inside the pydocs of the code
|
|
46
|
+
itself. Please read them for suggestions on work need to be done.
|
|
47
|
+
"""
|
|
48
|
+
|
|
49
|
+
from .. import mambuconfig, mambuutil
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# coding: utf-8
|
|
2
|
+
"""Mambu Activity objects.
|
|
3
|
+
|
|
4
|
+
.. autosummary::
|
|
5
|
+
:nosignatures:
|
|
6
|
+
:toctree: _autosummary
|
|
7
|
+
|
|
8
|
+
MambuActivity holds a mambu activity. Don't instantiate this class
|
|
9
|
+
directly. Look at MambuActivity pydoc for further info.
|
|
10
|
+
|
|
11
|
+
MambuActivities holds a list of activities.
|
|
12
|
+
|
|
13
|
+
Uses mambugeturl.getactivitiesurl as default urlfunc
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
from ..mambugeturl import getactivitiesurl
|
|
18
|
+
from .mambustruct import MambuStruct
|
|
19
|
+
from .mamburestutils import MambuStructIterator
|
|
20
|
+
|
|
21
|
+
mod_urlfunc = getactivitiesurl
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class MambuActivity(MambuStruct):
|
|
25
|
+
"""A loan Activity from Mambu.
|
|
26
|
+
|
|
27
|
+
Don't instantiate this class directly. It's mostly used by
|
|
28
|
+
MambuActivities to configure each of its elements as
|
|
29
|
+
MambuActivity objects. There's no suitable urlfunc to use to
|
|
30
|
+
retrieve just a specific transaction from a loan account. In fact,
|
|
31
|
+
you can look at the code of MambuActivities.convert_dict_to_attrs(),
|
|
32
|
+
it uses urlfunc and entid = None , so no connection to Mambu will be
|
|
33
|
+
made, never, for any particular MambuActivity object.
|
|
34
|
+
"""
|
|
35
|
+
|
|
36
|
+
def __init__(self, urlfunc=mod_urlfunc, entid="", *args, **kwargs):
|
|
37
|
+
"""Tasks done here:
|
|
38
|
+
|
|
39
|
+
Just initializes the MambuStruct.
|
|
40
|
+
"""
|
|
41
|
+
MambuStruct.__init__(self, urlfunc, entid, *args, **kwargs)
|
|
42
|
+
|
|
43
|
+
def __repr__(self):
|
|
44
|
+
"""Instead of the default id given by the parent class, shows
|
|
45
|
+
the transactionid of the transaction.
|
|
46
|
+
"""
|
|
47
|
+
try:
|
|
48
|
+
return self.__class__.__name__ + " - activityid: %s" % self["activity"]
|
|
49
|
+
except KeyError:
|
|
50
|
+
return self.__class__.__name__ + " - activityid: %s" % self["activity"]
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
class MambuActivities(MambuStruct):
|
|
54
|
+
"""A list of loan Activities from Mambu."""
|
|
55
|
+
|
|
56
|
+
def __init__(self, urlfunc=mod_urlfunc, entid="", *args, **kwargs):
|
|
57
|
+
MambuStruct.__init__(self, urlfunc, entid, *args, **kwargs)
|
|
58
|
+
|
|
59
|
+
def __iter__(self):
|
|
60
|
+
return MambuStructIterator(self.attrs)
|
|
61
|
+
|
|
62
|
+
def convert_dict_to_attrs(self, *args, **kwargs):
|
|
63
|
+
"""The trick for iterable Mambu Objects comes here:
|
|
64
|
+
|
|
65
|
+
You iterate over each element of the responded List from Mambu,
|
|
66
|
+
and create a Mambu Activity object for each one, initializing
|
|
67
|
+
them one at a time, and changing the attrs attribute (which just
|
|
68
|
+
holds a list of plain dictionaries) with a MambuActivity just
|
|
69
|
+
created.
|
|
70
|
+
|
|
71
|
+
"""
|
|
72
|
+
for n, a in enumerate(self.attrs):
|
|
73
|
+
# ok ok, I'm modifying elements of a list while iterating it. BAD PRACTICE!
|
|
74
|
+
try:
|
|
75
|
+
params = self.params
|
|
76
|
+
except AttributeError:
|
|
77
|
+
params = {}
|
|
78
|
+
kwargs.update(params)
|
|
79
|
+
try:
|
|
80
|
+
self.mambuactivityclass
|
|
81
|
+
except AttributeError:
|
|
82
|
+
self.mambuactivityclass = MambuActivity
|
|
83
|
+
|
|
84
|
+
activity = self.mambuactivityclass(urlfunc=None, entid=None, *args, **kwargs)
|
|
85
|
+
activity.init(a, *args, **kwargs)
|
|
86
|
+
activity._MambuStruct__urlfunc = getactivitiesurl
|
|
87
|
+
self.attrs[n] = activity
|