eido 0.2.2__tar.gz → 0.2.3__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.
- {eido-0.2.2/eido.egg-info → eido-0.2.3}/PKG-INFO +4 -3
- {eido-0.2.2 → eido-0.2.3}/README.md +1 -1
- eido-0.2.3/eido/_version.py +1 -0
- {eido-0.2.2 → eido-0.2.3}/eido/const.py +8 -3
- {eido-0.2.2 → eido-0.2.3}/eido/conversion.py +9 -6
- {eido-0.2.2 → eido-0.2.3}/eido/conversion_plugins.py +9 -6
- {eido-0.2.2 → eido-0.2.3}/eido/inspection.py +8 -7
- {eido-0.2.2 → eido-0.2.3}/eido/schema.py +8 -16
- {eido-0.2.2 → eido-0.2.3}/eido/validation.py +38 -23
- {eido-0.2.2 → eido-0.2.3/eido.egg-info}/PKG-INFO +4 -3
- eido-0.2.3/eido.egg-info/requires.txt +8 -0
- eido-0.2.3/requirements/requirements-all.txt +6 -0
- eido-0.2.2/eido/_version.py +0 -1
- eido-0.2.2/eido.egg-info/requires.txt +0 -5
- eido-0.2.2/requirements/requirements-all.txt +0 -5
- {eido-0.2.2 → eido-0.2.3}/LICENSE.txt +0 -0
- {eido-0.2.2 → eido-0.2.3}/MANIFEST.in +0 -0
- {eido-0.2.2 → eido-0.2.3}/eido/__init__.py +0 -0
- {eido-0.2.2 → eido-0.2.3}/eido/__main__.py +0 -0
- {eido-0.2.2 → eido-0.2.3}/eido/argparser.py +0 -0
- {eido-0.2.2 → eido-0.2.3}/eido/cli.py +0 -0
- {eido-0.2.2 → eido-0.2.3}/eido/exceptions.py +0 -0
- {eido-0.2.2 → eido-0.2.3}/eido/output_formatters.py +0 -0
- {eido-0.2.2 → eido-0.2.3}/eido.egg-info/SOURCES.txt +0 -0
- {eido-0.2.2 → eido-0.2.3}/eido.egg-info/dependency_links.txt +0 -0
- {eido-0.2.2 → eido-0.2.3}/eido.egg-info/entry_points.txt +0 -0
- {eido-0.2.2 → eido-0.2.3}/eido.egg-info/top_level.txt +0 -0
- {eido-0.2.2 → eido-0.2.3}/requirements/requirements-doc.txt +0 -0
- {eido-0.2.2 → eido-0.2.3}/requirements/requirements-test.txt +0 -0
- {eido-0.2.2 → eido-0.2.3}/setup.cfg +0 -0
- {eido-0.2.2 → eido-0.2.3}/setup.py +0 -0
- {eido-0.2.2 → eido-0.2.3}/tests/test_conversions.py +0 -0
- {eido-0.2.2 → eido-0.2.3}/tests/test_schema_operations.py +0 -0
- {eido-0.2.2 → eido-0.2.3}/tests/test_validations.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: eido
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.3
|
|
4
4
|
Summary: A project metadata validator
|
|
5
5
|
Home-page: https://github.com/pepkit/eido/
|
|
6
6
|
Author: Michal Stolarczyk, Nathan Sheffield
|
|
@@ -15,10 +15,11 @@ Classifier: Programming Language :: Python :: 3.11
|
|
|
15
15
|
Classifier: Topic :: Scientific/Engineering :: Bio-Informatics
|
|
16
16
|
Description-Content-Type: text/markdown
|
|
17
17
|
License-File: LICENSE.txt
|
|
18
|
+
Requires-Dist: importlib-metadata; python_version < "3.10"
|
|
18
19
|
Requires-Dist: jsonschema>=3.0.1
|
|
19
20
|
Requires-Dist: logmuse>=0.2.5
|
|
20
21
|
Requires-Dist: pandas
|
|
21
|
-
Requires-Dist: peppy>=0.
|
|
22
|
+
Requires-Dist: peppy>=0.40.6
|
|
22
23
|
Requires-Dist: ubiquerg>=0.5.2
|
|
23
24
|
|
|
24
25
|
# <img src="docs/img/eido.svg" alt="eido logo" height="70">
|
|
@@ -28,4 +29,4 @@ Requires-Dist: ubiquerg>=0.5.2
|
|
|
28
29
|
[](http://pepkit.github.io)
|
|
29
30
|
[](https://github.com/psf/black)
|
|
30
31
|
|
|
31
|
-
[PEP](
|
|
32
|
+
[PEP](https://pep.databio.org) validation tool based on [jsonschema](https://github.com/Julian/jsonschema). See [documentation](http://pep.databio.org/eido) for usage.
|
|
@@ -5,4 +5,4 @@
|
|
|
5
5
|
[](http://pepkit.github.io)
|
|
6
6
|
[](https://github.com/psf/black)
|
|
7
7
|
|
|
8
|
-
[PEP](
|
|
8
|
+
[PEP](https://pep.databio.org) validation tool based on [jsonschema](https://github.com/Julian/jsonschema). See [documentation](http://pep.databio.org/eido) for usage.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.2.3"
|
|
@@ -14,8 +14,11 @@ SUBPARSER_MSGS = {
|
|
|
14
14
|
CONVERT_CMD: "Convert PEP format using filters",
|
|
15
15
|
}
|
|
16
16
|
PROP_KEY = "properties"
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
|
|
18
|
+
SAMPLES_KEY = "samples"
|
|
19
|
+
|
|
20
|
+
TANGIBLE_KEY = "tangible"
|
|
21
|
+
SIZING_KEY = "sizing"
|
|
19
22
|
|
|
20
23
|
# sample schema input validation key names, these values are required by looper
|
|
21
24
|
# to refer to the dict values
|
|
@@ -34,7 +37,9 @@ GENERAL = [
|
|
|
34
37
|
"FILTERS_CMD",
|
|
35
38
|
"SUBPARSER_MSGS",
|
|
36
39
|
]
|
|
37
|
-
|
|
40
|
+
|
|
41
|
+
SCHEMA_SECTIONS = ["PROP_KEY", "TANGIBLE_KEY", "SIZING_KEY"]
|
|
42
|
+
|
|
38
43
|
SCHEMA_VALIDAION_KEYS = [
|
|
39
44
|
"MISSING_KEY",
|
|
40
45
|
"REQUIRED_INPUTS_KEY",
|
|
@@ -1,12 +1,15 @@
|
|
|
1
|
-
import inspect
|
|
2
1
|
import sys
|
|
3
|
-
import os
|
|
4
|
-
from logging import getLogger
|
|
5
2
|
|
|
6
|
-
|
|
3
|
+
if sys.version_info < (3, 10):
|
|
4
|
+
from importlib_metadata import entry_points
|
|
5
|
+
else:
|
|
6
|
+
from importlib.metadata import entry_points
|
|
7
|
+
import inspect
|
|
8
|
+
from logging import getLogger
|
|
9
|
+
import os
|
|
10
|
+
from typing import NoReturn
|
|
7
11
|
|
|
8
12
|
from .exceptions import *
|
|
9
|
-
from typing import NoReturn
|
|
10
13
|
|
|
11
14
|
_LOGGER = getLogger(__name__)
|
|
12
15
|
|
|
@@ -21,7 +24,7 @@ def pep_conversion_plugins():
|
|
|
21
24
|
:raise EidoFilterError: if any of the filters has an invalid signature.
|
|
22
25
|
"""
|
|
23
26
|
plugins = {}
|
|
24
|
-
for ep in
|
|
27
|
+
for ep in entry_points(group="pep.filters"):
|
|
25
28
|
plugin_fun = ep.load()
|
|
26
29
|
if len(list(inspect.signature(plugin_fun).parameters)) != 2:
|
|
27
30
|
raise EidoFilterError(
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
""" built-in PEP filters """
|
|
2
|
+
|
|
2
3
|
from typing import Dict
|
|
3
4
|
from .output_formatters import MultilineOutputFormatter
|
|
4
5
|
|
|
@@ -73,10 +74,12 @@ def processed_pep_filter(p, **kwargs) -> Dict[str, str]:
|
|
|
73
74
|
|
|
74
75
|
return {
|
|
75
76
|
"project": str(prj_repr),
|
|
76
|
-
"samples":
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
"subsamples":
|
|
80
|
-
|
|
81
|
-
|
|
77
|
+
"samples": (
|
|
78
|
+
str(p.samples) if samples_as_objects else str(p.sample_table.to_csv())
|
|
79
|
+
),
|
|
80
|
+
"subsamples": (
|
|
81
|
+
str(p.subsamples)
|
|
82
|
+
if subsamples_as_objects
|
|
83
|
+
else str(p.subsample_table.to_csv())
|
|
84
|
+
),
|
|
82
85
|
}
|
|
@@ -7,12 +7,13 @@ from ubiquerg import size
|
|
|
7
7
|
|
|
8
8
|
from .const import (
|
|
9
9
|
ALL_INPUTS_KEY,
|
|
10
|
-
FILES_KEY,
|
|
11
10
|
INPUT_FILE_SIZE_KEY,
|
|
12
11
|
MISSING_KEY,
|
|
13
12
|
PROP_KEY,
|
|
14
|
-
REQUIRED_FILES_KEY,
|
|
15
13
|
REQUIRED_INPUTS_KEY,
|
|
14
|
+
SIZING_KEY,
|
|
15
|
+
TANGIBLE_KEY,
|
|
16
|
+
SAMPLES_KEY,
|
|
16
17
|
)
|
|
17
18
|
from .schema import read_schema
|
|
18
19
|
from .validation import _validate_sample_object, _get_attr_values
|
|
@@ -67,12 +68,12 @@ def get_input_files_size(sample, schema):
|
|
|
67
68
|
all_inputs = set()
|
|
68
69
|
required_inputs = set()
|
|
69
70
|
schema = schema[-1] # use only first schema, in case there are imports
|
|
70
|
-
sample_schema_dict = schema[
|
|
71
|
-
if
|
|
72
|
-
all_inputs.update(_get_attr_values(sample, sample_schema_dict[
|
|
73
|
-
if
|
|
71
|
+
sample_schema_dict = schema[PROP_KEY][SAMPLES_KEY]["items"]
|
|
72
|
+
if SIZING_KEY in sample_schema_dict:
|
|
73
|
+
all_inputs.update(_get_attr_values(sample, sample_schema_dict[SIZING_KEY]))
|
|
74
|
+
if TANGIBLE_KEY in sample_schema_dict:
|
|
74
75
|
required_inputs = set(
|
|
75
|
-
_get_attr_values(sample, sample_schema_dict[
|
|
76
|
+
_get_attr_values(sample, sample_schema_dict[TANGIBLE_KEY])
|
|
76
77
|
)
|
|
77
78
|
all_inputs.update(required_inputs)
|
|
78
79
|
with catch_warnings(record=True) as w:
|
|
@@ -2,7 +2,7 @@ from logging import getLogger
|
|
|
2
2
|
|
|
3
3
|
from peppy.utils import load_yaml
|
|
4
4
|
|
|
5
|
-
from .const import
|
|
5
|
+
from .const import SAMPLES_KEY, PROP_KEY
|
|
6
6
|
|
|
7
7
|
_LOGGER = getLogger(__name__)
|
|
8
8
|
|
|
@@ -21,23 +21,15 @@ def preprocess_schema(schema_dict):
|
|
|
21
21
|
:return dict: preprocessed schema
|
|
22
22
|
"""
|
|
23
23
|
_LOGGER.debug(f"schema ori: {schema_dict}")
|
|
24
|
-
if "
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
_LOGGER.debug("No config section found in schema")
|
|
29
|
-
if "samples" in schema_dict[PROP_KEY]:
|
|
30
|
-
schema_dict[PROP_KEY]["_samples"] = schema_dict[PROP_KEY]["samples"]
|
|
31
|
-
del schema_dict[PROP_KEY]["samples"]
|
|
32
|
-
if "required" in schema_dict:
|
|
33
|
-
schema_dict["required"][
|
|
34
|
-
schema_dict["required"].index("samples")
|
|
35
|
-
] = "_samples"
|
|
24
|
+
if "project" not in schema_dict[PROP_KEY]:
|
|
25
|
+
_LOGGER.debug("No project section found in schema")
|
|
26
|
+
|
|
27
|
+
if SAMPLES_KEY in schema_dict[PROP_KEY]:
|
|
36
28
|
if (
|
|
37
|
-
"items" in schema_dict[PROP_KEY][
|
|
38
|
-
and PROP_KEY in schema_dict[PROP_KEY][
|
|
29
|
+
"items" in schema_dict[PROP_KEY][SAMPLES_KEY]
|
|
30
|
+
and PROP_KEY in schema_dict[PROP_KEY][SAMPLES_KEY]["items"]
|
|
39
31
|
):
|
|
40
|
-
s_props = schema_dict[PROP_KEY][
|
|
32
|
+
s_props = schema_dict[PROP_KEY][SAMPLES_KEY]["items"][PROP_KEY]
|
|
41
33
|
for prop, val in s_props.items():
|
|
42
34
|
if "type" in val and val["type"] in ["string", "number", "boolean"]:
|
|
43
35
|
s_props[prop] = {}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import os
|
|
2
|
+
from typing import NoReturn, Mapping, Union
|
|
2
3
|
from copy import deepcopy as dpcpy
|
|
3
4
|
from logging import getLogger
|
|
4
5
|
|
|
@@ -6,28 +7,25 @@ from warnings import warn
|
|
|
6
7
|
|
|
7
8
|
from .exceptions import EidoValidationError
|
|
8
9
|
|
|
9
|
-
|
|
10
10
|
from pandas.core.common import flatten
|
|
11
11
|
from jsonschema import Draft7Validator
|
|
12
|
+
import peppy
|
|
12
13
|
|
|
13
|
-
from .const import
|
|
14
|
-
FILES_KEY,
|
|
15
|
-
PROP_KEY,
|
|
16
|
-
REQUIRED_FILES_KEY,
|
|
17
|
-
)
|
|
14
|
+
from .const import PROP_KEY, SIZING_KEY, TANGIBLE_KEY, SAMPLES_KEY
|
|
18
15
|
from .exceptions import PathAttrNotFoundError
|
|
19
16
|
from .schema import preprocess_schema, read_schema
|
|
20
17
|
|
|
21
18
|
_LOGGER = getLogger(__name__)
|
|
22
19
|
|
|
23
20
|
|
|
24
|
-
def _validate_object(obj, schema, sample_name_colname=False):
|
|
21
|
+
def _validate_object(obj: Mapping, schema: Union[str, dict], sample_name_colname=False):
|
|
25
22
|
"""
|
|
26
23
|
Generic function to validate object against a schema
|
|
27
24
|
|
|
28
25
|
:param Mapping obj: an object to validate
|
|
29
26
|
:param str | dict schema: schema dict to validate against or a path to one
|
|
30
27
|
from the error. Useful when used ith large projects
|
|
28
|
+
|
|
31
29
|
:raises EidoValidationError: if validation is unsuccessful
|
|
32
30
|
"""
|
|
33
31
|
validator = Draft7Validator(schema)
|
|
@@ -58,13 +56,16 @@ def _validate_object(obj, schema, sample_name_colname=False):
|
|
|
58
56
|
_LOGGER.debug("Validation was successful...")
|
|
59
57
|
|
|
60
58
|
|
|
61
|
-
def validate_project(project, schema):
|
|
59
|
+
def validate_project(project: peppy.Project, schema: Union[str, dict]) -> NoReturn:
|
|
62
60
|
"""
|
|
63
61
|
Validate a project object against a schema
|
|
64
62
|
|
|
65
63
|
:param peppy.Project project: a project object to validate
|
|
66
64
|
:param str | dict schema: schema dict to validate against or a path to one
|
|
67
65
|
from the error. Useful when used ith large projects
|
|
66
|
+
|
|
67
|
+
:return: NoReturn
|
|
68
|
+
:raises EidoValidationError: if validation is unsuccessful
|
|
68
69
|
"""
|
|
69
70
|
sample_name_colname = project.sample_name_colname
|
|
70
71
|
schema_dicts = read_schema(schema=schema)
|
|
@@ -76,7 +77,7 @@ def validate_project(project, schema):
|
|
|
76
77
|
_LOGGER.debug("Project validation successful")
|
|
77
78
|
|
|
78
79
|
|
|
79
|
-
def _validate_sample_object(sample, schemas):
|
|
80
|
+
def _validate_sample_object(sample: peppy.Sample, schemas):
|
|
80
81
|
"""
|
|
81
82
|
Internal function that allows to validate a peppy.Sample object without
|
|
82
83
|
requiring a reference to peppy.Project.
|
|
@@ -86,20 +87,24 @@ def _validate_sample_object(sample, schemas):
|
|
|
86
87
|
"""
|
|
87
88
|
for schema_dict in schemas:
|
|
88
89
|
schema_dict = preprocess_schema(schema_dict)
|
|
89
|
-
sample_schema_dict = schema_dict[PROP_KEY][
|
|
90
|
+
sample_schema_dict = schema_dict[PROP_KEY][SAMPLES_KEY]["items"]
|
|
90
91
|
_validate_object(sample.to_dict(), sample_schema_dict)
|
|
91
92
|
_LOGGER.debug(
|
|
92
93
|
f"{getattr(sample, 'sample_name', '')} sample validation successful"
|
|
93
94
|
)
|
|
94
95
|
|
|
95
96
|
|
|
96
|
-
def validate_sample(
|
|
97
|
+
def validate_sample(
|
|
98
|
+
project: peppy.Project, sample_name: Union[str, int], schema: Union[str, dict]
|
|
99
|
+
) -> NoReturn:
|
|
97
100
|
"""
|
|
98
101
|
Validate the selected sample object against a schema
|
|
99
102
|
|
|
100
103
|
:param peppy.Project project: a project object to validate
|
|
101
104
|
:param str | int sample_name: name or index of the sample to validate
|
|
102
105
|
:param str | dict schema: schema dict to validate against or a path to one
|
|
106
|
+
|
|
107
|
+
:raises EidoValidationError: if validation is unsuccessful
|
|
103
108
|
"""
|
|
104
109
|
sample = (
|
|
105
110
|
project.samples[sample_name]
|
|
@@ -112,7 +117,9 @@ def validate_sample(project, sample_name, schema):
|
|
|
112
117
|
)
|
|
113
118
|
|
|
114
119
|
|
|
115
|
-
def validate_config(
|
|
120
|
+
def validate_config(
|
|
121
|
+
project: Union[peppy.Project, dict], schema: Union[str, dict]
|
|
122
|
+
) -> NoReturn:
|
|
116
123
|
"""
|
|
117
124
|
Validate the config part of the Project object against a schema
|
|
118
125
|
|
|
@@ -123,17 +130,21 @@ def validate_config(project, schema):
|
|
|
123
130
|
for schema_dict in schema_dicts:
|
|
124
131
|
schema_cpy = preprocess_schema(dpcpy(schema_dict))
|
|
125
132
|
try:
|
|
126
|
-
del schema_cpy[PROP_KEY][
|
|
133
|
+
del schema_cpy[PROP_KEY][SAMPLES_KEY]
|
|
127
134
|
except KeyError:
|
|
128
135
|
pass
|
|
129
136
|
if "required" in schema_cpy:
|
|
130
137
|
try:
|
|
131
|
-
schema_cpy["required"].remove(
|
|
138
|
+
schema_cpy["required"].remove(SAMPLES_KEY)
|
|
132
139
|
except ValueError:
|
|
133
140
|
pass
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
141
|
+
if isinstance(project, dict):
|
|
142
|
+
_validate_object({"project": project}, schema_cpy)
|
|
143
|
+
|
|
144
|
+
else:
|
|
145
|
+
project_dict = project.to_dict()
|
|
146
|
+
_validate_object(project_dict, schema_cpy)
|
|
147
|
+
_LOGGER.debug("Config validation successful")
|
|
137
148
|
|
|
138
149
|
|
|
139
150
|
def _get_attr_values(obj, attrlist):
|
|
@@ -157,7 +168,11 @@ def _get_attr_values(obj, attrlist):
|
|
|
157
168
|
return list(flatten([getattr(obj, attr, "") for attr in attrlist]))
|
|
158
169
|
|
|
159
170
|
|
|
160
|
-
def validate_input_files(
|
|
171
|
+
def validate_input_files(
|
|
172
|
+
project: peppy.Project,
|
|
173
|
+
schemas: Union[str, dict],
|
|
174
|
+
sample_name: Union[str, int] = None,
|
|
175
|
+
):
|
|
161
176
|
"""
|
|
162
177
|
Determine which of the required and optional files are missing.
|
|
163
178
|
|
|
@@ -197,12 +212,12 @@ def validate_input_files(project, schemas, sample_name=None):
|
|
|
197
212
|
all_inputs = set()
|
|
198
213
|
required_inputs = set()
|
|
199
214
|
schema = schemas[-1] # use only first schema, in case there are imports
|
|
200
|
-
sample_schema_dict = schema[
|
|
201
|
-
if
|
|
202
|
-
all_inputs.update(_get_attr_values(sample, sample_schema_dict[
|
|
203
|
-
if
|
|
215
|
+
sample_schema_dict = schema[PROP_KEY][SAMPLES_KEY]["items"]
|
|
216
|
+
if SIZING_KEY in sample_schema_dict:
|
|
217
|
+
all_inputs.update(_get_attr_values(sample, sample_schema_dict[SIZING_KEY]))
|
|
218
|
+
if TANGIBLE_KEY in sample_schema_dict:
|
|
204
219
|
required_inputs = set(
|
|
205
|
-
_get_attr_values(sample, sample_schema_dict[
|
|
220
|
+
_get_attr_values(sample, sample_schema_dict[TANGIBLE_KEY])
|
|
206
221
|
)
|
|
207
222
|
all_inputs.update(required_inputs)
|
|
208
223
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: eido
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.3
|
|
4
4
|
Summary: A project metadata validator
|
|
5
5
|
Home-page: https://github.com/pepkit/eido/
|
|
6
6
|
Author: Michal Stolarczyk, Nathan Sheffield
|
|
@@ -15,10 +15,11 @@ Classifier: Programming Language :: Python :: 3.11
|
|
|
15
15
|
Classifier: Topic :: Scientific/Engineering :: Bio-Informatics
|
|
16
16
|
Description-Content-Type: text/markdown
|
|
17
17
|
License-File: LICENSE.txt
|
|
18
|
+
Requires-Dist: importlib-metadata; python_version < "3.10"
|
|
18
19
|
Requires-Dist: jsonschema>=3.0.1
|
|
19
20
|
Requires-Dist: logmuse>=0.2.5
|
|
20
21
|
Requires-Dist: pandas
|
|
21
|
-
Requires-Dist: peppy>=0.
|
|
22
|
+
Requires-Dist: peppy>=0.40.6
|
|
22
23
|
Requires-Dist: ubiquerg>=0.5.2
|
|
23
24
|
|
|
24
25
|
# <img src="docs/img/eido.svg" alt="eido logo" height="70">
|
|
@@ -28,4 +29,4 @@ Requires-Dist: ubiquerg>=0.5.2
|
|
|
28
29
|
[](http://pepkit.github.io)
|
|
29
30
|
[](https://github.com/psf/black)
|
|
30
31
|
|
|
31
|
-
[PEP](
|
|
32
|
+
[PEP](https://pep.databio.org) validation tool based on [jsonschema](https://github.com/Julian/jsonschema). See [documentation](http://pep.databio.org/eido) for usage.
|
eido-0.2.2/eido/_version.py
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "0.2.2"
|
|
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
|