pomcorn 0.7.5__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
|
|
|
@@ -177,21 +197,36 @@ class ListComponent(Generic[ListItemType, TPage], Component[TPage]):
|
|
|
177
197
|
* all
|
|
178
198
|
* get_item_by_text()
|
|
179
199
|
|
|
180
|
-
Waits for `base_item_locator` property to be implemented and value of
|
|
181
|
-
`item_class` to be set.
|
|
182
|
-
|
|
183
200
|
Waits for `base_item_locator` property to be overridden or one of the
|
|
184
201
|
attributes (`item_locator` or `relative_item_locator`) to be specified.
|
|
185
202
|
|
|
186
|
-
The `item_class` attribute is also required.
|
|
187
|
-
|
|
188
203
|
"""
|
|
189
204
|
|
|
190
|
-
|
|
205
|
+
_item_class: type[ListItemType] = EmptyValue
|
|
191
206
|
|
|
192
207
|
item_locator: locators.XPathLocator | None = None
|
|
193
208
|
relative_item_locator: locators.XPathLocator | None = None
|
|
194
209
|
|
|
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
|
|
229
|
+
|
|
195
230
|
@property
|
|
196
231
|
def base_item_locator(self) -> locators.XPathLocator:
|
|
197
232
|
"""Get the base locator of list item.
|
|
@@ -236,21 +271,49 @@ class ListComponent(Generic[ListItemType, TPage], Component[TPage]):
|
|
|
236
271
|
|
|
237
272
|
items: list[ListItemType] = []
|
|
238
273
|
for locator in self.iter_locators(self.base_item_locator):
|
|
239
|
-
items.append(
|
|
274
|
+
items.append(
|
|
275
|
+
self._item_class(page=self.page, base_locator=locator),
|
|
276
|
+
)
|
|
240
277
|
return items
|
|
241
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
|
+
|
|
242
305
|
def get_item_by_text(self, text: str) -> ListItemType:
|
|
243
306
|
"""Get list item by text."""
|
|
244
307
|
locator = self.base_item_locator.extend_query(
|
|
245
308
|
extra_query=f"[contains(.,'{text}')]",
|
|
246
309
|
)
|
|
247
|
-
return self.
|
|
310
|
+
return self._item_class(page=self.page, base_locator=locator)
|
|
248
311
|
|
|
249
312
|
def __repr__(self) -> str:
|
|
250
313
|
return (
|
|
251
314
|
"ListComponent("
|
|
252
315
|
f"component={self.__class__}, "
|
|
253
|
-
f"item_class={self.
|
|
316
|
+
f"item_class={self._item_class}, "
|
|
254
317
|
f"base_item_locator={self.base_item_locator}, "
|
|
255
318
|
f"count={self.count}, "
|
|
256
319
|
f"items={self.all}, "
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: pomcorn
|
|
3
|
-
Version: 0.
|
|
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.
|
|
15
|
-
pomcorn-0.
|
|
16
|
-
pomcorn-0.
|
|
17
|
-
pomcorn-0.
|
|
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
|