Skip to content

Commit e1f1805

Browse files
authored
chore(code) better use of generic in entity manager (#283)
1 parent 8c5bf26 commit e1f1805

20 files changed

+66
-50
lines changed

cloudfoundry_client/v3/apps.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
from cloudfoundry_client.client import CloudFoundryClient
88

99

10-
class AppManager(EntityManager):
10+
class AppManager(EntityManager[Entity]):
1111
def __init__(self, target_endpoint: str, client: "CloudFoundryClient"):
1212
super(AppManager, self).__init__(target_endpoint, client, "/v3/apps")
1313

cloudfoundry_client/v3/buildpacks.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from cloudfoundry_client.client import CloudFoundryClient
77

88

9-
class BuildpackManager(EntityManager):
9+
class BuildpackManager(EntityManager[Entity]):
1010
def __init__(self, target_endpoint: str, client: "CloudFoundryClient"):
1111
super(BuildpackManager, self).__init__(target_endpoint, client, "/v3/buildpacks")
1212

cloudfoundry_client/v3/domains.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ def __init__(self, target_endpoint: str, client: "CloudFoundryClient", **kwargs)
1919
)
2020

2121

22-
class DomainManager(EntityManager):
22+
class DomainManager(EntityManager[Domain]):
2323
def __init__(self, target_endpoint: str, client: "CloudFoundryClient"):
2424
super(DomainManager, self).__init__(target_endpoint, client, "/v3/domains", Domain)
2525

cloudfoundry_client/v3/entities.py

Lines changed: 44 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import functools
22
from collections.abc import Callable
33
from json import JSONDecodeError
4-
from typing import Any, TypeVar, TYPE_CHECKING, Type
4+
from typing import Any, TypeVar, TYPE_CHECKING, Type, Generic
55
from urllib.parse import quote, urlparse
66

77
from requests import Response
@@ -111,30 +111,42 @@ def __init__(self, *guids: str):
111111
self.guids = list(guids)
112112

113113

114-
ENTITY_TYPE = TypeVar("ENTITY_TYPE", bound=Entity)
114+
ENTITY_TYPE = TypeVar("ENTITY_TYPE", bound=Entity, covariant=True)
115115

116116

117-
class EntityManager(object):
118-
def __init__(self, target_endpoint: str, client: "CloudFoundryClient", entity_uri: str, entity_type: ENTITY_TYPE = Entity):
117+
class EntityManager(Generic[ENTITY_TYPE]):
118+
def __init__(
119+
self,
120+
target_endpoint: str,
121+
client: "CloudFoundryClient",
122+
entity_uri: str,
123+
entity_type: type[ENTITY_TYPE] = Entity
124+
):
119125
self.target_endpoint = target_endpoint
120126
self.entity_uri = entity_uri
121127
self.client = client
122128
self.entity_type = entity_type
123129

124-
def _post(self, url: str, data: dict | None = None, files: Any = None, entity_type: ENTITY_TYPE = None) -> Entity:
125-
response = self.client.post(url, json=data, files=files)
126-
return self._read_response(response, entity_type)
127-
128-
def _get(self, url: str, entity_type: ENTITY_TYPE | None = None, **kwargs) -> Entity:
130+
def _get(self, url: str, entity_type: type[ENTITY_TYPE] | None = None, **kwargs) -> ENTITY_TYPE:
129131
url_requested = EntityManager._get_url_with_encoded_params(url, **kwargs)
130132
response = self.client.get(url_requested)
131133
return self._read_response(response, entity_type)
132134

133-
def _put(self, url: str, data: dict, entity_type: ENTITY_TYPE | None = None) -> Entity:
135+
def _post(
136+
self,
137+
url: str,
138+
data: dict | None = None,
139+
entity_type: type[ENTITY_TYPE] | None = None,
140+
files: Any = None
141+
) -> ENTITY_TYPE:
142+
response = self.client.post(url, json=data, files=files)
143+
return self._read_response(response, entity_type)
144+
145+
def _put(self, url: str, data: dict, entity_type: type[ENTITY_TYPE] | None = None) -> ENTITY_TYPE:
134146
response = self.client.put(url, json=data)
135147
return self._read_response(response, entity_type)
136148

137-
def _patch(self, url: str, data: dict, entity_type: ENTITY_TYPE | None = None) -> Entity:
149+
def _patch(self, url: str, data: dict, entity_type: type[ENTITY_TYPE] | None = None) -> ENTITY_TYPE:
138150
response = self.client.patch(url, json=data)
139151
return self._read_response(response, entity_type)
140152

@@ -166,21 +178,21 @@ def _extract_job_guid(job_location):
166178
job_guid = job_url.path.rsplit("/", 1)[-1]
167179
return job_guid
168180

