zeed-movs-viewer 0.0.0__tar.gz

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.
@@ -0,0 +1,15 @@
1
+ Metadata-Version: 2.1
2
+ Name: zeed-movs-viewer
3
+ Version: 0.0.0
4
+ Classifier: Programming Language :: Python :: 3 :: Only
5
+ Classifier: Programming Language :: Python :: 3.12
6
+ Project-URL: Homepage, https://github.com/ZeeD/movs-viewer
7
+ Project-URL: Repository, https://github.com/ZeeD/movs-viewer.git
8
+ Requires-Python: ==3.12.*
9
+ Requires-Dist: pyside6!=6.8,!=6.8.0.1,>=6.7
10
+ Requires-Dist: pythonqwt>=0.12.5
11
+ Requires-Dist: selenium>=4.22
12
+ Requires-Dist: zeed-guilib>=0.0.2
13
+ Requires-Dist: zeed-movs-merger>=0
14
+ Requires-Dist: zeed-movslib>=0.0.2
15
+
@@ -0,0 +1,139 @@
1
+ [build-system]
2
+ build-backend = "pdm.backend"
3
+ requires = [
4
+ "pdm-backend",
5
+ ]
6
+
7
+ [project]
8
+ name = "zeed-movs-viewer"
9
+ version = "0.0.0"
10
+ requires-python = "==3.12.*"
11
+ classifiers = [
12
+ "Programming Language :: Python :: 3 :: Only",
13
+ "Programming Language :: Python :: 3.12",
14
+ ]
15
+ dependencies = [
16
+ "pyside6!=6.8,!=6.8.0.1,>=6.7",
17
+ "pythonqwt>=0.12.5",
18
+ "selenium>=4.22",
19
+ "zeed-guilib>=0.0.2",
20
+ "zeed-movs-merger>=0",
21
+ "zeed-movslib>=0.0.2",
22
+ ]
23
+
24
+ [project.urls]
25
+ Homepage = "https://github.com/ZeeD/movs-viewer"
26
+ Repository = "https://github.com/ZeeD/movs-viewer.git"
27
+
28
+ [project.gui-scripts]
29
+ movs-viewer = "movsviewer.mainui:main"
30
+
31
+ [tool.pdm]
32
+ distribution = true
33
+ plugins = [
34
+ "pdm-version",
35
+ ]
36
+
37
+ [tool.pdm.dev-dependencies]
38
+ dev = [
39
+ "coverage>=7.6.1",
40
+ "mypy>=1.11.2",
41
+ "pyproject-fmt>=2.2.4",
42
+ "ruff>=0.6.9",
43
+ ]
44
+
45
+ [tool.pdm.scripts]
46
+ start = "movs-viewer"
47
+
48
+ [tool.pdm.scripts._.env]
49
+ PYTHONPATH = "src:tests"
50
+
51
+ [tool.pdm.scripts.lint]
52
+ composite = [
53
+ "pyproject-fmt pyproject.toml",
54
+ "ruff format .",
55
+ "ruff check --exit-zero .",
56
+ "dmypy run .",
57
+ ]
58
+
59
+ [tool.pdm.scripts.tests]
60
+ composite = [
61
+ "coverage run -m unittest discover --verbose --locals --failfast --catch --start-directory tests",
62
+ "coverage report",
63
+ "coverage erase",
64
+ ]
65
+
66
+ [tool.ruff]
67
+ line-length = 80
68
+ src = [
69
+ "demo",
70
+ "src",
71
+ "stubs",
72
+ "tests",
73
+ ]
74
+ fix = true
75
+
76
+ [tool.ruff.format]
77
+ quote-style = "single"
78
+ skip-magic-trailing-comma = true
79
+ docstring-code-format = true
80
+
81
+ [tool.ruff.lint]
82
+ select = [
83
+ "ALL",
84
+ ]
85
+ ignore = [
86
+ "ANN1",
87
+ "COM812",
88
+ "D1",
89
+ "D203",
90
+ "D213",
91
+ "ISC001",
92
+ "PT009",
93
+ "PT027",
94
+ "Q001",
95
+ "Q002",
96
+ ]
97
+
98
+ [tool.ruff.lint.flake8-annotations]
99
+ allow-star-arg-any = true
100
+
101
+ [tool.ruff.lint.flake8-quotes]
102
+ docstring-quotes = "single"
103
+ inline-quotes = "single"
104
+ multiline-quotes = "single"
105
+
106
+ [tool.ruff.lint.flake8-type-checking]
107
+ quote-annotations = true
108
+
109
+ [tool.ruff.lint.isort]
110
+ force-single-line = true
111
+
112
+ [tool.pyproject-fmt]
113
+ column_width = 80
114
+ indent = 4
115
+
116
+ [tool.coverage.run]
117
+ branch = true
118
+ source = [
119
+ "src",
120
+ "tests",
121
+ ]
122
+
123
+ [tool.coverage.report]
124
+ show_missing = true
125
+ sort = "Cover"
126
+ skip_empty = true
127
+
128
+ [tool.mypy]
129
+ mypy_path = [
130
+ "src",
131
+ "tests",
132
+ "demo",
133
+ "stubs",
134
+ ]
135
+ strict = true
136
+ warn_unused_configs = true
137
+ overrides = [
138
+ { module = "movsviewer.automation", disable_error_code = "no-untyped-call" },
139
+ ]
File without changes
@@ -0,0 +1,131 @@
1
+ from contextlib import contextmanager
2
+ from logging import info
3
+ from os import listdir
4
+ from pathlib import Path
5
+ from tempfile import TemporaryDirectory
6
+ from typing import TYPE_CHECKING
7
+
8
+ from selenium.webdriver import Firefox
9
+ from selenium.webdriver.common.by import By
10
+ from selenium.webdriver.common.keys import Keys
11
+ from selenium.webdriver.firefox.firefox_profile import FirefoxProfile
12
+ from selenium.webdriver.firefox.options import Options
13
+ from selenium.webdriver.firefox.service import Service
14
+ from selenium.webdriver.remote.webelement import WebElement
15
+ from selenium.webdriver.support.expected_conditions import all_of
16
+ from selenium.webdriver.support.expected_conditions import (
17
+ element_to_be_clickable,
18
+ )
19
+ from selenium.webdriver.support.expected_conditions import (
20
+ invisibility_of_element,
21
+ )
22
+ from selenium.webdriver.support.expected_conditions import (
23
+ presence_of_element_located,
24
+ )
25
+ from selenium.webdriver.support.expected_conditions import url_contains
26
+ from selenium.webdriver.support.select import Select
27
+ from selenium.webdriver.support.wait import WebDriverWait
28
+
29
+ from movsviewer.constants import GECKODRIVER_PATH
30
+
31
+ if TYPE_CHECKING:
32
+ from collections.abc import Callable
33
+ from collections.abc import Iterator
34
+
35
+ from selenium.webdriver.remote.webdriver import WebDriver
36
+
37
+
38
+ def get_options(dtemp: str) -> Options:
39
+ options = Options()
40
+
41
+ options.profile = FirefoxProfile()
42
+ # set download folder
43
+ options.profile.set_preference('browser.download.folderList', 2)
44
+ options.profile.set_preference('browser.download.dir', dtemp)
45
+
46
+ return options
47
+
48
+
49
+ def _w(
50
+ wait: 'WebDriverWait[WebDriver]',
51
+ condition: """Callable[[tuple[str, str]],
52
+ Callable[[WebDriver], bool | WebElement]]""",
53
+ css_selector: str,
54
+ ) -> WebElement:
55
+ ret = wait.until(condition((By.CSS_SELECTOR, css_selector)))
56
+ if not isinstance(ret, WebElement):
57
+ raise TypeError
58
+ return ret
59
+
60
+
61
+ def _c(wait: 'WebDriverWait[WebDriver]', css_selector: str) -> WebElement:
62
+ return _w(wait, element_to_be_clickable, css_selector)
63
+
64
+
65
+ def _p(wait: 'WebDriverWait[WebDriver]', css_selector: str) -> WebElement:
66
+ return _w(wait, presence_of_element_located, css_selector)
67
+
68
+
69
+ def _i(wait: 'WebDriverWait[WebDriver]', css_selector: str) -> WebElement:
70
+ return _w(wait, invisibility_of_element, css_selector)
71
+
72
+
73
+ def pl(wait: 'WebDriverWait[WebDriver]', wd: 'WebDriver') -> None:
74
+ _p(wait, '.pageLoader')
75
+ founds = wd.find_elements(By.CSS_SELECTOR, '.pageLoader')
76
+ wait.until(all_of(*(invisibility_of_element(found) for found in founds)))
77
+
78
+
79
+ HP = 'https://bancoposta.poste.it/bpol/public/BPOL_ListaMovimentiAPP/index.html'
80
+
81
+
82
+ @contextmanager
83
+ def get_movimenti(
84
+ username: str, password: str, num_conto: str, get_otp: 'Callable[[], str]'
85
+ ) -> 'Iterator[Path]':
86
+ with (
87
+ TemporaryDirectory() as dtemp,
88
+ Firefox(
89
+ service=Service(executable_path=str(GECKODRIVER_PATH)),
90
+ options=get_options(dtemp),
91
+ ) as wd
92
+ ): # fmt: skip
93
+ wait = WebDriverWait(wd, 1000)
94
+ # login
95
+ wd.get(HP)
96
+ pl(wait, wd)
97
+ wd.find_element(By.CSS_SELECTOR, '#username').send_keys(username)
98
+ wd.find_element(By.CSS_SELECTOR, '#password').send_keys(
99
+ password + Keys.RETURN
100
+ )
101
+ wait.until(
102
+ url_contains(
103
+ 'https://idp-poste.poste.it/jod-idp-retail/cas/app.html'
104
+ )
105
+ )
106
+ pl(wait, wd)
107
+ _c(wait, '#_prosegui').click()
108
+ otp = get_otp()
109
+ wd.find_element(By.CSS_SELECTOR, '#otp').send_keys(otp + Keys.RETURN)
110
+
111
+ # choose conto and download text
112
+ _p(wait, f'select.numconto>option[value="string:{num_conto}"]')
113
+ pl(wait, wd)
114
+ Select(_p(wait, 'select.numconto')).select_by_value(
115
+ f'string:{num_conto}'
116
+ )
117
+
118
+ # hide cookie banner
119
+ wd.execute_script(
120
+ 'document.querySelector("#content-alert-cookie")'
121
+ '.style.display="none"'
122
+ )
123
+ _c(wait, '#select>option[value=TESTO]')
124
+ Select(_p(wait, '#select')).select_by_value('TESTO')
125
+
126
+ info('prima: %s', listdir(dtemp))
127
+ _c(wait, '#downloadApi').click()
128
+ _i(wait, '.waiting')
129
+ info('dopo: %s', listdir(dtemp))
130
+
131
+ yield Path(dtemp) / 'ListaMovimenti.txt'