masstack-python-client 0.0.5__py3-none-any.whl → 0.1.1__py3-none-any.whl

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.
@@ -1,4 +1,4 @@
1
- __version__ = "0.0.5"
1
+ __version__ = "0.1.1"
2
2
  __homepage__ = "https://somconnexio.coop/"
3
3
  __author__ = "Borja Gimeno <borja.gimeno@somconnexio.coop>"
4
4
  __license__ = "GPL-3.0-only"
@@ -0,0 +1,59 @@
1
+ from typing import Optional, Union
2
+ from masstack_python_client.client import MasstackClient
3
+
4
+
5
+ class BaseResource:
6
+ __abstract__ = True
7
+
8
+ required_class_attributes = (
9
+ "_api_path",
10
+ "_api_domain",
11
+ "_version",
12
+ )
13
+
14
+ def __init_subclass__(cls, **kwargs):
15
+ super().__init_subclass__(**kwargs)
16
+
17
+ if cls.__dict__.get("__abstract__", False):
18
+ return
19
+
20
+ missing = [
21
+ attr for attr in cls.required_class_attributes if not hasattr(cls, attr)
22
+ ]
23
+
24
+ if missing:
25
+ raise TypeError(
26
+ f"{cls.__name__} missing required class attributes: "
27
+ f"{', '.join(missing)}"
28
+ )
29
+
30
+ @classmethod
31
+ def _get_endpoint(cls, suffix: str = "") -> str:
32
+ parts = [
33
+ cls._api_path,
34
+ getattr(cls, "_api_subpath", ""),
35
+ suffix,
36
+ ]
37
+ return "/".join(part.strip("/") for part in parts if part)
38
+
39
+ @classmethod
40
+ def _request(
41
+ cls,
42
+ *,
43
+ method: str,
44
+ suffix: Optional[str] = "",
45
+ header: Optional[dict] = None,
46
+ data: Optional[dict] = None,
47
+ params: Optional[dict] = None,
48
+ ) -> Union[dict, list]:
49
+ client = MasstackClient()
50
+ func = getattr(client, method)
51
+
52
+ return func(
53
+ api=cls._api_domain,
54
+ version=cls._version,
55
+ endpoint=cls._get_endpoint(suffix),
56
+ params=params,
57
+ data=data,
58
+ header=header,
59
+ )
@@ -1,5 +1,9 @@
1
1
  from typing import Optional, List
2
- from masstack_python_client.client import MasstackClient
2
+ from masstack_python_client.resources.base import BaseResource
3
+ from masstack_python_client.resources.enums.customer_type_name import CustomerTypeName
4
+ from masstack_python_client.resources.enums.sale_type_name import SaleTypeName
5
+ from masstack_python_client.resources.enums.technology_name import TechnologyName
6
+ from masstack_python_client.resources.models.bundled import BundledProduct
3
7
  from masstack_python_client.resources.enums.bundled_product_category import (
4
8
  BundleCategory,
5
9
  )
