Skip to content

Commit 9d629bb

Browse files
chore: move utils._validate_attrs inside types.RequiredOptional
Move the `validate_attrs` function to be inside the `RequiredOptional` class. It makes sense for it to be part of the class as it is working on data related to the class.
1 parent 0c5a121 commit 9d629bb

File tree

7 files changed

+41
-44
lines changed

7 files changed

+41
-44
lines changed

gitlab/mixins.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -278,7 +278,7 @@ def create(
278278
if data is None:
279279
data = {}
280280

281-
utils._validate_attrs(data=data, attributes=self._create_attrs)
281+
self._create_attrs.validate_attrs(data=data)
282282
data, files = utils._transform_types(data, self._types)
283283

284284
# Handle specific URL for creation
@@ -345,9 +345,7 @@ def update(
345345
excludes = []
346346
if self._obj_cls is not None and self._obj_cls._id_attr is not None:
347347
excludes = [self._obj_cls._id_attr]
348-
utils._validate_attrs(
349-
data=new_data, attributes=self._update_attrs, excludes=excludes
350-
)
348+
self._update_attrs.validate_attrs(data=new_data, excludes=excludes)
351349
new_data, files = utils._transform_types(new_data, self._types)
352350

353351
http_method = self._get_update_method()

gitlab/types.py

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
# along with this program. If not, see <http://www.gnu.org/licenses/>.
1717

1818
import dataclasses
19-
from typing import Any, Optional, Tuple, TYPE_CHECKING
19+
from typing import Any, Dict, List, Optional, Tuple, TYPE_CHECKING
2020

2121

2222
@dataclasses.dataclass(frozen=True)
@@ -25,6 +25,33 @@ class RequiredOptional:
2525
optional: Tuple[str, ...] = ()
2626
exclusive: Tuple[str, ...] = ()
2727

28+
def validate_attrs(
29+
self,
30+
*,
31+
data: Dict[str, Any],
32+
excludes: Optional[List[str]] = None,
33+
) -> None:
34+
if excludes is None:
35+
excludes = []
36+
37+
if self.required:
38+
required = [k for k in self.required if k not in excludes]
39+
missing = [attr for attr in required if attr not in data]
40+
if missing:
41+
raise AttributeError(f"Missing attributes: {', '.join(missing)}")
42+
43+
if self.exclusive:
44+
exclusives = [attr for attr in data if attr in self.exclusive]
45+
if len(exclusives) > 1:
46+
raise AttributeError(
47+
f"Provide only one of these attributes: {', '.join(exclusives)}"
48+
)
49+
if not exclusives:
50+
raise AttributeError(
51+
f"Must provide one of these attributes: "
52+
f"{', '.join(self.exclusive)}"
53+
)
54+
2855

2956
class GitlabAttribute:
3057
def __init__(self, value: Any = None) -> None:

gitlab/utils.py

Lines changed: 1 addition & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
import traceback
2020
import urllib.parse
2121
import warnings
22-
from typing import Any, Callable, Dict, List, Optional, Tuple, Type, Union
22+
from typing import Any, Callable, Dict, Optional, Tuple, Type, Union
2323

2424
import requests
2525

@@ -159,30 +159,3 @@ def warn(
159159
stacklevel=stacklevel,
160160
source=source,
161161
)
162-
163-
164-
def _validate_attrs(
165-
data: Dict[str, Any],
166-
attributes: types.RequiredOptional,
167-
excludes: Optional[List[str]] = None,
168-
) -> None:
169-
if excludes is None:
170-
excludes = []
171-
172-
if attributes.required:
173-
required = [k for k in attributes.required if k not in excludes]
174-
missing = [attr for attr in required if attr not in data]
175-
if missing:
176-
raise AttributeError(f"Missing attributes: {', '.join(missing)}")
177-
178-
if attributes.exclusive:
179-
exclusives = [attr for attr in data if attr in attributes.exclusive]
180-
if len(exclusives) > 1:
181-
raise AttributeError(
182-
f"Provide only one of these attributes: {', '.join(exclusives)}"
183-
)
184-
if not exclusives:
185-
raise AttributeError(
186-
f"Must provide one of these attributes: "
187-
f"{', '.join(attributes.exclusive)}"
188-
)

gitlab/v4/objects/epics.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from typing import Any, cast, Dict, Optional, TYPE_CHECKING, Union
22

33
from gitlab import exceptions as exc
4-
from gitlab import types, utils
4+
from gitlab import types
55
from gitlab.base import RESTManager, RESTObject
66
from gitlab.mixins import (
77
CreateMixin,
@@ -107,7 +107,7 @@ def create(
107107
"""
108108
if TYPE_CHECKING:
109109
assert data is not None
110-
utils._validate_attrs(data=data, attributes=self._create_attrs)
110+
self._create_attrs.validate_attrs(data=data)
111111
path = f"{self.path}/{data.pop('issue_id')}"
112112
server_data = self.gitlab.http_post(path, **kwargs)
113113
if TYPE_CHECKING:

gitlab/v4/objects/files.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ def create(
145145

146146
if TYPE_CHECKING:
147147
assert data is not None
148-
utils._validate_attrs(data=data, attributes=self._create_attrs)
148+
self._create_attrs.validate_attrs(data=data)
149149
new_data = data.copy()
150150
file_path = utils.EncodedId(new_data.pop("file_path"))
151151
path = f"{self.path}/{file_path}"
@@ -179,7 +179,7 @@ def update( # type: ignore
179179
file_path = utils.EncodedId(file_path)
180180
data["file_path"] = file_path
181181
path = f"{self.path}/{file_path}"
182-
utils._validate_attrs(data=data, attributes=self._update_attrs)
182+
self._update_attrs.validate_attrs(data=data)
183183
result = self.gitlab.http_put(path, post_data=data, **kwargs)
184184
if TYPE_CHECKING:
185185
assert isinstance(result, dict)

gitlab/v4/objects/issues.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
from gitlab import cli
44
from gitlab import exceptions as exc
5-
from gitlab import types, utils
5+
from gitlab import types
66
from gitlab.base import RESTManager, RESTObject
77
from gitlab.mixins import (
88
CreateMixin,
@@ -272,7 +272,7 @@ def create( # type: ignore
272272
GitlabAuthenticationError: If authentication is not correct
273273
GitlabCreateError: If the server cannot perform the request
274274
"""
275-
utils._validate_attrs(data=data, attributes=self._create_attrs)
275+
self._create_attrs.validate_attrs(data=data)
276276
if TYPE_CHECKING:
277277
assert self.path is not None
278278
server_data = self.gitlab.http_post(self.path, post_data=data, **kwargs)

tests/unit/mixins/test_mixin_methods.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33

44
from gitlab import base
55
from gitlab import types as gl_types
6-
from gitlab import utils
76
from gitlab.mixins import (
87
CreateMixin,
98
DeleteMixin,
@@ -174,11 +173,11 @@ class M(CreateMixin, FakeManager):
174173

175174
mgr = M(gl)
176175
data = {"foo": "bar", "baz": "blah"}
177-
utils._validate_attrs(data=data, attributes=mgr._create_attrs)
176+
mgr._create_attrs.validate_attrs(data=data)
178177

179178
data = {"baz": "blah"}
180179
with pytest.raises(AttributeError) as error:
181-
utils._validate_attrs(data=data, attributes=mgr._create_attrs)
180+
mgr._create_attrs.validate_attrs(data=data)
182181
assert "foo" in str(error.value)
183182

184183

@@ -240,11 +239,11 @@ class M(UpdateMixin, FakeManager):
240239

241240
mgr = M(gl)
242241
data = {"foo": "bar", "baz": "blah"}
243-
utils._validate_attrs(data=data, attributes=mgr._update_attrs)
242+
mgr._update_attrs.validate_attrs(data=data)
244243

245244
data = {"baz": "blah"}
246245
with pytest.raises(AttributeError) as error:
247-
utils._validate_attrs(data=data, attributes=mgr._update_attrs)
246+
mgr._update_attrs.validate_attrs(data=data)
248247
assert "foo" in str(error.value)
249248

250249

0 commit comments

Comments
 (0)