gooddata-pandas 1.44.0__py3-none-any.whl → 1.44.1.dev2__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 gooddata-pandas might be problematic. Click here for more details.
- gooddata_pandas/data_access.py +13 -2
- gooddata_pandas/dataframe.py +21 -2
- gooddata_pandas/series.py +7 -0
- {gooddata_pandas-1.44.0.dist-info → gooddata_pandas-1.44.1.dev2.dist-info}/METADATA +3 -3
- gooddata_pandas-1.44.1.dev2.dist-info/RECORD +14 -0
- gooddata_pandas-1.44.0.dist-info/RECORD +0 -14
- {gooddata_pandas-1.44.0.dist-info → gooddata_pandas-1.44.1.dev2.dist-info}/WHEEL +0 -0
- {gooddata_pandas-1.44.0.dist-info → gooddata_pandas-1.44.1.dev2.dist-info}/licenses/LICENSE.txt +0 -0
- {gooddata_pandas-1.44.0.dist-info → gooddata_pandas-1.44.1.dev2.dist-info}/top_level.txt +0 -0
gooddata_pandas/data_access.py
CHANGED
|
@@ -33,7 +33,7 @@ from gooddata_pandas.utils import (
|
|
|
33
33
|
class ExecutionDefinitionBuilder:
|
|
34
34
|
_DEFAULT_INDEX_NAME: str = "0"
|
|
35
35
|
|
|
36
|
-
def __init__(self, columns: ColumnsDef, index_by: Optional[IndexDef] = None) -> None:
|
|
36
|
+
def __init__(self, columns: ColumnsDef, index_by: Optional[IndexDef] = None, is_cancellable: bool = False) -> None:
|
|
37
37
|
"""
|
|
38
38
|
Initializes the ExecutionDefinitionBuilder instance with columns and an
|
|
39
39
|
optional index_by definition. Processes the given columns and index_by
|
|
@@ -42,6 +42,8 @@ class ExecutionDefinitionBuilder:
|
|
|
42
42
|
Args:
|
|
43
43
|
columns (ColumnsDef): Input columns to process and build internal mappings.
|
|
44
44
|
index_by (Optional[IndexDef], optional): Index definition to process. Defaults to None.
|
|
45
|
+
is_cancellable (Optional[bool]): Whether the execution of this definition should be cancelled when
|
|
46
|
+
the connection is interrupted.
|
|
45
47
|
|
|
46
48
|
"""
|
|
47
49
|
self._attributes: list[Attribute] = []
|
|
@@ -49,6 +51,7 @@ class ExecutionDefinitionBuilder:
|
|
|
49
51
|
self._col_to_attr_idx: dict[str, int] = dict()
|
|
50
52
|
self._index_to_attr_idx: dict[str, int] = dict()
|
|
51
53
|
self._col_to_metric_idx: dict[str, int] = dict()
|
|
54
|
+
self._is_cancellable = is_cancellable
|
|
52
55
|
|
|
53
56
|
self._process_columns(columns)
|
|
54
57
|
self._process_index(index_by)
|
|
@@ -248,6 +251,7 @@ class ExecutionDefinitionBuilder:
|
|
|
248
251
|
metrics=self._metrics,
|
|
249
252
|
filters=filters,
|
|
250
253
|
dimensions=dimensions,
|
|
254
|
+
is_cancellable=self._is_cancellable,
|
|
251
255
|
)
|
|
252
256
|
|
|
253
257
|
|
|
@@ -257,6 +261,7 @@ def _compute(
|
|
|
257
261
|
columns: ColumnsDef,
|
|
258
262
|
index_by: Optional[IndexDef] = None,
|
|
259
263
|
filter_by: Optional[Union[Filter, list[Filter]]] = None,
|
|
264
|
+
is_cancellable: bool = False,
|
|
260
265
|
) -> tuple[Execution, dict[str, int], dict[str, int], dict[str, int]]:
|
|
261
266
|
"""
|
|
262
267
|
Internal function that computes an execution-by-convention to retrieve data for a data frame with the provided
|
|
@@ -268,6 +273,8 @@ def _compute(
|
|
|
268
273
|
columns (ColumnsDef): The columns definition.
|
|
269
274
|
index_by (Optional[IndexDef]): The index definition, if any.
|
|
270
275
|
filter_by (Optional[Union[Filter, list[Filter]]]): A filter or a list of filters, if any.
|
|
276
|
+
is_cancellable (bool, optional): Whether the execution of this definition should be cancelled when
|
|
277
|
+
the connection is interrupted.
|
|
271
278
|
|
|
272
279
|
Returns:
|
|
273
280
|
tuple: A tuple containing the following elements:
|
|
@@ -277,7 +284,7 @@ def _compute(
|
|
|
277
284
|
- dict[str, int]: A mapping of pandas index names to attribute dimension indices.
|
|
278
285
|
"""
|
|
279
286
|
|
|
280
|
-
builder = ExecutionDefinitionBuilder(columns, index_by)
|
|
287
|
+
builder = ExecutionDefinitionBuilder(columns, index_by, is_cancellable=is_cancellable)
|
|
281
288
|
exec_def = builder.build_execution_definition(filter_by)
|
|
282
289
|
|
|
283
290
|
return (
|
|
@@ -413,6 +420,7 @@ def compute_and_extract(
|
|
|
413
420
|
index_by: Optional[IndexDef] = None,
|
|
414
421
|
filter_by: Optional[Union[Filter, list[Filter]]] = None,
|
|
415
422
|
on_execution_submitted: Optional[Callable[[Execution], None]] = None,
|
|
423
|
+
is_cancellable: bool = False,
|
|
416
424
|
) -> tuple[dict, dict]:
|
|
417
425
|
"""
|
|
418
426
|
Convenience function that computes and extracts data from the execution response.
|
|
@@ -425,6 +433,8 @@ def compute_and_extract(
|
|
|
425
433
|
filter_by (Optional[Union[Filter, list[Filter]]]): A filter or a list of filters, if any.
|
|
426
434
|
on_execution_submitted (Optional[Callable[[Execution], None]]): Callback to call when the execution was
|
|
427
435
|
submitted to the backend.
|
|
436
|
+
is_cancellable (bool, optional): Whether the execution of this definition should be cancelled when
|
|
437
|
+
the connection is interrupted.
|
|
428
438
|
|
|
429
439
|
Returns:
|
|
430
440
|
tuple: A tuple containing the following dictionaries:
|
|
@@ -440,6 +450,7 @@ def compute_and_extract(
|
|
|
440
450
|
index_by=index_by,
|
|
441
451
|
columns=columns,
|
|
442
452
|
filter_by=filter_by,
|
|
453
|
+
is_cancellable=is_cancellable,
|
|
443
454
|
)
|
|
444
455
|
|
|
445
456
|
execution, col_to_attr_idx, col_to_metric_idx, index_to_attr_idx = result
|
gooddata_pandas/dataframe.py
CHANGED
|
@@ -74,6 +74,7 @@ class DataFrameFactory:
|
|
|
74
74
|
columns: ColumnsDef,
|
|
75
75
|
filter_by: Optional[Union[Filter, list[Filter]]] = None,
|
|
76
76
|
on_execution_submitted: Optional[Callable[[Execution], None]] = None,
|
|
77
|
+
is_cancellable: bool = False,
|
|
77
78
|
) -> pandas.DataFrame:
|
|
78
79
|
"""
|
|
79
80
|
Creates a data frame indexed by values of the label. The data frame columns will be created from either
|
|
@@ -88,6 +89,7 @@ class DataFrameFactory:
|
|
|
88
89
|
Optional filters to apply during computation on the server.
|
|
89
90
|
on_execution_submitted (Optional[Callable[[Execution], None]]): Callback to call when the execution was
|
|
90
91
|
submitted to the backend.
|
|
92
|
+
is_cancellable (bool, optional): Whether the execution should be cancelled when the connection is interrupted.
|
|
91
93
|
|
|
92
94
|
Returns:
|
|
93
95
|
pandas.DataFrame: A DataFrame instance.
|
|
@@ -99,6 +101,7 @@ class DataFrameFactory:
|
|
|
99
101
|
index_by=index_by,
|
|
100
102
|
filter_by=filter_by,
|
|
101
103
|
on_execution_submitted=on_execution_submitted,
|
|
104
|
+
is_cancellable=is_cancellable,
|
|
102
105
|
)
|
|
103
106
|
|
|
104
107
|
_idx = make_pandas_index(index)
|
|
@@ -110,6 +113,7 @@ class DataFrameFactory:
|
|
|
110
113
|
columns: ColumnsDef,
|
|
111
114
|
filter_by: Optional[Union[Filter, list[Filter]]] = None,
|
|
112
115
|
on_execution_submitted: Optional[Callable[[Execution], None]] = None,
|
|
116
|
+
is_cancellable: bool = False,
|
|
113
117
|
) -> pandas.DataFrame:
|
|
114
118
|
"""
|
|
115
119
|
Creates a data frame with columns created from metrics and or labels.
|
|
@@ -120,6 +124,7 @@ class DataFrameFactory:
|
|
|
120
124
|
computation on the server.
|
|
121
125
|
on_execution_submitted (Optional[Callable[[Execution], None]]): Callback to call when the execution was
|
|
122
126
|
submitted to the backend.
|
|
127
|
+
is_cancellable (bool, optional): Whether the execution should be cancelled when the connection is interrupted.
|
|
123
128
|
|
|
124
129
|
Returns:
|
|
125
130
|
pandas.DataFrame: A DataFrame instance.
|
|
@@ -131,6 +136,7 @@ class DataFrameFactory:
|
|
|
131
136
|
columns=columns,
|
|
132
137
|
filter_by=filter_by,
|
|
133
138
|
on_execution_submitted=on_execution_submitted,
|
|
139
|
+
is_cancellable=is_cancellable,
|
|
134
140
|
)
|
|
135
141
|
|
|
136
142
|
return pandas.DataFrame(data=data)
|
|
@@ -141,6 +147,7 @@ class DataFrameFactory:
|
|
|
141
147
|
filter_by: Optional[Union[Filter, list[Filter]]] = None,
|
|
142
148
|
auto_index: bool = True,
|
|
143
149
|
on_execution_submitted: Optional[Callable[[Execution], None]] = None,
|
|
150
|
+
is_cancellable: bool = False,
|
|
144
151
|
) -> pandas.DataFrame:
|
|
145
152
|
"""
|
|
146
153
|
Creates a data frame for named items. This is a convenience method that will create DataFrame with or
|
|
@@ -154,6 +161,7 @@ class DataFrameFactory:
|
|
|
154
161
|
of the items.
|
|
155
162
|
on_execution_submitted (Optional[Callable[[Execution], None]]): Callback to call when the execution was
|
|
156
163
|
submitted to the backend.
|
|
164
|
+
is_cancellable (bool, optional): Whether the execution should be cancelled when the connection is interrupted.
|
|
157
165
|
|
|
158
166
|
Returns:
|
|
159
167
|
pandas.DataFrame: A DataFrame instance.
|
|
@@ -183,6 +191,7 @@ class DataFrameFactory:
|
|
|
183
191
|
columns=resolved_measure_cols,
|
|
184
192
|
filter_by=filter_by,
|
|
185
193
|
on_execution_submitted=on_execution_submitted,
|
|
194
|
+
is_cancellable=is_cancellable,
|
|
186
195
|
)
|
|
187
196
|
|
|
188
197
|
def for_visualization(
|
|
@@ -190,6 +199,7 @@ class DataFrameFactory:
|
|
|
190
199
|
visualization_id: str,
|
|
191
200
|
auto_index: bool = True,
|
|
192
201
|
on_execution_submitted: Optional[Callable[[Execution], None]] = None,
|
|
202
|
+
is_cancellable: bool = False,
|
|
193
203
|
) -> pandas.DataFrame:
|
|
194
204
|
"""
|
|
195
205
|
Creates a data frame with columns based on the content of the visualization with the provided identifier.
|
|
@@ -200,6 +210,7 @@ class DataFrameFactory:
|
|
|
200
210
|
of the visualization.
|
|
201
211
|
on_execution_submitted (Optional[Callable[[Execution], None]]): Callback to call when the execution was
|
|
202
212
|
submitted to the backend.
|
|
213
|
+
is_cancellable (bool, optional): Whether the execution should be cancelled when the connection is interrupted.
|
|
203
214
|
|
|
204
215
|
Returns:
|
|
205
216
|
pandas.DataFrame: A DataFrame instance.
|
|
@@ -215,13 +226,18 @@ class DataFrameFactory:
|
|
|
215
226
|
}
|
|
216
227
|
|
|
217
228
|
return self.for_items(
|
|
218
|
-
columns,
|
|
229
|
+
columns,
|
|
230
|
+
filter_by=filter_by,
|
|
231
|
+
auto_index=auto_index,
|
|
232
|
+
on_execution_submitted=on_execution_submitted,
|
|
233
|
+
is_cancellable=is_cancellable,
|
|
219
234
|
)
|
|
220
235
|
|
|
221
236
|
def for_created_visualization(
|
|
222
237
|
self,
|
|
223
238
|
created_visualizations_response: dict,
|
|
224
239
|
on_execution_submitted: Optional[Callable[[Execution], None]] = None,
|
|
240
|
+
is_cancellable: bool = False,
|
|
225
241
|
) -> tuple[pandas.DataFrame, DataFrameMetadata]:
|
|
226
242
|
"""
|
|
227
243
|
Creates a data frame using a created visualization.
|
|
@@ -230,11 +246,14 @@ class DataFrameFactory:
|
|
|
230
246
|
created_visualizations_response (dict): Created visualization response.
|
|
231
247
|
on_execution_submitted (Optional[Callable[[Execution], None]]): Callback to call when the execution was
|
|
232
248
|
submitted to the backend.
|
|
249
|
+
is_cancellable (bool, optional): Whether the execution should be cancelled when the connection is interrupted.
|
|
233
250
|
|
|
234
251
|
Returns:
|
|
235
252
|
pandas.DataFrame: A DataFrame instance.
|
|
236
253
|
"""
|
|
237
|
-
execution_definition = self._sdk.compute.build_exec_def_from_chat_result(
|
|
254
|
+
execution_definition = self._sdk.compute.build_exec_def_from_chat_result(
|
|
255
|
+
created_visualizations_response, is_cancellable=is_cancellable
|
|
256
|
+
)
|
|
238
257
|
return self.for_exec_def(
|
|
239
258
|
exec_def=execution_definition,
|
|
240
259
|
on_execution_submitted=on_execution_submitted,
|
gooddata_pandas/series.py
CHANGED
|
@@ -29,6 +29,7 @@ class SeriesFactory:
|
|
|
29
29
|
data_by: Union[SimpleMetric, str, ObjId, Attribute],
|
|
30
30
|
filter_by: Optional[Union[Filter, list[Filter]]] = None,
|
|
31
31
|
on_execution_submitted: Optional[Callable[[Execution], None]] = None,
|
|
32
|
+
is_cancellable: bool = False,
|
|
32
33
|
) -> pandas.Series:
|
|
33
34
|
"""Creates pandas Series from data points calculated from a single `data_by`.
|
|
34
35
|
|
|
@@ -65,6 +66,8 @@ class SeriesFactory:
|
|
|
65
66
|
on_execution_submitted (Optional[Callable[[Execution], None]]): Callback to call when the execution was
|
|
66
67
|
submitted to the backend.
|
|
67
68
|
|
|
69
|
+
is_cancellable (bool, optional): Whether the execution should be cancelled when the connection is interrupted.
|
|
70
|
+
|
|
68
71
|
Returns:
|
|
69
72
|
pandas.Series: pandas series instance
|
|
70
73
|
"""
|
|
@@ -76,6 +79,7 @@ class SeriesFactory:
|
|
|
76
79
|
columns={"_series": data_by},
|
|
77
80
|
filter_by=filter_by,
|
|
78
81
|
on_execution_submitted=on_execution_submitted,
|
|
82
|
+
is_cancellable=is_cancellable,
|
|
79
83
|
)
|
|
80
84
|
|
|
81
85
|
_idx = make_pandas_index(index)
|
|
@@ -88,6 +92,7 @@ class SeriesFactory:
|
|
|
88
92
|
granularity: Optional[Union[list[LabelItemDef], IndexDef]] = None,
|
|
89
93
|
filter_by: Optional[Union[Filter, list[Filter]]] = None,
|
|
90
94
|
on_execution_submitted: Optional[Callable[[Execution], None]] = None,
|
|
95
|
+
is_cancellable: bool = False,
|
|
91
96
|
) -> pandas.Series:
|
|
92
97
|
"""
|
|
93
98
|
Creates a pandas.Series from data points calculated from a single `data_by` without constructing an index.
|
|
@@ -116,6 +121,7 @@ class SeriesFactory:
|
|
|
116
121
|
Defaults to None.
|
|
117
122
|
on_execution_submitted (Optional[Callable[[Execution], None]]): Callback to call when the execution was
|
|
118
123
|
submitted to the backend.
|
|
124
|
+
is_cancellable (bool, optional): Whether the execution should be cancelled when the connection is interrupted.
|
|
119
125
|
|
|
120
126
|
Returns:
|
|
121
127
|
pandas.Series: The resulting pandas Series instance.
|
|
@@ -133,6 +139,7 @@ class SeriesFactory:
|
|
|
133
139
|
columns={"_series": data_by},
|
|
134
140
|
filter_by=filter_by,
|
|
135
141
|
on_execution_submitted=on_execution_submitted,
|
|
142
|
+
is_cancellable=is_cancellable,
|
|
136
143
|
)
|
|
137
144
|
|
|
138
145
|
return pandas.Series(data=data["_series"])
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: gooddata-pandas
|
|
3
|
-
Version: 1.44.
|
|
3
|
+
Version: 1.44.1.dev2
|
|
4
4
|
Summary: GoodData Cloud to pandas
|
|
5
5
|
Author: GoodData
|
|
6
6
|
Author-email: support@gooddata.com
|
|
7
7
|
License: MIT
|
|
8
|
-
Project-URL: Documentation, https://gooddata-pandas.readthedocs.io/en/v1.44.
|
|
8
|
+
Project-URL: Documentation, https://gooddata-pandas.readthedocs.io/en/v1.44.1.dev2
|
|
9
9
|
Project-URL: Source, https://github.com/gooddata/gooddata-python-sdk
|
|
10
10
|
Keywords: gooddata,pandas,series,data,frame,data_frame,analytics,headless,business,intelligence,headless-bi,cloud,native,semantic,layer,sql,metrics
|
|
11
11
|
Classifier: Development Status :: 5 - Production/Stable
|
|
@@ -23,7 +23,7 @@ Classifier: Typing :: Typed
|
|
|
23
23
|
Requires-Python: >=3.9.0
|
|
24
24
|
Description-Content-Type: text/markdown
|
|
25
25
|
License-File: LICENSE.txt
|
|
26
|
-
Requires-Dist: gooddata-sdk~=1.44.
|
|
26
|
+
Requires-Dist: gooddata-sdk~=1.44.1.dev2
|
|
27
27
|
Requires-Dist: pandas<3.0.0,>=2.0.0
|
|
28
28
|
Dynamic: author
|
|
29
29
|
Dynamic: author-email
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
gooddata_pandas/__init__.py,sha256=Ta3qIIDq7kBRUsYSV3aC69AQBFvFvhtWDQucgP-l88w,297
|
|
2
|
+
gooddata_pandas/_version.py,sha256=960vTs6l7xsN2BOXWCxOc4PSKdzzKhnNEPTMnmMTCQs,119
|
|
3
|
+
gooddata_pandas/data_access.py,sha256=VPFjlOVH4dsQvbspEkT6UG_g3yA9sE5g8OLSrqKaeH4,20129
|
|
4
|
+
gooddata_pandas/dataframe.py,sha256=EsOgO8O42JBg1as0RZVwbeVOlGlENpkEsvlL-Xi5Jsg,16679
|
|
5
|
+
gooddata_pandas/good_pandas.py,sha256=ePEm2Lmeiftz5td0BLC71q7my5Aj8aABn3xV0myRmqI,3444
|
|
6
|
+
gooddata_pandas/py.typed,sha256=u_MS29sadlaIqGRPYFjWml5u0gQnoQfvbsf9pu3TZJU,94
|
|
7
|
+
gooddata_pandas/result_convertor.py,sha256=r7uFrjeM6cxMy08YcS3LywF1iUPSyEyG3BAddh0DkIQ,25807
|
|
8
|
+
gooddata_pandas/series.py,sha256=ELBSg1jKy-AYrtXErpNhsmQ0Zd6mP1M6FNS6bGgNPyI,6780
|
|
9
|
+
gooddata_pandas/utils.py,sha256=JhWs0WYqg-9o3aWRP21ERFAxCKoT5oNKQ5mKlJh4uT4,8091
|
|
10
|
+
gooddata_pandas-1.44.1.dev2.dist-info/licenses/LICENSE.txt,sha256=3RjzQk8y9HG1_LgqvbEqWZKJnTQGOO1cpzYzBc13Myk,149825
|
|
11
|
+
gooddata_pandas-1.44.1.dev2.dist-info/METADATA,sha256=P1p0lbtujH7kvNeHpEjgdbNPzTQv5K0b_9BrjMFrZ40,3148
|
|
12
|
+
gooddata_pandas-1.44.1.dev2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
13
|
+
gooddata_pandas-1.44.1.dev2.dist-info/top_level.txt,sha256=B7K_WFxlxplJbEbv5Mf0YhX74dbOpTPgDX-W6I7CssI,16
|
|
14
|
+
gooddata_pandas-1.44.1.dev2.dist-info/RECORD,,
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
gooddata_pandas/__init__.py,sha256=Ta3qIIDq7kBRUsYSV3aC69AQBFvFvhtWDQucgP-l88w,297
|
|
2
|
-
gooddata_pandas/_version.py,sha256=960vTs6l7xsN2BOXWCxOc4PSKdzzKhnNEPTMnmMTCQs,119
|
|
3
|
-
gooddata_pandas/data_access.py,sha256=cGvg7Uk_G0DdLdqIzoZows-viQ8DE9Z3uKof31xCuKY,19408
|
|
4
|
-
gooddata_pandas/dataframe.py,sha256=E45gvV7C1Lv_6mfav2P-DJJcZsr1nbWC57VCDPdhumY,15612
|
|
5
|
-
gooddata_pandas/good_pandas.py,sha256=ePEm2Lmeiftz5td0BLC71q7my5Aj8aABn3xV0myRmqI,3444
|
|
6
|
-
gooddata_pandas/py.typed,sha256=u_MS29sadlaIqGRPYFjWml5u0gQnoQfvbsf9pu3TZJU,94
|
|
7
|
-
gooddata_pandas/result_convertor.py,sha256=r7uFrjeM6cxMy08YcS3LywF1iUPSyEyG3BAddh0DkIQ,25807
|
|
8
|
-
gooddata_pandas/series.py,sha256=S4h_GuapUTwpnbIEXnBH1Z_f1LpxsU9DR0amq2vB9Ww,6371
|
|
9
|
-
gooddata_pandas/utils.py,sha256=JhWs0WYqg-9o3aWRP21ERFAxCKoT5oNKQ5mKlJh4uT4,8091
|
|
10
|
-
gooddata_pandas-1.44.0.dist-info/licenses/LICENSE.txt,sha256=3RjzQk8y9HG1_LgqvbEqWZKJnTQGOO1cpzYzBc13Myk,149825
|
|
11
|
-
gooddata_pandas-1.44.0.dist-info/METADATA,sha256=YAWAGHjpZ9Z3yYQcvZ3UiNWX3OxHJvzsXpiWpvkLMbs,3133
|
|
12
|
-
gooddata_pandas-1.44.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
13
|
-
gooddata_pandas-1.44.0.dist-info/top_level.txt,sha256=B7K_WFxlxplJbEbv5Mf0YhX74dbOpTPgDX-W6I7CssI,16
|
|
14
|
-
gooddata_pandas-1.44.0.dist-info/RECORD,,
|
|
File without changes
|
{gooddata_pandas-1.44.0.dist-info → gooddata_pandas-1.44.1.dev2.dist-info}/licenses/LICENSE.txt
RENAMED
|
File without changes
|
|
File without changes
|