@@ -9,50 +13,25 @@ from masstack_python_client.resources.enums.commercial_segment_name import (
9
13
  from masstack_python_client.resources.enums.customer_segment_name import (
10
14
  CustomerSegmentName,
11
15
  )
12
- from masstack_python_client.resources.enums.customer_type_name import CustomerTypeName
13
- from masstack_python_client.resources.enums.sale_type_name import SaleTypeName
14
- from masstack_python_client.resources.enums.technology_name import TechnologyName
15
- from masstack_python_client.resources.models.bundled import BundledProduct
16
+ from masstack_python_client.resources.utils.normalize import normalize
16
17
 
17
18
 
18
- class CatalogueResource:
19
+ class CatalogueResource(BaseResource):
19
20
  """Support sales and post-sales operations from catalogue perspective
20
21
  https://developers.masstack.com/en/docs/apis_catalogue_doc_swagger/2/apioverview/
21
22
  """
22
23
 
24
+ __abstract__ = True
23
25
  _api_domain = "catalogue"
24
26
 
25
27
 
26
28
  class BundledProducts(CatalogueResource):
29
+ __abstract__ = True
27
30
  _api_path = "bundled_products"
28
31
  _version = "v2"
29
32
 
30
- @classmethod
31
- def _get_endpoint(cls, subpath: str) -> str:
32
- return f"{cls._api_path}/{subpath}"
33
-
34
- @classmethod
35
- def _request(
36
- cls,
37
- method: str,
38
- subpath: str,
39
- params: Optional[dict] = None,
40
- data: Optional[dict] = None,
41
- ) -> dict:
42
- client = MasstackClient()
43
- func = getattr(client, method)
44
-
45
- return func(
46
- api=cls._api_domain,
47
- version=cls._version,
48
- endpoint=cls._get_endpoint(subpath),
49
- params=params,
50
- data=data,
51
- )
52
-
53
33
 
54
34
  class Sellable(BundledProducts):
55
-
56
35
  _api_subpath = "sellable"
57
36
 
58
37
  @classmethod
@@ -82,7 +61,7 @@ class Sellable(BundledProducts):
82
61
  sale_type_name(SaleTypeName): sale type name
83
62
 
84
63
  Returns:
85
- BundledProduct
64
+ List[BundledProduct]
86
65
 
87
66
  """
88
67
  params = {
@@ -95,15 +74,7 @@ class Sellable(BundledProducts):
95
74
  "customer_type_name": customer_type_name,
96
75
  "sale_type_name": sale_type_name,
97
76
  }
98
- sellable_bundled_products = cls._request(
99
- "get",
100
- cls._api_subpath,
101
- {
102
- k: (v.value if hasattr(v, "value") else v)
103
- for k, v in params.items()
104
- if v is not None
105
- },
106
- )
77
+ sellable_bundled_products = cls._request(method="get", params=normalize(params))
107
78
  return [
108
79
  BundledProduct.from_dict(**sellable_bundled_product)
109
80
  for sellable_bundled_product in sellable_bundled_products
@@ -1,7 +1,7 @@
1
- from typing import Optional
2
1
  from dataclasses import asdict
3
-
4
- from masstack_python_client.client import MasstackClient
2
+ from masstack_python_client.resources.base import BaseResource
3
+ from masstack_python_client.resources.models.user import UserData
4
+ from masstack_python_client.resources.utils.normalize import normalize
5
5
  from masstack_python_client.resources.enums.document_type_search import (
6
6
  DocumentTypeSearch,
7
7
  )
@@ -9,37 +9,17 @@ from masstack_python_client.resources.models.signup import (
9
9
  SignupRequestData,
10
10
  SignupsResponseData,
11
11
  )
12
- from masstack_python_client.resources.models.user import UserData
13
- from masstack_python_client.resources.utils.serialize import remove_none
14
12
 
15
13
 
16
- class CustomersResource:
14
+ class CustomersResource(BaseResource):
17
15
  """Provide the necessary functionality to be able to give
18
16
  E2E coverage to the entire life-cycle of a client
19
17
  https://developers.masstack.com/en/docs/apis_customers_doc_swagger/2/apioverview
20
18
  """
21
19
 
20
+ __abstract__ = True
22
21
  _api_domain = "customers"
23
22
 
24
- @classmethod
25
- def _request(
26
- cls,
27
- method: str,
28
- endpoint: str,
29
- params: Optional[dict] = None,
30
- data: Optional[dict] = None,
31
- ) -> dict:
32
- client = MasstackClient()
33
- func = getattr(client, method)
34
-
35
- return func(
36
- api=cls._api_domain,
37
- version=cls._version,
38
- endpoint=endpoint,
39
- params=params,
40
- data=data,
41
- )
42
-
43
23
 
44
24
  class SignupsResource(CustomersResource):
45
25
  _api_path = "signups"
@@ -55,10 +35,9 @@ class SignupsResource(CustomersResource):
55
35
  Returns:
56
36
  SignupsResponseData
57
37
  """
58
- payload = remove_none(asdict(customer_data))
38
+ payload = normalize(asdict(customer_data))
59
39
  result = cls._request(
60
40
  method="post",
61
- endpoint=cls._api_path,
62
41
  data=payload,
63
42
  )
64
43
 
@@ -86,10 +65,7 @@ class Users(CustomersResource):
86
65
  user id.
87
66
  """
88
67
  data = {"document_type": doc_type.value, "document": doc}
89
-
90
- return cls._request(method="post", endpoint=f"{cls._api_path}/tree", data=data)[
91
- "id"
92
- ]
68
+ return cls._request(method="post", suffix="tree", data=data)["id"]
93
69
 
94
70
  @classmethod
95
71
  def get_user_by_id(cls, user_id: str) -> dict:
@@ -102,5 +78,5 @@ class Users(CustomersResource):
102
78
  Returns:
103
79
  UserData
104
80
  """
105
- user = cls._request(method="get", endpoint=f"{cls._api_path}/{user_id}")
81
+ user = cls._request(method="get", suffix=user_id)
106
82
  return UserData.from_dict(**user)
@@ -0,0 +1,6 @@
1
+ from enum import Enum
2
+
3
+
4
+ class DonorLineType(Enum):
5
+ POSTPAID = "C"
6
+ PREPAID = "P"
@@ -0,0 +1,6 @@
1
+ from enum import Enum
2
+
3
+
4
+ class OperationType(Enum):
5
+ INSTANT = 1
6
+ SCHEDULED = 2
@@ -1,7 +1,8 @@
1
1
  import os
2
- from typing import Optional, List
3
- from masstack_python_client.client import MasstackClient
2
+ from typing import Optional, List, Union
3
+ from masstack_python_client.resources.base import BaseResource
4
4
  from masstack_python_client.resources.enums.technology import Technology
5
+ from masstack_python_client.resources.models.portability import PortabilityData
5
6
  from masstack_python_client.resources.models.address import (
6
7
  BuildingData,
7
8
  ClarifierData,
@@ -9,62 +10,35 @@ from masstack_python_client.resources.models.address import (
9
10
  StreetData,
10
11
  UnitData,
11
12
  )
12
- from masstack_python_client.resources.models.portability import PortabilityData
13
-
14
13
 
15
14
  """
16
- FeasibilityResource
17
- ├── Coverage
18
- ├── Streets
19
- │ ├── Buildings
20
- └── Units
21
- └── Portability
22
- └── PortabilityCheck
15
+ BaseResource
16
+ └──FeasibilityResource
17
+ ├── Coverage
18
+ │ ├── Streets
19
+ ├── Buildings
20
+ └── Units
21
+ └── Portability
22
+ └── PortabilityCheck
23
23
  """
24
24
 
25
25
 
26
- class FeasibilityResource:
26
+ class FeasibilityResource(BaseResource):
27
27
  """Resource for feasibility operations
28
28
  https://developers.masstack.com/en/docs/apis_feasibility_doc_swagger/1/apioverview
29
29
  """
30
30
 
31
+ __abstract__ = True
31
32
  _api_domain = "feasibility"
32
33
 
33
- @classmethod
34
- def _get_endpoint(cls, suffix: str) -> str:
35
- return f"{cls._api_path}/{cls._api_subpath}{suffix}"
36
-
37
- @classmethod
38
- def _request(
39
- cls,
40
- *,
41
- method: str,
42
- suffix: Optional[str] = "",
43
- header: Optional[dict] = None,
44
- data: Optional[dict] = None,
45
- params: Optional[dict] = None,
46
- ) -> dict | list:
47
- client = MasstackClient()
48
- func = getattr(client, method)
49
-
50
- return func(
51
- api=cls._api_domain,
52
- version=cls._version,
53
- endpoint=cls._get_endpoint(suffix),
54
- params=params,
55
- data=data,
56
- header=header,
57
- )
58
-
59
34
 
60
35
  class Portability(FeasibilityResource):
61
-
36
+ __abstract__ = True
62
37
  _api_path = "portability"
63
38
  _version = "v2"
64
39
 
65
40
 
66
41
  class PortabilityCheck(Portability):
67
-
68
42
  _api_subpath = "portabilityCheck"
69
43
 
70
44
  @classmethod
@@ -105,7 +79,7 @@ class PortabilityCheck(Portability):
105
79
 
106
80
 
107
81
  class Coverage(FeasibilityResource):
108
-
82
+ __abstract__ = True
109
83
  _api_path = "coverage"
110
84
  _version = "v1"
111
85
 
@@ -126,12 +100,11 @@ class Coverage(FeasibilityResource):
126
100
  }
127
101
 
128
102
  @classmethod
129
- def _request(cls, *, uuid: str, **kwargs) -> dict | list:
103
+ def _request(cls, *, uuid: str, **kwargs) -> Union[dict, list]:
130
104
  return super()._request(header=cls._get_header(uuid), **kwargs)
131
105
 
132
106
 
133
107
  class Streets(Coverage):
134
-
135
108
  _api_subpath = "streets"
136
109
 
137
110
  @classmethod
@@ -169,7 +142,7 @@ class Streets(Coverage):
169
142
  """
170
143
  clarifiers = cls._request(
171
144
  method="get",
172
- suffix=f"/clarifiers/{street_id}",
145
+ suffix=f"clarifiers/{street_id}",
173
146
  uuid=uuid,
174
147
  )
175
148
 
@@ -177,7 +150,6 @@ class Streets(Coverage):
177
150
 
178
151
 
179
152
  class Buildings(Coverage):
180
-
181
153
  _api_subpath = "buildings"
182
154
 
183
155
  @classmethod
@@ -218,7 +190,7 @@ class Buildings(Coverage):
218
190
  """
219
191
  building = cls._request(
220
192
  method="get",
221
- suffix=f"/{id}",
193
+ suffix=id,
222
194
  uuid=uuid,
223
195
  params={"unit_to_data": unit_to_data},
224
196
  )
@@ -257,7 +229,7 @@ class Buildings(Coverage):
257
229
 
258
230
  buildings = cls._request(
259
231
  method="post",
260
- suffix="/search",
232
+ suffix="search",
261
233
  uuid=uuid,
262
234
  data={
263
235
  "way_name": way_name,
@@ -273,7 +245,6 @@ class Buildings(Coverage):
273
245
 
274
246
 
275
247
  class Units(Coverage):
276
-
277
248
  _api_subpath = "units"
278
249
 
279
250
  @classmethod
@@ -293,7 +264,7 @@ class Units(Coverage):
293
264
  """
294
265
  unit = cls._request(
295
266
  method="get",
296
- suffix=f"/{unit_id}",
267
+ suffix=unit_id,
297
268
  uuid=uuid,
298
269
  params={"parent_coverage": parent_coverage},
299
270
  )
@@ -321,7 +292,7 @@ class Units(Coverage):
321
292
  """
322
293
  unit = cls._request(
323
294
  method="get",
324
- suffix="/extra",
295
+ suffix="extra",
325
296
  uuid=uuid,
326
297
  params={"id": unit_id, "territory_owner": territory_owner},
327
298
  )
@@ -1,4 +1,5 @@
1
1
  from dataclasses import dataclass
2
+ from typing import Optional
2
3
 
3
4
 
4
5
  @dataclass(frozen=True)
@@ -23,17 +24,21 @@ class PortabilityData:
23
24
  isPortable: bool
24
25
  installationRequired: bool
25
26
  operator: OperatorData
26
- installationInfo: InstallationInfoData
27
+ installationInfo: Optional[InstallationInfoData] = None
27
28
 
28
29
  @classmethod
29
30
  def from_dict(
30
31
  cls,
31
32
  operator,
32
- installationInformation,
33
+ installationInformation=None,
33
34
  **kwargs,
34
35
  ):
35
36
  return cls(
36
37
  operator=OperatorData(**operator),
37
- installationInfo=InstallationInfoData(**installationInformation),
38
+ installationInfo=(
39
+ InstallationInfoData(**installationInformation)
40
+ if installationInformation
41
+ else None
42
+ ),
38
43
  **kwargs,
39
44
  )
@@ -1,5 +1,8 @@
1
1
  from dataclasses import dataclass, field
2
- from typing import List, Dict, Any
2
+ from typing import Optional, List, Dict, Any
3
+
4
+ from masstack_python_client.resources.enums.donor_line_type import DonorLineType
5
+ from masstack_python_client.resources.enums.operation_type import OperationType
3
6
 
4
7
 
5
8
  @dataclass(frozen=True)
@@ -43,13 +46,33 @@ class Info:
43
46
  )
44
47
 
45
48
 
49
+ @dataclass(frozen=True)
50
+ class PortabilityInfo:
51
+ operator_id: str
52
+ internal_portability: bool
53
+ installation_required: bool
54
+ operation_type: Optional[OperationType] = OperationType.INSTANT
55
+ donor_line_type: Optional[DonorLineType] = DonorLineType.POSTPAID
56
+
57
+
46
58
  @dataclass(frozen=True)
47
59
  class Landline:
48
60
  product_id: int
49
61
  number: str
62
+ portability_info: Optional[PortabilityInfo] = None
50
63
  services: List = field(default_factory=list)
51
64
  wants_communications: bool = False
52
- # TODO portability_info
65
+
66
+ @classmethod
67
+ def from_dict(cls, product_id, number, portability_info=None, **data) -> "Landline":
68
+ return cls(
69
+ product_id,
70
+ number,
71
+ portability_info=(
72
+ PortabilityInfo(**portability_info) if portability_info else None
73
+ ),
74
+ **data,
75
+ )
53
76
 
54
77
 
55
78
  @dataclass(frozen=True)
@@ -58,9 +81,9 @@ class Ftth:
58
81
  connection_type: str = ""
59
82
  installer: str = "MM"
60
83
  wants_communications: bool = False
61
- # TODO access_reuse
62
- # TODO access_reuse_choice
63
- # TODO iua
84
+ access_reuse: str = None
85
+ access_reuse_choice: bool = False
86
+ iua: str = None
64
87
 
65
88
 
66
89
  @dataclass(frozen=True)
@@ -85,6 +108,6 @@ class Bundle:
85
108
  territory_owner,
86
109
  installation_info=info,
87
110
  delivery_info=info,
88
- landline=Landline(**data["land_line"]),
111
+ landline=Landline.from_dict(**data["land_line"]),
89
112
  ftth=Ftth(**data["ftth"]),
90
113
  )
@@ -1,14 +1,14 @@
1
- from typing import Optional
2
- from masstack_python_client.client import MasstackClient
1
+ from masstack_python_client.resources.base import BaseResource
3
2
  from masstack_python_client.resources.models.fixed_phone import FixedPhoneData
4
3
 
5
4
 
6
5
  "https://provision-inventory-network.sta.masstack.com/v1/orgs/marblanca/fixed/number"
7
6
 
8
7
 
9
- class ProvisionNetworkResource:
8
+ class ProvisionNetworkResource(BaseResource):
10
9
  """not documented"""
11
10
 
11
+ __abstract__ = True
12
12
  _api_domain = "provision-inventory-network"
13
13
 
14
14
 
@@ -16,29 +16,6 @@ class FixedPhone(ProvisionNetworkResource):
16
16
  _api_path = "fixed"
17
17
  _version = "v1"
18
18
 
19
- @classmethod
20
- def _get_endpoint(cls, subpath: str) -> str:
21
- return f"{cls._api_path}/{subpath}"
22
-
23
- @classmethod
24
- def _request(
25
- cls,
26
- method: str,
27
- subpath: str,
28
- params: Optional[dict] = None,
29
- data: Optional[dict] = None,
30
- ) -> dict:
31
- client = MasstackClient()
32
- func = getattr(client, method)
33
-
34
- return func(
35
- api=cls._api_domain,
36
- version=cls._version,
37
- endpoint=cls._get_endpoint(subpath),
38
- params=params,
39
- data=data,
40
- )
41
-
42
19
  @classmethod
43
20
  def get_number(cls, postal_code: str, state: str = "new"):
44
21
  """Obtain fixed numbering for sale.
@@ -51,9 +28,9 @@ class FixedPhone(ProvisionNetworkResource):
51
28
 
52
29
  """
53
30
  response = cls._request(
54
- "get",
55
- "number",
56
- {
31
+ method="get",
32
+ suffix="number",
33
+ params={
57
34
  "postal_code": postal_code,
58
35
  "state": state,
59
36
  },
@@ -0,0 +1,27 @@
1
+ from enum import Enum
2
+
3
+
4
+ def normalize(obj):
5
+ """Recursively prepare an object for API serialization.
6
+
7
+ Traverses dicts and lists removing None values and converting
8
+ Enum members to their primitive values.
9
+
10
+ Args:
11
+ obj: The object to normalize. Supported types:
12
+ - dict: filters out None values and recurses on remaining values.
13
+ - list: filters out None items and recurses on remaining items.
14
+ - Enum: returns its primitive value.
15
+ - Any other type: returned as-is.
16
+
17
+ Returns:
18
+ The serialized object, ready to be sent as an API payload.
19
+ """
20
+ if isinstance(obj, dict):
21
+ return {k: normalize(v) for k, v in obj.items() if v is not None}
22
+ elif isinstance(obj, list):
23
+ return [normalize(v) for v in obj if v is not None]
24
+ elif isinstance(obj, Enum):
25
+ return obj.value
26
+ else:
27
+ return obj
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: masstack-python-client
3
- Version: 0.0.5
3
+ Version: 0.1.1
4
4
  Summary: This Python API client provides access to masmovil core API domains
5
5
  Author-email: Borja Gimeno <borja.gimeno@somconnexio.coop>
6
6
  License: GPL-3.0-only
@@ -25,36 +25,37 @@ This Python API client provides access to masmovil core API domains.
25
25
 
26
26
  ## Resources
27
27
 
28
- * Feasibility
29
- - Coverage - find an address
30
- - Streets:
31
- - search: returns a list of street by text
32
- - get_building_info_by_street: returns a list of building info by street id
33
- - Buildings:
34
- - search: returns a list of buildings by text
35
- - multi_search: returns a list of buildings by request body
36
- - get: returns a building by id with a list of units
37
- - Units:
38
- - get: returns a unit by id with a list of coverages
39
- - get_coverage: returns coverage info for a unit id and territory_owner
40
- - Portability - Checks if a landline portability or an access transfer is allowed
41
- - PortabilityCheck:
42
- - check: Returns whether the portability process can be carried out and whether it requires a new installation
43
-
44
- * Customers
45
- - Signups - access to signups new clients
46
- - post new client
47
- - Users
48
- - returns customer tree data associated to a given document identification, email or number of the client.
49
- - returns user data by userId
50
-
51
- * Catalogue
52
- - bundled_products - access to bundled products
53
- - get sellable bundled products
54
-
55
- * Provision inventory network
56
- - fixed - Obtain fixed numbering for sale
57
- - get number
28
+ - **Feasibility**
29
+ - Coverage - find an address
30
+ - Streets:
31
+ - *search: returns a list of street by text*
32
+ - *get_building_info_by_street: returns a list of building info by street id*
33
+ - Buildings:
34
+ - *search: returns a list of buildings by text*
35
+ - *multi_search: returns a list of buildings by request body*
36
+ - *get: returns a building by id with a list of units*
37
+ - Units:
38
+ - *get: returns a unit by id with a list of coverages*
39
+ - *get_coverage: returns coverage info for a unit id and territory_owner*
40
+ - Portability - Checks if a landline portability or an access transfer is allowed
41
+ - PortabilityCheck:
42
+ - *check: Returns whether the portability process can be carried out and whether it requires a new* installation
43
+
44
+ - **Customers**
45
+ - Signups - access to signups new clients
46
+ - *post new client*
47
+ - Users
48
+ - *returns customer tree data associated to a given document identification, email or number of the client.*
49
+ - *returns user data by userId*
50
+
51
+ - **Catalogue**
52
+ - bundled_products - access to bundled products
53
+ - Sellable:
54
+ - *get: Returns sellable bundled products*
55
+
56
+ - **Provision inventory network**
57
+ - fixed - Obtain fixed numbering for sale
58
+ - *get number*
58
59
 
59
60
 
60
61
  ## Installation
@@ -1,4 +1,4 @@
1
- masstack_python_client/__init__.py,sha256=LglbAMxBWseiHlWgcEl_eDDUXuK1sHtH-Rx6_y6YVbU,154
1
+ masstack_python_client/__init__.py,sha256=cIbh6HfgSC2KVnbWlTpxEt9G647-wvmPvv5wR59YVqE,154
2
2
  masstack_python_client/client.py,sha256=5b52Q2ekABi7DlZPsNobcmaJXOKzZfhKE_kHvNEqE9Q,2496
3
3
  masstack_python_client/exceptions.py,sha256=HkX1cP4Ryeas59CzIVW8N5gmnRE1x0yQUQwS3tm9QZQ,2115
4
4
  masstack_python_client/auth/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -10,16 +10,19 @@ masstack_python_client/data/province_translation.csv,sha256=Jpd6jbjYaqeNOk9lUA3W
10
10
  masstack_python_client/data/street_type_translation.csv,sha256=2MGeTs0v6wVz2yRMyZUuoNOYA4NSqKGJCGYIRi9X8Ic,1791
11
11
  masstack_python_client/data/unit_translation.csv,sha256=34FPfaCC1eSmBfV0BbHSHJ-tktQk7YLlfT8tMxnfnys,194
12
12
  masstack_python_client/resources/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
13
- masstack_python_client/resources/catalogue.py,sha256=6evwB75NC2jRsTQ6Zz3-qmzNo9dFsQhdtAtYhwW9Zu0,4002
14
- masstack_python_client/resources/customers.py,sha256=9GTXQ5fiVosbAzK__uydZOBu9wXC9yO4pHufseHqD38,2924
15
- masstack_python_client/resources/feasibility.py,sha256=WSPprQFMoJAJFzlI65YLnt6AfErnfoziMbBqxpZYqGE,8974
16
- masstack_python_client/resources/provision.py,sha256=EkSgYz7xaAWPrILTcrDATK3spBCOdEKwnV4-TvRzLg4,1525
13
+ masstack_python_client/resources/base.py,sha256=yCzYXBjjyelWOF7lQsabtib662Goebx0h1OHJVv4OMs,1508
14
+ masstack_python_client/resources/catalogue.py,sha256=-9Jn_en0REEN-yknuzhrY4LsSeErxN89tPPIQpTIax0,3397
15
+ masstack_python_client/resources/customers.py,sha256=fSI1SN8U4uiyYEvJQtzpUgUTtqhx7fKjYKt6bfLrOvE,2397
16
+ masstack_python_client/resources/feasibility.py,sha256=eYGIUwMIkDIfrbgR69Um284UJh5KlR0HLOUp-0FcYKE,8425
17
+ masstack_python_client/resources/provision.py,sha256=SfMly7_19-yxXZRuqXaxRzpHUSVIjcxO_Oq7g_K5d2A,997
17
18
  masstack_python_client/resources/enums/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
18
19
  masstack_python_client/resources/enums/bundled_product_category.py,sha256=0rEsOud4kyDVX07DQ15C_DPcw8hZy84bAVj8j7nT22k,388
19
20
  masstack_python_client/resources/enums/commercial_segment_name.py,sha256=94yOXfHNCcZNCoR9ELQ-x2tarNin7gdYBVZ-CTzJsGA,101
20
21
  masstack_python_client/resources/enums/customer_segment_name.py,sha256=NSQUUSUGL-vYEUe4w9deym9Vuez-QGn26hs_2fOojh0,163
21
22
  masstack_python_client/resources/enums/customer_type_name.py,sha256=mMdZh0D7qLDMxe6QYVQLGMqHqQMBAnZaPkjgE8q_D9Q,99
22
23
  masstack_python_client/resources/enums/document_type_search.py,sha256=pniXpUA_odqeKyxS6yYiN2uje0-F1kKXXBLOk0F8UTQ,136
24
+ masstack_python_client/resources/enums/donor_line_type.py,sha256=VKf4aUgSa1jXGnY062tUPreKA1PPvFvO_bXiJO9Jf5I,88
25
+ masstack_python_client/resources/enums/operation_type.py,sha256=cBfWs59HhvglpJcrTPwybsuFvsv0FTm0xW7RvMvweYQ,85
23
26
  masstack_python_client/resources/enums/sale_type_name.py,sha256=NWl5j_SkbysOGVBn4-c7gVbzynOiE44Aqj34n_1v_sU,183
24
27
  masstack_python_client/resources/enums/technology.py,sha256=ipHLhdY2EMQgmeDzJ0LnvWvdiG_Oq-JHuEb5ZIx5x3g,106
25
28
  masstack_python_client/resources/enums/technology_name.py,sha256=7h8LUyZ-2XHAxOZXelUkkFifmk9dCcwmBbWueFABfQ4,90
@@ -29,13 +32,13 @@ masstack_python_client/resources/models/client_address.py,sha256=7WBiPTce2X6uZUV
29
32
  masstack_python_client/resources/models/client_attribute.py,sha256=rZlLjJeBVD6IpXbSEucujTqcmHhqoJGRTOV1wqyStak,697
30
33
  masstack_python_client/resources/models/client_payment.py,sha256=yMGMTuk_07-TzXWO89sCaaZv8soTO9cT0TzfV3xQa1o,262
31
34
  masstack_python_client/resources/models/fixed_phone.py,sha256=ihF-iICz89eVhkeyRsX3pXYkODlXRpYPGJLiFiTBilM,98
32
- masstack_python_client/resources/models/portability.py,sha256=ZO7la2BDabw6aLQhTxW0d9TZ3Iu9Cc4Kvf1WxrliiJo,775
33
- masstack_python_client/resources/models/products.py,sha256=cIuUlEKs0OfvBXtYxxUwG4vibfAlZL4uVBK7-nAL9rw,1831
35
+ masstack_python_client/resources/models/portability.py,sha256=64WjYLyxDCNgwzmqiDgMHnfouwIyxPmQKcaBZGT50L0,926
36
+ masstack_python_client/resources/models/products.py,sha256=dSFZ2Cdn1xbEXlklcUr9qHfTj9tnTJcdYIcsTlHgmoc,2657
34
37
  masstack_python_client/resources/models/signup.py,sha256=Hvo5nZce1ikpUUMEoLt_2g2HipHwh4XRIz344X8_IJk,2018
35
38
  masstack_python_client/resources/models/user.py,sha256=N5mwuZN0Saxiro2UXYcCxLL6jrpIU83crHhmrdAcgE8,1080
36
- masstack_python_client/resources/utils/serialize.py,sha256=F6JxqR2M9HH0TpYKaJritnppWkYlpPztZ9ZC43FdPLg,251
37
- masstack_python_client-0.0.5.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
38
- masstack_python_client-0.0.5.dist-info/METADATA,sha256=I_UMFcemF9efNV1wjDrsrT5Di2e6nhy9jA6CPuQBttk,4154
39
- masstack_python_client-0.0.5.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
40
- masstack_python_client-0.0.5.dist-info/top_level.txt,sha256=q_iYlqJq22lhg_2O2iktARr7Mzz3QfjaW4l6J4vwyE8,23
41
- masstack_python_client-0.0.5.dist-info/RECORD,,
39
+ masstack_python_client/resources/utils/normalize.py,sha256=3XXrh4WxujpoxouKoTP1WZQomQhuirk6KW_3ZYsvBGQ,901
40
+ masstack_python_client-0.1.1.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
41
+ masstack_python_client-0.1.1.dist-info/METADATA,sha256=49OZS-pIpZySj6M4W3e3EMWmY82NM6e7zyIby9IkrCU,4076
42
+ masstack_python_client-0.1.1.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
43
+ masstack_python_client-0.1.1.dist-info/top_level.txt,sha256=q_iYlqJq22lhg_2O2iktARr7Mzz3QfjaW4l6J4vwyE8,23
44
+ masstack_python_client-0.1.1.dist-info/RECORD,,
@@ -1,7 +0,0 @@
1
- def remove_none(obj):
2
- if isinstance(obj, dict):
3
- return {k: remove_none(v) for k, v in obj.items() if v is not None}
4
- elif isinstance(obj, list):
5
- return [remove_none(v) for v in obj if v is not None]
6
- else:
7
- return obj