tulit 0.2.0__tar.gz → 0.2.2__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.
- {tulit-0.2.0 → tulit-0.2.2}/PKG-INFO +1 -2
- {tulit-0.2.0 → tulit-0.2.2}/pyproject.toml +2 -2
- {tulit-0.2.0 → tulit-0.2.2}/tulit/parsers/xml/formex.py +67 -68
- {tulit-0.2.0 → tulit-0.2.2}/LICENSE +0 -0
- {tulit-0.2.0 → tulit-0.2.2}/README.md +0 -0
- {tulit-0.2.0 → tulit-0.2.2}/tulit/__init__.py +0 -0
- {tulit-0.2.0 → tulit-0.2.2}/tulit/client/__init__.py +0 -0
- {tulit-0.2.0 → tulit-0.2.2}/tulit/client/boe.py +0 -0
- {tulit-0.2.0 → tulit-0.2.2}/tulit/client/cellar.py +0 -0
- {tulit-0.2.0 → tulit-0.2.2}/tulit/client/client.py +0 -0
- {tulit-0.2.0 → tulit-0.2.2}/tulit/client/legifrance.py +0 -0
- {tulit-0.2.0 → tulit-0.2.2}/tulit/client/legilux.py +0 -0
- {tulit-0.2.0 → tulit-0.2.2}/tulit/client/normattiva.py +0 -0
- {tulit-0.2.0 → tulit-0.2.2}/tulit/client/veneto.py +0 -0
- {tulit-0.2.0 → tulit-0.2.2}/tulit/main.py +0 -0
- {tulit-0.2.0 → tulit-0.2.2}/tulit/parsers/__init__.py +0 -0
- {tulit-0.2.0 → tulit-0.2.2}/tulit/parsers/html/cellar.py +0 -0
- {tulit-0.2.0 → tulit-0.2.2}/tulit/parsers/html/veneto.py +0 -0
- {tulit-0.2.0 → tulit-0.2.2}/tulit/parsers/html/xhtml.py +0 -0
- {tulit-0.2.0 → tulit-0.2.2}/tulit/parsers/parser.py +0 -0
- {tulit-0.2.0 → tulit-0.2.2}/tulit/parsers/xml/akomantoso.py +0 -0
- {tulit-0.2.0 → tulit-0.2.2}/tulit/parsers/xml/assets/akomantoso30.xsd +0 -0
- {tulit-0.2.0 → tulit-0.2.2}/tulit/parsers/xml/assets/eli.owl +0 -0
- {tulit-0.2.0 → tulit-0.2.2}/tulit/parsers/xml/assets/formex4.xsd +0 -0
- {tulit-0.2.0 → tulit-0.2.2}/tulit/parsers/xml/assets/import/xml.xsd +0 -0
- {tulit-0.2.0 → tulit-0.2.2}/tulit/parsers/xml/assets/subdivisions.xml +0 -0
- {tulit-0.2.0 → tulit-0.2.2}/tulit/parsers/xml/assets/xml.xsd +0 -0
- {tulit-0.2.0 → tulit-0.2.2}/tulit/parsers/xml/xml.py +0 -0
- {tulit-0.2.0 → tulit-0.2.2}/tulit/rdf.py +0 -0
- {tulit-0.2.0 → tulit-0.2.2}/tulit/sparql.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: tulit
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.2
|
|
4
4
|
Summary: TULIT - The Universal Legal Informatics Toolkit, is set of legal informatics utilities collected in a Python package that focuses on the retrieval of legal data and metadata from official sources in the EU, and their transformation in pythonic data structures
|
|
5
5
|
License: EUPL 1.2
|
|
6
6
|
Author: AlessioNar
|
|
@@ -10,7 +10,6 @@ Classifier: License :: Other/Proprietary License
|
|
|
10
10
|
Classifier: Operating System :: OS Independent
|
|
11
11
|
Classifier: Programming Language :: Python :: 3
|
|
12
12
|
Classifier: Programming Language :: Python :: 3.11
|
|
13
|
-
Classifier: Programming Language :: Python :: 3.12
|
|
14
13
|
Requires-Dist: beautifulsoup4 (>=4.9.3,<5.0.0)
|
|
15
14
|
Requires-Dist: chardet (>=5.2.0,<6.0.0)
|
|
16
15
|
Requires-Dist: coverage (>=7.6.9,<8.0.0)
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "tulit"
|
|
3
|
-
version = "0.2.
|
|
3
|
+
version = "0.2.2"
|
|
4
4
|
description = "TULIT - The Universal Legal Informatics Toolkit, is set of legal informatics utilities collected in a Python package that focuses on the retrieval of legal data and metadata from official sources in the EU, and their transformation in pythonic data structures"
|
|
5
5
|
|
|
6
6
|
[tool.poetry]
|
|
7
7
|
name = "tulit"
|
|
8
|
-
version = "0.2.
|
|
8
|
+
version = "0.2.2"
|
|
9
9
|
description = "TULIT - The Universal Legal Informatics Toolkit, is set of legal informatics utilities collected in a Python package that focuses on the retrieval of legal data and metadata from official sources in the EU, and their transformation in pythonic data structures"
|
|
10
10
|
authors = ["AlessioNar <alessio.nardin@gmail.com>"]
|
|
11
11
|
license = "EUPL 1.2"
|
|
@@ -163,8 +163,8 @@ class Formex4Parser(XMLParser):
|
|
|
163
163
|
extract_eId=extract_eId,
|
|
164
164
|
get_headings=get_headings
|
|
165
165
|
)
|
|
166
|
+
|
|
166
167
|
|
|
167
|
-
|
|
168
168
|
def get_articles(self):
|
|
169
169
|
"""
|
|
170
170
|
Extracts articles from the ENACTING.TERMS section. Articles are assumed to be contained within the
|
|
@@ -182,35 +182,56 @@ class Formex4Parser(XMLParser):
|
|
|
182
182
|
|
|
183
183
|
self.articles = []
|
|
184
184
|
if self.body is not None:
|
|
185
|
-
|
|
185
|
+
# The usage of xpath() method is to exclude nested ARTICLE elements
|
|
186
|
+
articles = self.body.xpath(".//ARTICLE[@IDENTIFIER][not(ancestor::ARTICLE)]")
|
|
187
|
+
for article in articles:
|
|
186
188
|
article_eId = article.get("IDENTIFIER")
|
|
187
|
-
article_eId = article_eId.lstrip('
|
|
189
|
+
article_eId = article_eId.lstrip('3')
|
|
188
190
|
article_eId = f'art_{article_eId}'
|
|
191
|
+
|
|
189
192
|
children = []
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
#
|
|
193
|
+
|
|
194
|
+
# Check whether within the ARTICLE element there are
|
|
195
|
+
# QUOT.S elements, that mark the presence of amendments
|
|
193
196
|
if article.findall('.//QUOT.S'):
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
197
|
+
for alinea in article.xpath('.//ALINEA[not(ancestor::QUOT.S)]'):
|
|
198
|
+
children.append({
|
|
199
|
+
"eId": 0,
|
|
200
|
+
"text": self.clean_text(alinea),
|
|
201
|
+
"amendment": True
|
|
202
|
+
})
|
|
203
|
+
|
|
204
|
+
#article.xpath('.//ALINEA')
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
# Treat amendments. First extract the text contained within the
|
|
208
|
+
# a P element that is outside of a LIST element
|
|
209
|
+
#for p in article.xpath('.//P[not(ancestor::LIST)]'):
|
|
210
|
+
# self._extract_elements(p, '.', children)
|
|
211
|
+
|
|
212
|
+
# Treat all the rest of the content of the ARTICLE element
|
|
213
|
+
# as a unique child
|
|
214
|
+
#children
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
# Extract text and metadata from PARAG elements that are not descendants of QUOT.S elements (exclude amendments)
|
|
218
|
+
elif article.xpath('.//PARAG'):
|
|
219
|
+
self._extract_elements(article, './/PARAG', children)
|
|
204
220
|
elif article.findall('.//ALINEA'):
|
|
205
221
|
# If no PARAG elements, check for ALINEA elements
|
|
206
|
-
alineas = article.
|
|
222
|
+
alineas = article.xpath('.//ALINEA')
|
|
207
223
|
for alinea in alineas:
|
|
208
|
-
|
|
209
|
-
p_elements
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
224
|
+
p_elements = alinea.xpath('.//P')
|
|
225
|
+
if p_elements:
|
|
226
|
+
for p in p_elements:
|
|
227
|
+
self._extract_elements(p, '.', children)
|
|
228
|
+
for item in alinea.findall('.//LIST//ITEM'):
|
|
229
|
+
self._extract_elements(item, '.', children)
|
|
230
|
+
else:
|
|
231
|
+
self._extract_elements(alinea, '.', children)
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
|
|
214
235
|
|
|
215
236
|
self.articles.append({
|
|
216
237
|
"eId": article_eId,
|
|
@@ -223,8 +244,22 @@ class Formex4Parser(XMLParser):
|
|
|
223
244
|
else:
|
|
224
245
|
print('No enacting terms XML tag has been found')
|
|
225
246
|
return []
|
|
226
|
-
|
|
227
|
-
def
|
|
247
|
+
|
|
248
|
+
def clean_text(self, element):
|
|
249
|
+
for sub_element in element.iter():
|
|
250
|
+
if sub_element.tag == 'QUOT.START':
|
|
251
|
+
sub_element.text = "‘"
|
|
252
|
+
elif sub_element.tag == 'QUOT.END':
|
|
253
|
+
sub_element.text = "’"
|
|
254
|
+
text = "".join(element.itertext()).strip()
|
|
255
|
+
text = re.sub(r'^\(\d+\)', '', text).strip()
|
|
256
|
+
text = text.replace('\n', '').replace('\t', '').replace('\r', '') # remove newline and tab characters
|
|
257
|
+
text = text.replace('\u00A0', ' ') # replace non-breaking spaces with regular spaces
|
|
258
|
+
text = re.sub(' +', ' ', text) # replace multiple spaces with a single space
|
|
259
|
+
text = re.sub(r'\s+([.,!?;:’])', r'\1', text) # replace spaces before punctuation with nothing
|
|
260
|
+
return text
|
|
261
|
+
|
|
262
|
+
def _extract_elements(self, parent, xpath, children):
|
|
228
263
|
"""
|
|
229
264
|
Helper method to extract text and metadata from elements.
|
|
230
265
|
|
|
@@ -236,55 +271,19 @@ class Formex4Parser(XMLParser):
|
|
|
236
271
|
The XPath expression to locate the elements.
|
|
237
272
|
children : list
|
|
238
273
|
The list to append the extracted elements to.
|
|
239
|
-
amendments : list
|
|
240
|
-
List of amendments extracted from the article.
|
|
241
|
-
start_index : int, optional
|
|
242
|
-
The starting index for the elements (default is 0).
|
|
243
274
|
"""
|
|
244
275
|
elements = parent.findall(xpath)
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
sub_element.text = "‘"
|
|
250
|
-
elif sub_element.tag == 'QUOT.END':
|
|
251
|
-
sub_element.text = "’"
|
|
252
|
-
|
|
253
|
-
text = "".join(element.itertext()).strip()
|
|
254
|
-
text = re.sub(r'^\(\d+\)', '', text).strip()
|
|
255
|
-
text = text.replace('\n', '').replace('\t', '').replace('\r', '') # remove newline and tab characters
|
|
256
|
-
text = text.replace('\u00A0', ' ') # replace non-breaking spaces with regular spaces
|
|
257
|
-
text = re.sub(' +', ' ', text) # replace multiple spaces with a single space
|
|
258
|
-
text = re.sub(r'\s+([.,!?;:’])', r'\1', text) # replace spaces before punctuation with nothing
|
|
276
|
+
for index, element in enumerate(elements):
|
|
277
|
+
|
|
278
|
+
text = self.clean_text(element)
|
|
279
|
+
|
|
259
280
|
if text is not None and text != '' and text != ';':
|
|
260
281
|
child = {
|
|
261
282
|
"eId": element.get("IDENTIFIER") or element.get("ID") or element.get("NO.P") or index,
|
|
262
|
-
"text": text,
|
|
263
|
-
"
|
|
264
|
-
"amendment": amendments[amendment_index] if amendment_index < len(amendments) else None
|
|
283
|
+
"text": text,
|
|
284
|
+
"amendment": False
|
|
265
285
|
}
|
|
266
|
-
children.append(child)
|
|
267
|
-
amendment_index += 1
|
|
268
|
-
|
|
269
|
-
def _handle_amendments(self, article):
|
|
270
|
-
"""
|
|
271
|
-
Handles amendments made in the ACT using the <QUOT.S> tag.
|
|
272
|
-
|
|
273
|
-
Parameters
|
|
274
|
-
----------
|
|
275
|
-
article : lxml.etree._Element
|
|
276
|
-
The article element to process.
|
|
277
|
-
"""
|
|
278
|
-
amendments = []
|
|
279
|
-
for quot_s in article.findall('.//QUOT.S'):
|
|
280
|
-
amendment_text = " ".join(quot_s.itertext()).strip()
|
|
281
|
-
# Process the amendment text as needed
|
|
282
|
-
# For example, you could store it in a list or apply it to the article text
|
|
283
|
-
amendments.append(amendment_text)
|
|
284
|
-
# Remove the QUOT.S tags from the article using the self.remove_node method
|
|
285
|
-
article = self.remove_node(article, './/QUOT.S')
|
|
286
|
-
return article, amendments
|
|
287
|
-
|
|
286
|
+
children.append(child)
|
|
288
287
|
|
|
289
288
|
def get_conclusions(self):
|
|
290
289
|
"""
|
|
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
|