pyLodStorage 0.3.4__tar.gz → 0.3.6__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.
- {pylodstorage-0.3.4/pylodstorage.egg-info → pylodstorage-0.3.6}/PKG-INFO +1 -1
- {pylodstorage-0.3.4 → pylodstorage-0.3.6}/lodstorage/query.py +7 -0
- {pylodstorage-0.3.4 → pylodstorage-0.3.6}/lodstorage/trulytabular.py +87 -71
- {pylodstorage-0.3.4 → pylodstorage-0.3.6}/lodstorage/version.py +2 -2
- {pylodstorage-0.3.4 → pylodstorage-0.3.6/pylodstorage.egg-info}/PKG-INFO +1 -1
- {pylodstorage-0.3.4 → pylodstorage-0.3.6}/sampledata/endpoints.yaml +4 -2
- {pylodstorage-0.3.4 → pylodstorage-0.3.6}/LICENSE +0 -0
- {pylodstorage-0.3.4 → pylodstorage-0.3.6}/README.md +0 -0
- {pylodstorage-0.3.4 → pylodstorage-0.3.6}/lodstorage/__init__.py +0 -0
- {pylodstorage-0.3.4 → pylodstorage-0.3.6}/lodstorage/csv.py +0 -0
- {pylodstorage-0.3.4 → pylodstorage-0.3.6}/lodstorage/entity.py +0 -0
- {pylodstorage-0.3.4 → pylodstorage-0.3.6}/lodstorage/jsonable.py +0 -0
- {pylodstorage-0.3.4 → pylodstorage-0.3.6}/lodstorage/jsonpicklemixin.py +0 -0
- {pylodstorage-0.3.4 → pylodstorage-0.3.6}/lodstorage/lod.py +0 -0
- {pylodstorage-0.3.4 → pylodstorage-0.3.6}/lodstorage/mwTable.py +0 -0
- {pylodstorage-0.3.4 → pylodstorage-0.3.6}/lodstorage/plot.py +0 -0
- {pylodstorage-0.3.4 → pylodstorage-0.3.6}/lodstorage/querymain.py +0 -0
- {pylodstorage-0.3.4 → pylodstorage-0.3.6}/lodstorage/sample.py +0 -0
- {pylodstorage-0.3.4 → pylodstorage-0.3.6}/lodstorage/schema.py +0 -0
- {pylodstorage-0.3.4 → pylodstorage-0.3.6}/lodstorage/sparql.py +0 -0
- {pylodstorage-0.3.4 → pylodstorage-0.3.6}/lodstorage/sql.py +0 -0
- {pylodstorage-0.3.4 → pylodstorage-0.3.6}/lodstorage/storageconfig.py +0 -0
- {pylodstorage-0.3.4 → pylodstorage-0.3.6}/lodstorage/tabulateCounter.py +0 -0
- {pylodstorage-0.3.4 → pylodstorage-0.3.6}/lodstorage/uml.py +0 -0
- {pylodstorage-0.3.4 → pylodstorage-0.3.6}/lodstorage/xml.py +0 -0
- {pylodstorage-0.3.4 → pylodstorage-0.3.6}/lodstorage/yamlablemixin.py +0 -0
- {pylodstorage-0.3.4 → pylodstorage-0.3.6}/pylodstorage.egg-info/SOURCES.txt +0 -0
- {pylodstorage-0.3.4 → pylodstorage-0.3.6}/pylodstorage.egg-info/dependency_links.txt +0 -0
- {pylodstorage-0.3.4 → pylodstorage-0.3.6}/pylodstorage.egg-info/entry_points.txt +0 -0
- {pylodstorage-0.3.4 → pylodstorage-0.3.6}/pylodstorage.egg-info/requires.txt +0 -0
- {pylodstorage-0.3.4 → pylodstorage-0.3.6}/pylodstorage.egg-info/top_level.txt +0 -0
- {pylodstorage-0.3.4 → pylodstorage-0.3.6}/sampledata/__init__.py +0 -0
- {pylodstorage-0.3.4 → pylodstorage-0.3.6}/sampledata/formats.yaml +0 -0
- {pylodstorage-0.3.4 → pylodstorage-0.3.6}/sampledata/queries.yaml +0 -0
- {pylodstorage-0.3.4 → pylodstorage-0.3.6}/sampledata/scholia.yaml +0 -0
- {pylodstorage-0.3.4 → pylodstorage-0.3.6}/sampledata/trulytabular.yaml +0 -0
- {pylodstorage-0.3.4 → pylodstorage-0.3.6}/sampledata/wf.yaml +0 -0
- {pylodstorage-0.3.4 → pylodstorage-0.3.6}/sampledata/wikidata.yaml +0 -0
- {pylodstorage-0.3.4 → pylodstorage-0.3.6}/setup.cfg +0 -0
- {pylodstorage-0.3.4 → pylodstorage-0.3.6}/setup.py +0 -0
|
@@ -580,12 +580,19 @@ class Endpoint(JSONAble):
|
|
|
580
580
|
"lang": "sparql",
|
|
581
581
|
"endpoint": "https://query.wikidata.org/sparql",
|
|
582
582
|
"website": "https://query.wikidata.org/",
|
|
583
|
+
"database": "blazegraph",
|
|
583
584
|
"method": "POST",
|
|
584
585
|
"prefixes": "PREFIX bd: <http://www.bigdata.com/rdf#>\nPREFIX cc: <http://creativecommons.org/ns#>"
|
|
585
586
|
}
|
|
586
587
|
]
|
|
587
588
|
return samples
|
|
588
589
|
|
|
590
|
+
@classmethod
|
|
591
|
+
def getDefault(cls):
|
|
592
|
+
endpointConf=Endpoint()
|
|
593
|
+
endpointConf.fromDict(Endpoint.getSamples()[0])
|
|
594
|
+
return endpointConf
|
|
595
|
+
|
|
589
596
|
def __init__(self):
|
|
590
597
|
'''
|
|
591
598
|
constructor for setting defaults
|
|
@@ -5,7 +5,7 @@ Created on 2022-04-14
|
|
|
5
5
|
'''
|
|
6
6
|
import datetime
|
|
7
7
|
from lodstorage.sparql import SPARQL
|
|
8
|
-
from lodstorage.query import Query,QueryManager,YamlPath
|
|
8
|
+
from lodstorage.query import Query,QueryManager,YamlPath,Endpoint
|
|
9
9
|
from lodstorage.version import Version
|
|
10
10
|
from pathlib import Path
|
|
11
11
|
import os
|
|
@@ -74,23 +74,20 @@ class WikidataProperty():
|
|
|
74
74
|
'''
|
|
75
75
|
# the result dict
|
|
76
76
|
wdProperties={}
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
# get the
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
FILTER((LANG(?propertyLabel)) = "%s")
|
|
92
|
-
}""" % (valuesClause,lang)
|
|
93
|
-
cls.addPropertiesForQuery(wdProperties,sparql,query)
|
|
77
|
+
if len(propertyLabels)>0:
|
|
78
|
+
valuesClause=""
|
|
79
|
+
for propertyLabel in propertyLabels:
|
|
80
|
+
valuesClause+=f' "{propertyLabel}"@{lang}\n'
|
|
81
|
+
query=f"""# get the properties for the given labels
|
|
82
|
+
{WikidataItem.getPrefixes()}
|
|
83
|
+
SELECT ?property ?propertyLabel WHERE {{
|
|
84
|
+
VALUES ?propertyLabel {{
|
|
85
|
+
{valuesClause}
|
|
86
|
+
}}
|
|
87
|
+
?property rdf:type wikibase:Property;rdfs:label ?propertyLabel.
|
|
88
|
+
FILTER(LANG(?propertyLabel) = "{lang}")
|
|
89
|
+
}}"""
|
|
90
|
+
cls.addPropertiesForQuery(wdProperties,sparql,query)
|
|
94
91
|
return wdProperties
|
|
95
92
|
|
|
96
93
|
@classmethod
|
|
@@ -105,23 +102,21 @@ SELECT ?property ?propertyLabel WHERE {
|
|
|
105
102
|
'''
|
|
106
103
|
# the result dict
|
|
107
104
|
wdProperties={}
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
105
|
+
if len(propertyIds)>0:
|
|
106
|
+
valuesClause=""
|
|
107
|
+
for propertyId in propertyIds:
|
|
108
|
+
valuesClause+=f' wd:{propertyId}\n'
|
|
109
|
+
query=f"""
|
|
112
110
|
# get the property for the given property Ids
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
FILTER((LANG(?propertyLabel)) = "%s")
|
|
123
|
-
}""" % (valuesClause,lang)
|
|
124
|
-
cls.addPropertiesForQuery(wdProperties,sparql,query)
|
|
111
|
+
{WikidataItem.getPrefixes()}
|
|
112
|
+
SELECT ?property ?propertyLabel WHERE {{
|
|
113
|
+
VALUES ?property {{
|
|
114
|
+
{valuesClause}
|
|
115
|
+
}}
|
|
116
|
+
?property rdf:type wikibase:Property;rdfs:label ?propertyLabel.
|
|
117
|
+
FILTER(LANG(?propertyLabel) = "{lang}")
|
|
118
|
+
}}"""
|
|
119
|
+
cls.addPropertiesForQuery(wdProperties,sparql,query)
|
|
125
120
|
return wdProperties
|
|
126
121
|
|
|
127
122
|
@classmethod
|
|
@@ -160,6 +155,8 @@ class WikidataItem:
|
|
|
160
155
|
sparql(SPARQL): the sparql access to use
|
|
161
156
|
'''
|
|
162
157
|
self.qid=qid
|
|
158
|
+
# numeric qid
|
|
159
|
+
self.qnumber=int(qid[1:])
|
|
163
160
|
self.url=f"https://www.wikidata.org/wiki/{self.qid}"
|
|
164
161
|
self.lang=lang
|
|
165
162
|
self.sparql=sparql
|
|
@@ -195,13 +192,16 @@ class WikidataItem:
|
|
|
195
192
|
|
|
196
193
|
@classmethod
|
|
197
194
|
def getPrefixes(cls):
|
|
198
|
-
|
|
195
|
+
# see also https://www.wikidata.org/wiki/EntitySchema:E49
|
|
196
|
+
prefixes="""PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
|
|
197
|
+
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
|
|
199
198
|
PREFIX schema: <http://schema.org/>
|
|
200
199
|
PREFIX wd: <http://www.wikidata.org/entity/>
|
|
201
200
|
PREFIX wdt: <http://www.wikidata.org/prop/direct/>
|
|
201
|
+
PREFIX wikibase: <http://wikiba.se/ontology#>
|
|
202
202
|
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>"""
|
|
203
203
|
return prefixes
|
|
204
|
-
|
|
204
|
+
|
|
205
205
|
@classmethod
|
|
206
206
|
def getLabelAndDescription(cls,sparql:SPARQL, itemId:str,lang:str="en"):
|
|
207
207
|
'''
|
|
@@ -223,9 +223,9 @@ WHERE
|
|
|
223
223
|
wd:{itemId}
|
|
224
224
|
}}
|
|
225
225
|
?item rdfs:label ?itemLabel.
|
|
226
|
-
FILTER (
|
|
226
|
+
FILTER (LANG(?itemLabel) = "{lang}").
|
|
227
227
|
?item schema:description ?itemDescription.
|
|
228
|
-
FILTER(
|
|
228
|
+
FILTER(LANG(?itemDescription) = "{lang}")
|
|
229
229
|
}}"""
|
|
230
230
|
return sparql.getValues(query, ["itemLabel","itemDescription"])
|
|
231
231
|
|
|
@@ -247,17 +247,21 @@ WHERE
|
|
|
247
247
|
# e.g. we'll find human=Q5 as the oldest type for the label "human" first
|
|
248
248
|
# and then the newer ones such as "race in Warcraft"
|
|
249
249
|
{cls.getPrefixes()}
|
|
250
|
-
SELECT
|
|
250
|
+
SELECT
|
|
251
|
+
#?itemId
|
|
252
|
+
?item
|
|
253
|
+
?itemLabel
|
|
254
|
+
?itemDescription
|
|
251
255
|
WHERE {{
|
|
252
256
|
VALUES ?itemLabel {{
|
|
253
257
|
{valuesClause}
|
|
254
258
|
}}
|
|
255
|
-
BIND (xsd:integer(SUBSTR(STR(?item),33)) AS ?itemId)
|
|
259
|
+
#BIND (xsd:integer(SUBSTR(STR(?item),33)) AS ?itemId)
|
|
256
260
|
?item rdfs:label ?itemLabel.
|
|
257
|
-
?item schema:description ?itemDescription
|
|
261
|
+
?item schema:description ?itemDescription.
|
|
258
262
|
FILTER(LANG(?itemDescription)="{lang}")
|
|
259
|
-
}}
|
|
260
|
-
|
|
263
|
+
}}
|
|
264
|
+
#ORDER BY ?itemId"""
|
|
261
265
|
qLod=sparql.queryAsListOfDicts(query)
|
|
262
266
|
items=[]
|
|
263
267
|
for record in qLod:
|
|
@@ -269,7 +273,8 @@ WHERE {{
|
|
|
269
273
|
item.varname=Variable.validVarName(item.qlabel)
|
|
270
274
|
item.description=record["itemDescription"]
|
|
271
275
|
items.append(item)
|
|
272
|
-
|
|
276
|
+
sortedItems=sorted(items,key=lambda item: item.qnumber)
|
|
277
|
+
return sortedItems
|
|
273
278
|
|
|
274
279
|
class TrulyTabular(object):
|
|
275
280
|
'''
|
|
@@ -277,9 +282,8 @@ class TrulyTabular(object):
|
|
|
277
282
|
|
|
278
283
|
checks "how tabular" a query based on a list of properties of an itemclass is
|
|
279
284
|
'''
|
|
280
|
-
endpoint="https://query.wikidata.org/sparql"
|
|
281
285
|
|
|
282
|
-
def __init__(self, itemQid, propertyLabels:list=[],propertyIds:list=[],where:str=None,
|
|
286
|
+
def __init__(self, itemQid, propertyLabels:list=[],propertyIds:list=[],where:str=None,endpointConf=None,lang="en",debug=False):
|
|
283
287
|
'''
|
|
284
288
|
Constructor
|
|
285
289
|
|
|
@@ -292,10 +296,10 @@ class TrulyTabular(object):
|
|
|
292
296
|
'''
|
|
293
297
|
self.itemQid=itemQid
|
|
294
298
|
self.debug=debug
|
|
295
|
-
if
|
|
296
|
-
|
|
297
|
-
self.
|
|
298
|
-
self.sparql=SPARQL(endpoint,method=method)
|
|
299
|
+
if endpointConf is None:
|
|
300
|
+
endpointConf=Endpoint.getDefault()
|
|
301
|
+
self.endpointConf=endpointConf
|
|
302
|
+
self.sparql=SPARQL(endpointConf.endpoint,method=self.endpointConf.method)
|
|
299
303
|
self.sparql.debug=self.debug
|
|
300
304
|
self.where=f"\n {where}" if where is not None else ""
|
|
301
305
|
self.lang=lang
|
|
@@ -329,6 +333,8 @@ WHERE
|
|
|
329
333
|
}}"""
|
|
330
334
|
try:
|
|
331
335
|
count=self.sparql.getValue(query, "count")
|
|
336
|
+
# workaround https://github.com/ad-freiburg/qlever/issues/717
|
|
337
|
+
count=int(count)
|
|
332
338
|
except Exception as ex:
|
|
333
339
|
self.error=ex
|
|
334
340
|
count=None
|
|
@@ -475,32 +481,41 @@ WHERE {{
|
|
|
475
481
|
whereClause(str): an extra WhereClause to use
|
|
476
482
|
'''
|
|
477
483
|
if whereClause is None:
|
|
478
|
-
whereClause=f"?item wdt:P31 wd:{self.itemQid}
|
|
479
|
-
|
|
480
|
-
|
|
484
|
+
whereClause=f"?item wdt:P31 wd:{self.itemQid}";
|
|
485
|
+
if self.endpointConf.database!="qlever":
|
|
486
|
+
whereClause+=";?p ?id"
|
|
487
|
+
whereClause+="."
|
|
481
488
|
itemText=self.getItemText()
|
|
482
|
-
if self.endpoint=="https://query.wikidata.org/sparql":
|
|
483
|
-
optimizerHint=' hint:Query hint:optimizer "None".\n'
|
|
484
|
-
else:
|
|
485
|
-
optimizerHint=''
|
|
486
489
|
sparqlQuery=f"""# get the most frequently used properties for
|
|
487
490
|
# {itemText}
|
|
488
|
-
|
|
489
|
-
PREFIX schema: <http://schema.org/>
|
|
490
|
-
PREFIX wd: <http://www.wikidata.org/entity/>
|
|
491
|
-
PREFIX wdt: <http://www.wikidata.org/prop/direct/>
|
|
492
|
-
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
|
|
491
|
+
{WikidataItem.getPrefixes()}
|
|
493
492
|
SELECT ?prop ?propLabel ?count WHERE {{
|
|
494
|
-
{{
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
493
|
+
{{"""
|
|
494
|
+
if self.endpointConf.database=="qlever":
|
|
495
|
+
sparqlQuery+=f"""
|
|
496
|
+
SELECT ?p (COUNT(DISTINCT ?item) AS ?count) WHERE {{"""
|
|
497
|
+
else:
|
|
498
|
+
sparqlQuery+=f"""
|
|
499
|
+
SELECT ?prop (COUNT(DISTINCT ?item) AS ?count) WHERE {{"""
|
|
500
|
+
if self.endpointConf.database=="blazegraph":
|
|
501
|
+
sparqlQuery+=f"""
|
|
502
|
+
hint:Query hint:optimizer "None"."""
|
|
503
|
+
sparqlQuery+=f"""
|
|
504
|
+
{whereClause}"""
|
|
505
|
+
if self.endpointConf.database=="qlever":
|
|
506
|
+
sparqlQuery+=f"""
|
|
507
|
+
?item ql:has-predicate ?p
|
|
508
|
+
}} GROUP BY ?p
|
|
509
|
+
}}
|
|
510
|
+
?prop wikibase:directClaim ?p."""
|
|
511
|
+
else:
|
|
512
|
+
sparqlQuery+=f"""
|
|
499
513
|
?prop wikibase:directClaim ?p.
|
|
500
514
|
}}
|
|
501
515
|
GROUP BY ?prop ?propLabel
|
|
502
|
-
}}
|
|
503
|
-
|
|
516
|
+
}}"""
|
|
517
|
+
sparqlQuery+=f"""
|
|
518
|
+
?prop rdfs:label ?propLabel.
|
|
504
519
|
FILTER(LANG(?propLabel) = "{self.lang}")
|
|
505
520
|
}}
|
|
506
521
|
ORDER BY DESC (?count)
|
|
@@ -525,16 +540,17 @@ ORDER BY DESC (?count)
|
|
|
525
540
|
sparql=f"""
|
|
526
541
|
# Count all {self.asText(long=True)} items
|
|
527
542
|
# with the given {propertyLabel}({propertyId}) https://www.wikidata.org/wiki/Property:{propertyId}
|
|
543
|
+
{WikidataItem.getPrefixes()}
|
|
528
544
|
SELECT ?item ?itemLabel (COUNT (?value) AS ?count)
|
|
529
545
|
WHERE
|
|
530
546
|
{{
|
|
531
547
|
# instance of {self.item.qlabel}
|
|
532
548
|
?item wdt:P31 wd:{self.itemQid}.{self.where}
|
|
533
549
|
?item rdfs:label ?itemLabel.
|
|
534
|
-
|
|
550
|
+
FILTER (LANG(?itemLabel) = "{self.lang}").
|
|
535
551
|
# {propertyLabel}
|
|
536
552
|
?item {wdProperty.getPredicate()} ?value.
|
|
537
|
-
}} GROUP
|
|
553
|
+
}} GROUP BY ?item ?itemLabel
|
|
538
554
|
"""
|
|
539
555
|
if asFrequency:
|
|
540
556
|
freqDesc="frequencies"
|
|
@@ -9,7 +9,7 @@ class Version(object):
|
|
|
9
9
|
Version handling for pyLoDStorage
|
|
10
10
|
'''
|
|
11
11
|
name="pylodstorage"
|
|
12
|
-
version='0.3.
|
|
12
|
+
version='0.3.6'
|
|
13
13
|
date = '2020-09-10'
|
|
14
|
-
updated = '2022-07-
|
|
14
|
+
updated = '2022-07-31'
|
|
15
15
|
description='python List of Dict (Table) Storage library'
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
lang: sparql
|
|
5
5
|
endpoint: https://query.wikidata.org/sparql
|
|
6
6
|
website: https://query.wikidata.org/
|
|
7
|
+
database: blazegraph
|
|
7
8
|
method: POST
|
|
8
9
|
prefixes: |
|
|
9
10
|
PREFIX bd: <http://www.bigdata.com/rdf#>
|
|
@@ -37,10 +38,10 @@
|
|
|
37
38
|
PREFIX wdv: <http://www.wikidata.org/value/>
|
|
38
39
|
PREFIX wikibase: <http://wikiba.se/ontology#>
|
|
39
40
|
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
|
|
40
|
-
|
|
41
41
|
'qlever-wikidata':
|
|
42
42
|
lang: sparql
|
|
43
43
|
method: GET
|
|
44
|
+
database: qlever
|
|
44
45
|
endpoint: https://qlever.cs.uni-freiburg.de/api/wikidata
|
|
45
46
|
website: https://qlever.cs.uni-freiburg.de/wikidata
|
|
46
47
|
prefixes: |
|
|
@@ -75,10 +76,10 @@
|
|
|
75
76
|
PREFIX wdv: <http://www.wikidata.org/value/>
|
|
76
77
|
PREFIX wikibase: <http://wikiba.se/ontology#>
|
|
77
78
|
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
|
|
78
|
-
|
|
79
79
|
'qlever-wikidata-proxy':
|
|
80
80
|
lang: sparql
|
|
81
81
|
method: GET
|
|
82
|
+
database: qlever
|
|
82
83
|
endpoint: https://qlever.cs.uni-freiburg.de/api/wikidata-proxy
|
|
83
84
|
website: https://qlever.cs.uni-freiburg.de/wikidata
|
|
84
85
|
prefixes: |
|
|
@@ -117,6 +118,7 @@
|
|
|
117
118
|
lang: sparql
|
|
118
119
|
endpoint: https://wikidata.demo.openlinksw.com/sparql
|
|
119
120
|
website: https://wikidata.demo.openlinksw.com/sparql
|
|
121
|
+
database: virtuoso
|
|
120
122
|
prefixes: |
|
|
121
123
|
PREFIX bd: <http://www.bigdata.com/rdf#>
|
|
122
124
|
PREFIX cc: <http://creativecommons.org/ns#>
|
|
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
|