169-
def _list(self, requested_path: str, entity_type: ENTITY_TYPE | None = None, **kwargs) -> Pagination[Entity]:
181+
def _list(self, requested_path: str, entity_type: type[ENTITY_TYPE] | None = None, **kwargs) -> Pagination[ENTITY_TYPE]:
170182
url_requested = EntityManager._get_url_with_encoded_params("%s%s" % (self.target_endpoint, requested_path), **kwargs)
171183
response_json = self._read_response(self.client.get(url_requested), JsonObject)
172184
return self._pagination(response_json, entity_type)
173185

174-
def _attempt_to_paginate(self, url_requested: str, entity_type: ENTITY_TYPE | None = None) \
175-
-> Pagination[Entity] | Entity:
186+
def _attempt_to_paginate(self, url_requested: str, entity_type: type[ENTITY_TYPE] | None = None) \
187+
-> Pagination[ENTITY_TYPE] | ENTITY_TYPE:
176188
response_json = self._read_response(self.client.get(url_requested), JsonObject)
177189
if "resources" in response_json:
178190
return self._pagination(response_json, entity_type)
179191
else:
180192
return response_json
181193

182-
def _pagination(self, page: JsonObject, entity_type: ENTITY_TYPE | None = None) -> Pagination[Entity]:
183-
def _entity(json_object: JsonObject) -> Entity:
194+
def _pagination(self, page: JsonObject, entity_type: type[ENTITY_TYPE] | None = None) -> Pagination[ENTITY_TYPE]:
195+
def _entity(json_object: JsonObject) -> ENTITY_TYPE:
184196
return self._entity(json_object, entity_type)
185197

