pomcorn 0.8.0__py3-none-any.whl → 0.8.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.
Potentially problematic release.
This version of pomcorn might be problematic. Click here for more details.
pomcorn/component.py
CHANGED
|
@@ -1,4 +1,13 @@
|
|
|
1
|
-
from
|
|
1
|
+
from inspect import isclass
|
|
2
|
+
from typing import (
|
|
3
|
+
Any,
|
|
4
|
+
Generic,
|
|
5
|
+
Literal,
|
|
6
|
+
TypeVar,
|
|
7
|
+
get_args,
|
|
8
|
+
get_origin,
|
|
9
|
+
overload,
|
|
10
|
+
)
|
|
2
11
|
|
|
3
12
|
from . import locators
|
|
4
13
|
from .element import XPathElement
|
|
@@ -8,6 +17,17 @@ from .web_view import WebView
|
|
|
8
17
|
TPage = TypeVar("TPage", bound=Page)
|
|
9
18
|
|
|
10
19
|
|
|
20
|
+
class _EmptyValue:
|
|
21
|
+
"""Singleton to use as default value for empty class attribute."""
|
|
22
|
+
|
|
23
|
+
def __bool__(self) -> Literal[False]:
|
|
24
|
+
"""Allow `EmptyValue` to be used in bool expressions."""
|
|
25
|
+
return False
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
EmptyValue: Any = _EmptyValue()
|
|
29
|
+
|
|
30
|
+
|
|
11
31
|
class Component(Generic[TPage], WebView):
|
|
12
32
|
"""The class to represent a page component that depends on base locator.
|
|
13
33
|
|
|
@@ -182,31 +202,30 @@ class ListComponent(Generic[ListItemType, TPage], Component[TPage]):
|
|
|
182
202
|
|
|
183
203
|
"""
|
|
184
204
|
|
|
205
|
+
_item_class: type[ListItemType] = EmptyValue
|
|
206
|
+
|
|
185
207
|
item_locator: locators.XPathLocator | None = None
|
|
186
208
|
relative_item_locator: locators.XPathLocator | None = None
|
|
187
209
|
|
|
188
|
-
def
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
self._item_class = item_class
|
|
208
|
-
else:
|
|
209
|
-
self._item_class = self._get_list_item_class()
|
|
210
|
+
def __init_subclass__(cls) -> None:
|
|
211
|
+
"""Run logic for getting/overriding item_class attr for subclasses."""
|
|
212
|
+
super().__init_subclass__()
|
|
213
|
+
|
|
214
|
+
# If class has valid `_item_class` attribute from a parent class
|
|
215
|
+
if cls.is_valid_item_class(cls._item_class):
|
|
216
|
+
# We leave using of parent `item_class`
|
|
217
|
+
return
|
|
218
|
+
|
|
219
|
+
# Try to get `item_class` from first generic variable
|
|
220
|
+
list_item_class = cls.get_list_item_class()
|
|
221
|
+
|
|
222
|
+
if not list_item_class:
|
|
223
|
+
# If `item_class` is not specified in generic we leave it empty
|
|
224
|
+
# because it maybe not specified in base class but will be
|
|
225
|
+
# specified in child
|
|
226
|
+
return
|
|
227
|
+
|
|
228
|
+
cls._item_class = list_item_class
|
|
210
229
|
|
|
211
230
|
@property
|
|
212
231
|
def base_item_locator(self) -> locators.XPathLocator:
|
|
@@ -257,6 +276,32 @@ class ListComponent(Generic[ListItemType, TPage], Component[TPage]):
|
|
|
257
276
|
)
|
|
258
277
|
return items
|
|
259
278
|
|
|
279
|
+
@classmethod
|
|
280
|
+
def get_list_item_class(cls) -> type[ListItemType] | None:
|
|
281
|
+
"""Return class passed in `Generic[ListItemType]`."""
|
|
282
|
+
base_class = next(
|
|
283
|
+
_class
|
|
284
|
+
for _class in cls.__orig_bases__ # type: ignore
|
|
285
|
+
if isclass(get_origin(_class))
|
|
286
|
+
and issubclass(get_origin(_class), ListComponent)
|
|
287
|
+
)
|
|
288
|
+
|
|
289
|
+
# Get first generic variable and return it if it is valid item class
|
|
290
|
+
item_class = get_args(base_class)[0]
|
|
291
|
+
if cls.is_valid_item_class(item_class):
|
|
292
|
+
return item_class
|
|
293
|
+
|
|
294
|
+
return None
|
|
295
|
+
|
|
296
|
+
@classmethod
|
|
297
|
+
def is_valid_item_class(cls, item_class: Any) -> bool:
|
|
298
|
+
"""Check that specified ``item_class`` is valid.
|
|
299
|
+
|
|
300
|
+
Valid `item_class` should be a class and subclass of ``Component``.
|
|
301
|
+
|
|
302
|
+
"""
|
|
303
|
+
return isclass(item_class) and issubclass(item_class, Component)
|
|
304
|
+
|
|
260
305
|
def get_item_by_text(self, text: str) -> ListItemType:
|
|
261
306
|
"""Get list item by text."""
|
|
262
307
|
locator = self.base_item_locator.extend_query(
|
|
@@ -264,10 +309,6 @@ class ListComponent(Generic[ListItemType, TPage], Component[TPage]):
|
|
|
264
309
|
)
|
|
265
310
|
return self._item_class(page=self.page, base_locator=locator)
|
|
266
311
|
|
|
267
|
-
def _get_list_item_class(self) -> type[ListItemType]:
|
|
268
|
-
"""Return class passed in `Generic[ListItemType]`."""
|
|
269
|
-
return get_args(self.__orig_bases__[0])[0] # type: ignore
|
|
270
|
-
|
|
271
312
|
def __repr__(self) -> str:
|
|
272
313
|
return (
|
|
273
314
|
"ListComponent("
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: pomcorn
|
|
3
|
-
Version: 0.8.
|
|
3
|
+
Version: 0.8.1
|
|
4
4
|
Summary: Base implementation of Page Object Model
|
|
5
5
|
Home-page: https://pypi.org/project/pomcorn/
|
|
6
6
|
License: MIT
|
|
@@ -119,7 +119,6 @@ Below is the code that opens ``PyPI.org``, searches for packages by name and pri
|
|
|
119
119
|
|
|
120
120
|
class PackageList(ListComponent[Package, PyPIPage]):
|
|
121
121
|
|
|
122
|
-
item_class = Package
|
|
123
122
|
relative_item_locator = locators.ClassLocator("snippet__name")
|
|
124
123
|
|
|
125
124
|
@property
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
pomcorn/__init__.py,sha256=V8v_V3wgKbao1KAQkcVTMnpGwyslw0nHfuTp-DwWTXg,318
|
|
2
|
-
pomcorn/component.py,sha256
|
|
2
|
+
pomcorn/component.py,sha256=iZrTw8F_DiLvJe9voe3FlhKt2B3Ncy_g8hxP3hq2LzU,10260
|
|
3
3
|
pomcorn/descriptors/__init__.py,sha256=5q_d5GtcaFlIIyHdsUnE9UNbz3g40qJCHKNaWGvcC6s,72
|
|
4
4
|
pomcorn/descriptors/element.py,sha256=4g_4ay5f00AXzCT4xHN1i7mTrlsECoUHh1Ph_TFPBDs,4502
|
|
5
5
|
pomcorn/element.py,sha256=6VLLSPlc7961qa4rRXdno7cEAAeY8GEP2d4wtM5R9a0,12216
|
|
@@ -11,7 +11,7 @@ pomcorn/page.py,sha256=wuLoGUn1n0e7wSXLGYyUVnoPlz_gMfT8Jtg6yA09IeY,5755
|
|
|
11
11
|
pomcorn/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
12
12
|
pomcorn/waits_conditions.py,sha256=E8sLfBvIV2EO91Mm5KyKXB5IGEB9gUWza3XPE4_aCQE,3528
|
|
13
13
|
pomcorn/web_view.py,sha256=PlwEVgdOwFZXJY2WuUT2C2wyK1xOBJne5-A_FOuwsQI,14209
|
|
14
|
-
pomcorn-0.8.
|
|
15
|
-
pomcorn-0.8.
|
|
16
|
-
pomcorn-0.8.
|
|
17
|
-
pomcorn-0.8.
|
|
14
|
+
pomcorn-0.8.1.dist-info/LICENSE,sha256=1vmhQNp1dDH8ksJ199LuG4oKz5D4ZvNccPcFckiG2S4,1091
|
|
15
|
+
pomcorn-0.8.1.dist-info/METADATA,sha256=l9lbcd093ClWUJeEtyLXcUGFFG3S8mteJ_PTMBbYTo8,5922
|
|
16
|
+
pomcorn-0.8.1.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
|
|
17
|
+
pomcorn-0.8.1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|