mbu-dev-shared-components 4.1.0__tar.gz → 4.2.1__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.
- {mbu_dev_shared_components-4.1.0 → mbu_dev_shared_components-4.2.1}/PKG-INFO +2 -1
- {mbu_dev_shared_components-4.1.0 → mbu_dev_shared_components-4.2.1}/mbu_dev_shared_components/database/utility.py +30 -15
- {mbu_dev_shared_components-4.1.0 → mbu_dev_shared_components-4.2.1}/mbu_dev_shared_components/solteqtand/application/app_handler.py +10 -1
- {mbu_dev_shared_components-4.1.0 → mbu_dev_shared_components-4.2.1}/mbu_dev_shared_components/solteqtand/application/base_ui.py +33 -12
- {mbu_dev_shared_components-4.1.0 → mbu_dev_shared_components-4.2.1}/mbu_dev_shared_components.egg-info/PKG-INFO +2 -1
- {mbu_dev_shared_components-4.1.0 → mbu_dev_shared_components-4.2.1}/mbu_dev_shared_components.egg-info/requires.txt +1 -0
- {mbu_dev_shared_components-4.1.0 → mbu_dev_shared_components-4.2.1}/pyproject.toml +2 -1
- {mbu_dev_shared_components-4.1.0 → mbu_dev_shared_components-4.2.1}/LICENSE +0 -0
- {mbu_dev_shared_components-4.1.0 → mbu_dev_shared_components-4.2.1}/README.md +0 -0
- {mbu_dev_shared_components-4.1.0 → mbu_dev_shared_components-4.2.1}/mbu_dev_shared_components/database/__init__.py +0 -0
- {mbu_dev_shared_components-4.1.0 → mbu_dev_shared_components-4.2.1}/mbu_dev_shared_components/database/connection.py +0 -0
- {mbu_dev_shared_components-4.1.0 → mbu_dev_shared_components-4.2.1}/mbu_dev_shared_components/database/constants.py +0 -0
- {mbu_dev_shared_components-4.1.0 → mbu_dev_shared_components-4.2.1}/mbu_dev_shared_components/database/logging.py +0 -0
- {mbu_dev_shared_components-4.1.0 → mbu_dev_shared_components-4.2.1}/mbu_dev_shared_components/getorganized/__init__.py +0 -0
- {mbu_dev_shared_components-4.1.0 → mbu_dev_shared_components-4.2.1}/mbu_dev_shared_components/getorganized/auth.py +0 -0
- {mbu_dev_shared_components-4.1.0 → mbu_dev_shared_components-4.2.1}/mbu_dev_shared_components/getorganized/cases.py +0 -0
- {mbu_dev_shared_components-4.1.0 → mbu_dev_shared_components-4.2.1}/mbu_dev_shared_components/getorganized/contacts.py +0 -0
- {mbu_dev_shared_components-4.1.0 → mbu_dev_shared_components-4.2.1}/mbu_dev_shared_components/getorganized/documents.py +0 -0
- {mbu_dev_shared_components-4.1.0 → mbu_dev_shared_components-4.2.1}/mbu_dev_shared_components/getorganized/objects.py +0 -0
- {mbu_dev_shared_components-4.1.0 → mbu_dev_shared_components-4.2.1}/mbu_dev_shared_components/google/__init__.py +0 -0
- {mbu_dev_shared_components-4.1.0 → mbu_dev_shared_components-4.2.1}/mbu_dev_shared_components/google/api/__init__.py +0 -0
- {mbu_dev_shared_components-4.1.0 → mbu_dev_shared_components-4.2.1}/mbu_dev_shared_components/google/api/auth.py +0 -0
- {mbu_dev_shared_components-4.1.0 → mbu_dev_shared_components-4.2.1}/mbu_dev_shared_components/google/workspace/__init__.py +0 -0
- {mbu_dev_shared_components-4.1.0 → mbu_dev_shared_components-4.2.1}/mbu_dev_shared_components/google/workspace/alerts.py +0 -0
- {mbu_dev_shared_components-4.1.0 → mbu_dev_shared_components-4.2.1}/mbu_dev_shared_components/msoffice365/__init__.py +0 -0
- {mbu_dev_shared_components-4.1.0 → mbu_dev_shared_components-4.2.1}/mbu_dev_shared_components/msoffice365/excel/__init__.py +0 -0
- {mbu_dev_shared_components-4.1.0 → mbu_dev_shared_components-4.2.1}/mbu_dev_shared_components/msoffice365/excel/excel_reader.py +0 -0
- {mbu_dev_shared_components-4.1.0 → mbu_dev_shared_components-4.2.1}/mbu_dev_shared_components/msoffice365/sharepoint_api/__init__.py +0 -0
- {mbu_dev_shared_components-4.1.0 → mbu_dev_shared_components-4.2.1}/mbu_dev_shared_components/msoffice365/sharepoint_api/files.py +0 -0
- {mbu_dev_shared_components-4.1.0 → mbu_dev_shared_components-4.2.1}/mbu_dev_shared_components/os2forms/__init__.py +0 -0
- {mbu_dev_shared_components-4.1.0 → mbu_dev_shared_components-4.2.1}/mbu_dev_shared_components/os2forms/documents.py +0 -0
- {mbu_dev_shared_components-4.1.0 → mbu_dev_shared_components-4.2.1}/mbu_dev_shared_components/os2forms/forms.py +0 -0
- {mbu_dev_shared_components-4.1.0 → mbu_dev_shared_components-4.2.1}/mbu_dev_shared_components/romexis/__init__.py +0 -0
- {mbu_dev_shared_components-4.1.0 → mbu_dev_shared_components-4.2.1}/mbu_dev_shared_components/romexis/db_handler.py +0 -0
- {mbu_dev_shared_components-4.1.0 → mbu_dev_shared_components-4.2.1}/mbu_dev_shared_components/romexis/helper_functions.py +0 -0
- {mbu_dev_shared_components-4.1.0 → mbu_dev_shared_components-4.2.1}/mbu_dev_shared_components/sap/__init__.py +0 -0
- {mbu_dev_shared_components-4.1.0 → mbu_dev_shared_components-4.2.1}/mbu_dev_shared_components/sap/create_invoice.py +0 -0
- {mbu_dev_shared_components-4.1.0 → mbu_dev_shared_components-4.2.1}/mbu_dev_shared_components/solteqtand/__init__.py +0 -0
- {mbu_dev_shared_components-4.1.0 → mbu_dev_shared_components-4.2.1}/mbu_dev_shared_components/solteqtand/application/__init__.py +0 -0
- {mbu_dev_shared_components-4.1.0 → mbu_dev_shared_components-4.2.1}/mbu_dev_shared_components/solteqtand/application/aftalebog.py +0 -0
- {mbu_dev_shared_components-4.1.0 → mbu_dev_shared_components-4.2.1}/mbu_dev_shared_components/solteqtand/application/appointment.py +0 -0
- {mbu_dev_shared_components-4.1.0 → mbu_dev_shared_components-4.2.1}/mbu_dev_shared_components/solteqtand/application/clinic.py +0 -0
- {mbu_dev_shared_components-4.1.0 → mbu_dev_shared_components-4.2.1}/mbu_dev_shared_components/solteqtand/application/document.py +0 -0
- {mbu_dev_shared_components-4.1.0 → mbu_dev_shared_components-4.2.1}/mbu_dev_shared_components/solteqtand/application/edi_portal.py +0 -0
- {mbu_dev_shared_components-4.1.0 → mbu_dev_shared_components-4.2.1}/mbu_dev_shared_components/solteqtand/application/event.py +0 -0
- {mbu_dev_shared_components-4.1.0 → mbu_dev_shared_components-4.2.1}/mbu_dev_shared_components/solteqtand/application/exceptions.py +0 -0
- {mbu_dev_shared_components-4.1.0 → mbu_dev_shared_components-4.2.1}/mbu_dev_shared_components/solteqtand/application/handler_base.py +0 -0
- {mbu_dev_shared_components-4.1.0 → mbu_dev_shared_components-4.2.1}/mbu_dev_shared_components/solteqtand/application/journal_note.py +0 -0
- {mbu_dev_shared_components-4.1.0 → mbu_dev_shared_components-4.2.1}/mbu_dev_shared_components/solteqtand/application/patient.py +0 -0
- {mbu_dev_shared_components-4.1.0 → mbu_dev_shared_components-4.2.1}/mbu_dev_shared_components/solteqtand/database/__init__.py +0 -0
- {mbu_dev_shared_components-4.1.0 → mbu_dev_shared_components-4.2.1}/mbu_dev_shared_components/solteqtand/database/db_handler.py +0 -0
- {mbu_dev_shared_components-4.1.0 → mbu_dev_shared_components-4.2.1}/mbu_dev_shared_components/utils/__init__.py +0 -0
- {mbu_dev_shared_components-4.1.0 → mbu_dev_shared_components-4.2.1}/mbu_dev_shared_components/utils/db_stored_procedure_executor.py +0 -0
- {mbu_dev_shared_components-4.1.0 → mbu_dev_shared_components-4.2.1}/mbu_dev_shared_components/utils/fernet_encryptor.py +0 -0
- {mbu_dev_shared_components-4.1.0 → mbu_dev_shared_components-4.2.1}/mbu_dev_shared_components/utils/file_handler.py +0 -0
- {mbu_dev_shared_components-4.1.0 → mbu_dev_shared_components-4.2.1}/mbu_dev_shared_components/utils/json_handler.py +0 -0
- {mbu_dev_shared_components-4.1.0 → mbu_dev_shared_components-4.2.1}/mbu_dev_shared_components.egg-info/SOURCES.txt +0 -0
- {mbu_dev_shared_components-4.1.0 → mbu_dev_shared_components-4.2.1}/mbu_dev_shared_components.egg-info/dependency_links.txt +0 -0
- {mbu_dev_shared_components-4.1.0 → mbu_dev_shared_components-4.2.1}/mbu_dev_shared_components.egg-info/top_level.txt +0 -0
- {mbu_dev_shared_components-4.1.0 → mbu_dev_shared_components-4.2.1}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mbu_dev_shared_components
|
|
3
|
-
Version: 4.1
|
|
3
|
+
Version: 4.2.1
|
|
4
4
|
Summary: Shared components to use in RPA projects
|
|
5
5
|
Author-email: MBU <rpa@mbu.aarhus.dk>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -12,6 +12,7 @@ License-File: LICENSE
|
|
|
12
12
|
Requires-Dist: cryptography>=43.0.0
|
|
13
13
|
Requires-Dist: pyodbc>=5.1.0
|
|
14
14
|
Requires-Dist: python-dateutil==2.9.*
|
|
15
|
+
Requires-Dist: dotenv
|
|
15
16
|
Provides-Extra: getorganized
|
|
16
17
|
Requires-Dist: requests_ntlm>=1.2.0; extra == "getorganized"
|
|
17
18
|
Provides-Extra: google
|
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
"""This module handles general database connection and calls"""
|
|
2
2
|
|
|
3
|
-
import os
|
|
4
3
|
import json
|
|
5
|
-
|
|
6
|
-
from
|
|
4
|
+
import os
|
|
5
|
+
from typing import Any, Dict, Tuple, Union
|
|
6
|
+
|
|
7
7
|
import pyodbc
|
|
8
|
-
from
|
|
8
|
+
from dateutil import parser
|
|
9
|
+
from dotenv import load_dotenv
|
|
9
10
|
|
|
10
11
|
|
|
11
12
|
class Utility:
|
|
12
13
|
"""Base class handling general utilities"""
|
|
14
|
+
|
|
13
15
|
def connect_to_db(self, autocommit=True, db_env="PROD") -> pyodbc.Connection:
|
|
14
16
|
"""Establish connection to sql database
|
|
15
17
|
|
|
@@ -22,17 +24,24 @@ class Utility:
|
|
|
22
24
|
rpa_conn = pyodbc.connect(rpa_conn_string, autocommit=autocommit)
|
|
23
25
|
return rpa_conn
|
|
24
26
|
|
|
25
|
-
def execute_query(
|
|
27
|
+
def execute_query(
|
|
28
|
+
self, query: str, params: list = None, return_dict: bool = False
|
|
29
|
+
) -> list | None:
|
|
26
30
|
"""Execute SQL query with pyodbc"""
|
|
27
31
|
params = [] if not params else params
|
|
28
|
-
is_select = query.strip().upper().startswith(
|
|
32
|
+
is_select = query.strip().upper().startswith("SELECT")
|
|
29
33
|
try:
|
|
30
34
|
res = self.cursor.execute(query, params)
|
|
31
35
|
if is_select:
|
|
32
|
-
|
|
33
|
-
if len(
|
|
36
|
+
rows = self.cursor.fetchall()
|
|
37
|
+
if len(rows) == 0:
|
|
34
38
|
print("No results from query")
|
|
35
39
|
return None
|
|
40
|
+
if return_dict:
|
|
41
|
+
columns = [column[0] for column in self.cursor.description]
|
|
42
|
+
res = [dict(zip(columns, row)) for row in rows]
|
|
43
|
+
else:
|
|
44
|
+
res = rows
|
|
36
45
|
return res
|
|
37
46
|
else:
|
|
38
47
|
return None
|
|
@@ -44,15 +53,19 @@ class Utility:
|
|
|
44
53
|
def fetch_env(self, db_env):
|
|
45
54
|
"""Get env variable based on context, PROD or TEST"""
|
|
46
55
|
if db_env.upper() == "PROD":
|
|
47
|
-
connection_env = "DBCONNECTIONSTRINGPROD"
|
|
56
|
+
connection_env = "DBCONNECTIONSTRINGPROD"
|
|
48
57
|
return connection_env
|
|
49
58
|
if db_env.upper() == "TEST":
|
|
50
|
-
connection_env = "DBCONNECTIONSTRINGDEV"
|
|
59
|
+
connection_env = "DBCONNECTIONSTRINGDEV"
|
|
51
60
|
return connection_env
|
|
52
61
|
|
|
53
|
-
raise ValueError(
|
|
62
|
+
raise ValueError(
|
|
63
|
+
f"arg db_env is {db_env.upper()} but should be 'PROD' or 'TEST'"
|
|
64
|
+
)
|
|
54
65
|
|
|
55
|
-
def execute_stored_procedure(
|
|
66
|
+
def execute_stored_procedure(
|
|
67
|
+
self, stored_procedure: str, params: Dict[str, Tuple[type, Any]] | None = None
|
|
68
|
+
) -> Dict[str, Union[bool, str, Any]]:
|
|
56
69
|
"""
|
|
57
70
|
Executes a stored procedure with the given parameters.
|
|
58
71
|
|
|
@@ -76,12 +89,12 @@ class Utility:
|
|
|
76
89
|
"int": int,
|
|
77
90
|
"float": float,
|
|
78
91
|
"datetime": parser.isoparse,
|
|
79
|
-
"json": lambda x: json.dumps(x, ensure_ascii=False)
|
|
92
|
+
"json": lambda x: json.dumps(x, ensure_ascii=False),
|
|
80
93
|
}
|
|
81
94
|
|
|
82
95
|
try:
|
|
83
96
|
if params:
|
|
84
|
-
param_placeholders =
|
|
97
|
+
param_placeholders = ", ".join([f"@{key} = ?" for key in params.keys()])
|
|
85
98
|
param_values = []
|
|
86
99
|
|
|
87
100
|
for key, value in params.items():
|
|
@@ -92,7 +105,9 @@ class Utility:
|
|
|
92
105
|
else:
|
|
93
106
|
param_values.append(actual_value)
|
|
94
107
|
else:
|
|
95
|
-
raise ValueError(
|
|
108
|
+
raise ValueError(
|
|
109
|
+
"Each parameter value must be a tuple of (type, actual_value)."
|
|
110
|
+
)
|
|
96
111
|
|
|
97
112
|
sql = f"EXEC {stored_procedure} {param_placeholders}"
|
|
98
113
|
rows_updated = self.cursor.execute(sql, tuple(param_values))
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import os
|
|
4
4
|
|
|
5
|
+
import psutil
|
|
5
6
|
import uiautomation as auto
|
|
6
7
|
|
|
7
8
|
from .aftalebog import AftalebogHandler
|
|
@@ -158,6 +159,14 @@ class SolteqTandApp(
|
|
|
158
159
|
try:
|
|
159
160
|
if self.app_window:
|
|
160
161
|
self.close_window(self.app_window)
|
|
162
|
+
print(
|
|
163
|
+
"\n".join([p.info["name"] for p in psutil.process_iter(["name"])])
|
|
164
|
+
)
|
|
165
|
+
assert "TMTand.exe" not in [
|
|
166
|
+
p.info["name"] for p in psutil.process_iter(["name"])
|
|
167
|
+
]
|
|
161
168
|
self.app_window = None
|
|
162
169
|
except Exception as error:
|
|
163
|
-
|
|
170
|
+
raise RuntimeError(
|
|
171
|
+
f"Error closing Solteq Tand application window: {error}"
|
|
172
|
+
) from error
|
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
"""Base UI-Automation helper methods for SolteqTand project."""
|
|
2
|
+
|
|
2
3
|
import time
|
|
4
|
+
|
|
3
5
|
import uiautomation as auto
|
|
4
6
|
|
|
5
7
|
|
|
6
8
|
class BaseUI:
|
|
7
9
|
"""Base UI-Automation helper methods."""
|
|
8
10
|
|
|
9
|
-
def find_element_by_property(
|
|
11
|
+
def find_element_by_property(
|
|
12
|
+
self, control, control_type=None, automation_id=None, name=None, class_name=None
|
|
13
|
+
) -> auto.Control:
|
|
10
14
|
"""
|
|
11
15
|
Uses GetChildren to traverse through controls and find an element based on the specified properties.
|
|
12
16
|
|
|
@@ -24,20 +28,29 @@ class BaseUI:
|
|
|
24
28
|
|
|
25
29
|
for child in children:
|
|
26
30
|
if (
|
|
27
|
-
(control_type is None or child.ControlType == control_type)
|
|
28
|
-
(automation_id is None or child.AutomationId == automation_id)
|
|
29
|
-
(name is None or child.Name == name)
|
|
30
|
-
(class_name is None or child.ClassName == class_name)
|
|
31
|
+
(control_type is None or child.ControlType == control_type)
|
|
32
|
+
and (automation_id is None or child.AutomationId == automation_id)
|
|
33
|
+
and (name is None or child.Name == name)
|
|
34
|
+
and (class_name is None or child.ClassName == class_name)
|
|
31
35
|
):
|
|
32
36
|
return child
|
|
33
37
|
|
|
34
|
-
found = self.find_element_by_property(
|
|
38
|
+
found = self.find_element_by_property(
|
|
39
|
+
child, control_type, automation_id, name, class_name
|
|
40
|
+
)
|
|
35
41
|
if found:
|
|
36
42
|
return found
|
|
37
43
|
|
|
38
44
|
return None
|
|
39
45
|
|
|
40
|
-
def wait_for_control(
|
|
46
|
+
def wait_for_control(
|
|
47
|
+
self,
|
|
48
|
+
control_type,
|
|
49
|
+
search_params,
|
|
50
|
+
search_depth=1,
|
|
51
|
+
timeout=30,
|
|
52
|
+
retry_interval=0.5,
|
|
53
|
+
):
|
|
41
54
|
"""
|
|
42
55
|
Waits for a given control type to become available with the specified search parameters.
|
|
43
56
|
|
|
@@ -67,9 +80,13 @@ class BaseUI:
|
|
|
67
80
|
time.sleep(retry_interval)
|
|
68
81
|
print(f"Retrying to find control: {search_params}...")
|
|
69
82
|
|
|
70
|
-
raise TimeoutError(
|
|
83
|
+
raise TimeoutError(
|
|
84
|
+
f"Control with parameters {search_params} was not found within the {timeout} second timeout."
|
|
85
|
+
)
|
|
71
86
|
|
|
72
|
-
def wait_for_control_to_disappear(
|
|
87
|
+
def wait_for_control_to_disappear(
|
|
88
|
+
self, control_type, search_params, search_depth=1, timeout=30
|
|
89
|
+
):
|
|
73
90
|
"""
|
|
74
91
|
Waits for a given control type to disappear with the specified search parameters.
|
|
75
92
|
|
|
@@ -95,7 +112,9 @@ class BaseUI:
|
|
|
95
112
|
time.sleep(0.5)
|
|
96
113
|
print(f"Retrying to find control: {search_params}...")
|
|
97
114
|
|
|
98
|
-
raise TimeoutError(
|
|
115
|
+
raise TimeoutError(
|
|
116
|
+
f"Control with parameters {search_params} did not disappear within the timeout period."
|
|
117
|
+
)
|
|
99
118
|
|
|
100
119
|
def close_window(self, window_to_close: auto.WindowControl) -> None:
|
|
101
120
|
"""Closes specified window."""
|
|
@@ -105,7 +124,6 @@ class BaseUI:
|
|
|
105
124
|
|
|
106
125
|
# Handle popup when closin main window
|
|
107
126
|
if window_name.lower().startswith("hovedvindue"):
|
|
108
|
-
|
|
109
127
|
pop_up_window = window_to_close.WindowControl(Name="TMT - Afslut")
|
|
110
128
|
pop_up_window.SetFocus()
|
|
111
129
|
pop_up_window.ButtonControl(Name="Ja").Click(simulateMove=False, waitTime=0)
|
|
@@ -113,4 +131,7 @@ class BaseUI:
|
|
|
113
131
|
time.sleep(2)
|
|
114
132
|
|
|
115
133
|
else:
|
|
116
|
-
self.app_window = self.wait_for_control(
|
|
134
|
+
self.app_window = self.wait_for_control(
|
|
135
|
+
search_params={"AutomationId": "FormFront"},
|
|
136
|
+
control_type=auto.WindowControl,
|
|
137
|
+
)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mbu_dev_shared_components
|
|
3
|
-
Version: 4.1
|
|
3
|
+
Version: 4.2.1
|
|
4
4
|
Summary: Shared components to use in RPA projects
|
|
5
5
|
Author-email: MBU <rpa@mbu.aarhus.dk>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -12,6 +12,7 @@ License-File: LICENSE
|
|
|
12
12
|
Requires-Dist: cryptography>=43.0.0
|
|
13
13
|
Requires-Dist: pyodbc>=5.1.0
|
|
14
14
|
Requires-Dist: python-dateutil==2.9.*
|
|
15
|
+
Requires-Dist: dotenv
|
|
15
16
|
Provides-Extra: getorganized
|
|
16
17
|
Requires-Dist: requests_ntlm>=1.2.0; extra == "getorganized"
|
|
17
18
|
Provides-Extra: google
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "mbu_dev_shared_components"
|
|
7
|
-
version = "4.1
|
|
7
|
+
version = "4.2.1"
|
|
8
8
|
authors = [
|
|
9
9
|
{ name="MBU", email="rpa@mbu.aarhus.dk" },
|
|
10
10
|
]
|
|
@@ -20,6 +20,7 @@ dependencies = [
|
|
|
20
20
|
"cryptography >= 43.0.0",
|
|
21
21
|
"pyodbc >= 5.1.0",
|
|
22
22
|
"python-dateutil == 2.9.*",
|
|
23
|
+
"dotenv",
|
|
23
24
|
]
|
|
24
25
|
|
|
25
26
|
[project.optional-dependencies]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|