186198
return Pagination(page,
@@ -200,54 +212,58 @@ def _next_page(self, current_page: JsonObject) -> JsonObject | None:
200212
return None
201213
return self._read_response(self.client.get(current_page["pagination"]["next"]["href"]), JsonObject)
202214

203-
def _create(self, data: dict) -> Entity:
215+
def _create(self, data: dict) -> ENTITY_TYPE:
204216
url = "%s%s" % (self.target_endpoint, self.entity_uri)
205217
return self._post(url, data=data)
206218

207-
def _upload_bits(self, resource_id: str, filename: str) -> Entity:
219+
def _upload_bits(self, resource_id: str, filename: str) -> ENTITY_TYPE:
208220
url = "%s%s/%s/upload" % (self.target_endpoint, self.entity_uri, resource_id)
209221
files = {"bits": (filename, open(filename, "rb"))}
210222
return self._post(url, files=files)
211223

212-
def _update(self, resource_id: str, data: dict) -> Entity:
224+
def _update(self, resource_id: str, data: dict) -> ENTITY_TYPE:
213225
url = "%s%s/%s" % (self.target_endpoint, self.entity_uri, resource_id)
214226
return self._patch(url, data)
215227

216-
def __iter__(self) -> Pagination[Entity]:
228+
def __iter__(self) -> Pagination[ENTITY_TYPE]:
217229
return self.list()
218230

219-
def __getitem__(self, entity_guid) -> Entity:
231+
def __getitem__(self, entity_guid) -> ENTITY_TYPE:
220232
return self.get(entity_guid)
221233

222234
def __len__(self):
223235
return self.len()
224236

225237
def len(self, **kwargs):
226238
url_requested = EntityManager._get_url_with_encoded_params("%s%s" % (self.target_endpoint, self.entity_uri), **kwargs)
227-
response_json = self._read_response(self.client.get(url_requested, JsonObject))
239+
response_json = self._read_response(self.client.get(url_requested), JsonObject)
228240
pagination = response_json.get("pagination")
229241
if pagination is not None:
230242
return pagination.get("total_results", 0)
231243
else:
232244
return 0
233245

234-
def list(self, **kwargs) -> Pagination[Entity]:
246+
def list(self, **kwargs) -> Pagination[ENTITY_TYPE]:
235247
return self._list(self.entity_uri, **kwargs)
236248

237-
def get_first(self, **kwargs) -> Entity | None:
249+
def get_first(self, **kwargs) -> ENTITY_TYPE | None:
238250
kwargs.setdefault("per_page", 1)
239251
for entity in self._list(self.entity_uri, **kwargs):
240252
return entity
241253
return None
242254

243-
def get(self, entity_id: str, *extra_paths, **kwargs) -> Entity:
255+
def get(self, entity_id: str, *extra_paths, **kwargs) -> ENTITY_TYPE:
244256
if len(extra_paths) == 0:
245257
requested_path = "%s%s/%s" % (self.target_endpoint, self.entity_uri, entity_id)
246258
else:
247259
requested_path = "%s%s/%s/%s" % (self.target_endpoint, self.entity_uri, entity_id, "/".join(extra_paths))
248260
return self._get(requested_path, **kwargs)
249261

250-
def _read_response(self, response: Response, entity_type: ENTITY_TYPE | None) -> JsonObject | Entity:
262+
def _read_response(
263+
self,
264+
response: Response,
265+
entity_type: type[ENTITY_TYPE] | type[JsonObject] | None
266+
) -> JsonObject | ENTITY_TYPE:
251267
try:
252268
result = response.json(object_pairs_hook=JsonObject)
253269
except JSONDecodeError:
@@ -289,7 +305,7 @@ def _include_resources(self, resource: JsonObject, result: JsonObject) -> None:
289305
def _get_entity_type(entity_name: str) -> Type[ENTITY_TYPE]:
290306
return Entity
291307

292-
def _entity(self, result: JsonObject, entity_type: ENTITY_TYPE | None) -> JsonObject | Entity:
308+
def _entity(self, result: JsonObject, entity_type: type[ENTITY_TYPE] | None) -> JsonObject | ENTITY_TYPE:
293309
if "guid" in result or ("links" in result and "job" in result["links"]):
294310
return (entity_type or self.entity_type)(self.target_endpoint, self.client, **result)
295311
else:
@@ -301,7 +317,7 @@ def _append_encoded_parameter(parameters: list[str], args: tuple[str, Any]) -> l
301317
parameter_name, parameter_value = args[0], args[1]
302318
if isinstance(parameter_value, (list, tuple)):
303319
parameters.append("%s=%s" % (parameter_name, quote(",".join(parameter_value))))
304-
elif isinstance(parameter_value, (dict)) and parameter_name == "fields":
320+
elif isinstance(parameter_value, dict) and parameter_name == "fields":
305321
for resource, key in parameter_value.items():
306322
parameters.append("%s[%s]=%s" % (parameter_name, resource, ",".join(key)))
307323
else:

cloudfoundry_client/v3/feature_flags.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from cloudfoundry_client.client import CloudFoundryClient
77

88

9-
class FeatureFlagManager(EntityManager):
9+
class FeatureFlagManager(EntityManager[Entity]):
1010
def __init__(self, target_endpoint: str, client: "CloudFoundryClient"):
1111
super(FeatureFlagManager, self).__init__(target_endpoint, client, "/v3/feature_flags")
1212

cloudfoundry_client/v3/isolation_segments.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from cloudfoundry_client.client import CloudFoundryClient
77

88

9-
class IsolationSegmentManager(EntityManager):
9+
class IsolationSegmentManager(EntityManager[Entity]):
1010
def __init__(self, target_endpoint: str, client: "CloudFoundryClient"):
1111
super(IsolationSegmentManager, self).__init__(target_endpoint, client, "/v3/isolation_segments")
1212

cloudfoundry_client/v3/jobs.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ class JobTimeout(Exception):
1313
pass
1414

1515

16-
class JobManager(EntityManager):
16+
class JobManager(EntityManager[Entity]):
1717
def __init__(self, target_endpoint: str, client: "CloudFoundryClient"):
1818
super(JobManager, self).__init__(target_endpoint, client, "/v3/jobs")
1919

cloudfoundry_client/v3/organization_quotas.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ class DomainsQuota:
3333
total_domains: int
3434

3535

36-
class OrganizationQuotaManager(EntityManager):
36+
class OrganizationQuotaManager(EntityManager[Entity]):
3737
def __init__(self, target_endpoint: str, client: "CloudFoundryClient"):
3838
super().__init__(target_endpoint, client, "/v3/organization_quotas")
3939

cloudfoundry_client/v3/organizations.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from cloudfoundry_client.client import CloudFoundryClient
77

88

9-
class OrganizationManager(EntityManager):
9+
class OrganizationManager(EntityManager[Entity]):
1010
def __init__(self, target_endpoint: str, client: "CloudFoundryClient"):
1111
super(OrganizationManager, self).__init__(target_endpoint, client, "/v3/organizations")
1212

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
from typing import TYPE_CHECKING
22

3-
from cloudfoundry_client.v3.entities import EntityManager
3+
from cloudfoundry_client.v3.entities import EntityManager, Entity
44

55
if TYPE_CHECKING:
66
from cloudfoundry_client.client import CloudFoundryClient
77

88

9-
class ProcessManager(EntityManager):
9+
class ProcessManager(EntityManager[Entity]):
1010
def __init__(self, target_endpoint: str, client: "CloudFoundryClient"):
1111
super(ProcessManager, self).__init__(target_endpoint, client, "/v3/processes")

0 commit comments

Comments
 (0)