Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit91c4f18

Browse files
igorp-collaboranejch
authored andcommitted
feat(api): Make RESTManager generic on RESTObject class
Currently mixins like ListMixin are type hinted to return baseRESTObject instead of a specific class like `MergeRequest`.The GetMixin and GetWithoutIdMixin solve this problem by defininga new `get` method for every defined class. However, this createsa lot of duplicated code.Make RESTManager use `typing.Generic` as its base class and useand assign the declared TypeVar to the `_obj_cls` attribute asa type of the passed class.Make both `_obj_cls` and `_path` attributes an abstract propertiesso that type checkers can check that those attributes were properlydefined in subclasses. Mypy will only check then the class isinstantiated which makes non-final subclasses possible.Unfortunately pylint will check the declarations not instantiationsso add `# pylint: disable=abstract-method` comments to all non-finalsubclasses like ListMixin.Make `_path` attribute always be `str` instead of sometimes `None`.This eliminates unnecessary type checks.Change all mixins like ListMixin or GetMixin to a subclass. This makesthe attribute declarations much cleaner as for example `_list_filters`is now the only attribute defined by ListMixin.Change SidekiqManager to not inherit from RESTManager and onlycopy its `__init__` method. This is because SidekiqManager neverwas a real manager and does not define `_path` or `_obj_cls`.Delete `tests/unit/meta/test_ensure_type_hints.py` file as the `get`method is no required to be defined for every class.Signed-off-by: Igor Ponomarev <igor.ponomarev@collabora.com>
1 parent46dfc50 commit91c4f18

File tree

88 files changed

+748
-536
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

88 files changed

+748
-536
lines changed

‎gitlab/base.py

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,18 @@
44
importpprint
55
importtextwrap
66
fromtypesimportModuleType
7-
fromtypingimportAny,Dict,Iterable,Optional,Type,TYPE_CHECKING,Union
7+
fromtypingimport (
8+
Any,
9+
ClassVar,
10+
Dict,
11+
Generic,
12+
Iterable,
13+
Optional,
14+
Type,
15+
TYPE_CHECKING,
16+
TypeVar,
17+
Union,
18+
)
819

920
importgitlab
1021
fromgitlabimporttypesasg_types
@@ -48,11 +59,11 @@ class RESTObject:
4859
_repr_attr:Optional[str]=None
4960
_updated_attrs:Dict[str,Any]
5061
_lazy:bool
51-
manager:"RESTManager"
62+
manager:"RESTManager[Any]"
5263

5364
def__init__(
5465
self,
55-
manager:"RESTManager",
66+
manager:"RESTManager[Any]",
5667
attrs:Dict[str,Any],
5768
*,
5869
created_from_list:bool=False,
@@ -269,7 +280,7 @@ class RESTObjectList:
269280
"""
270281

271282
def__init__(
272-
self,manager:"RESTManager",obj_cls:Type[RESTObject],_list:GitlabList
283+
self,manager:"RESTManager[Any]",obj_cls:Type[RESTObject],_list:GitlabList
273284
)->None:
274285
"""Creates an objects list from a GitlabList.
275286
@@ -335,7 +346,10 @@ def total(self) -> Optional[int]:
335346
returnself._list.total
336347

337348

338-
classRESTManager:
349+
TObjCls=TypeVar("TObjCls",bound=RESTObject)
350+
351+
352+
classRESTManager(Generic[TObjCls]):
339353
"""Base class for CRUD operations on objects.
340354
341355
Derived class must define ``_path`` and ``_obj_cls``.
@@ -346,12 +360,12 @@ class RESTManager:
346360

347361
_create_attrs:g_types.RequiredOptional=g_types.RequiredOptional()
348362
_update_attrs:g_types.RequiredOptional=g_types.RequiredOptional()
349-
_path:Optional[str]=None
350-
_obj_cls:Optional[Type[RESTObject]]=None
363+
_path:ClassVar[str]
364+
_obj_cls:type[TObjCls]
351365
_from_parent_attrs:Dict[str,Any]= {}
352366
_types:Dict[str,Type[g_types.GitlabAttribute]]= {}
353367

354-
_computed_path:Optional[str]
368+
_computed_path:str
355369
_parent:Optional[RESTObject]
356370
_parent_attrs:Dict[str,Any]
357371
gitlab:Gitlab
@@ -371,12 +385,10 @@ def __init__(self, gl: Gitlab, parent: Optional[RESTObject] = None) -> None:
371385
defparent_attrs(self)->Optional[Dict[str,Any]]:
372386
returnself._parent_attrs
373387

374-
def_compute_path(self,path:Optional[str]=None)->Optional[str]:
388+
def_compute_path(self,path:Optional[str]=None)->str:
375389
self._parent_attrs= {}
376390
ifpathisNone:
377391
path=self._path
378-
ifpathisNone:
379-
returnNone
380392
ifself._parentisNoneornotself._from_parent_attrs:
381393
returnpath
382394

@@ -390,5 +402,5 @@ def _compute_path(self, path: Optional[str] = None) -> Optional[str]:
390402
returnpath.format(**data)
391403

392404
@property
393-
defpath(self)->Optional[str]:
405+
defpath(self)->str:
394406
returnself._computed_path

‎gitlab/client.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -397,11 +397,10 @@ def auth(self) -> None:
397397
The `user` attribute will hold a `gitlab.objects.CurrentUser` object on
398398
success.
399399
"""
400-
# pylint: disable=line-too-long
401-
self.user=self._objects.CurrentUserManager(self).get()# type: ignore[assignment]
400+
self.user=self._objects.CurrentUserManager(self).get()
402401

403402
ifhasattr(self.user,"web_url")andhasattr(self.user,"username"):
404-
self._check_url(self.user.web_url,path=self.user.username)# type: ignore[union-attr]
403+
self._check_url(self.user.web_url,path=self.user.username)
405404

406405
defversion(self)->Tuple[str,str]:
407406
"""Returns the version and revision of the gitlab server.

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp