diff --git a/.vscode/launch.json b/.vscode/launch.json
index d6dbcf45c..77e9b0cc4 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -6,7 +6,7 @@
"configurations": [
{
"name": "django: runserver",
- "type": "python",
+ "type": "debugpy",
"request": "launch",
"program": "${workspaceFolder}/backend/manage.py",
"args": ["runserver"],
@@ -15,7 +15,7 @@
},
{
"name": "django: shell",
- "type": "python",
+ "type": "debugpy",
"request": "launch",
"program": "${workspaceFolder}/backend/manage.py",
"args": ["shell"],
@@ -24,16 +24,17 @@
},
{
"name": "django: index",
- "type": "python",
+ "type": "debugpy",
"request": "launch",
"program": "${workspaceFolder}/backend/manage.py",
- "args": ["index", "${input:corpusName}"],
+ "args": ["index", "${input:corpusName}", "--delete"],
"django": true,
- "justMyCode": true
+ "justMyCode": true,
+ "console": "internalConsole"
},
{
"name": "django: loadcorpora",
- "type": "python",
+ "type": "debugpy",
"request": "launch",
"program": "${workspaceFolder}/backend/manage.py",
"args": ["loadcorpora"],
diff --git a/backend/corpora/parliament/conftest.py b/backend/corpora/parliament/conftest.py
index e0b1c7817..c71476e91 100644
--- a/backend/corpora/parliament/conftest.py
+++ b/backend/corpora/parliament/conftest.py
@@ -34,7 +34,7 @@ def parliament_corpora_settings(settings):
settings.PP_CANADA_DATA = os.path.join(here, 'tests', 'data', 'canada')
settings.PP_DENMARK_DATA = os.path.join(here, 'tests', 'data', 'denmark')
settings.PP_DENMARK_NEW_DATA = os.path.join(here, 'tests', 'data', 'denmark-new')
- settings.PP_EUPARL_DATA = os.path.join(here, 'tests', 'data', 'euparl', 'rdf')
+ settings.PP_EUPARL_DATA = os.path.join(here, 'tests', 'data', 'euparl', 'rds')
settings.PP_FINLAND_DATA = os.path.join(here, 'tests', 'data', 'finland')
settings.PP_FINLAND_OLD_DATA = os.path.join(here, 'tests', 'data', 'finland-old')
settings.PP_FR_DATA = os.path.join(here, 'tests', 'data', 'france')
@@ -685,48 +685,63 @@ def parliament_corpora_settings(settings):
"name": "parliament-europe",
"start": datetime(1999, 7, 20),
"docs": [
+ # EUPDCorp data
{
- "id": "1999-07-21-Speech-3-063",
- "date": "1999-07-21",
- "debate_id": "1999-07-21_AgendaItem_5",
- "debate_title": "Statement by Mr Prodi, President-elect of the Commission",
- "party": "Group for the Technical Coordination and Defence of Indipendent Groups and Members (TGI)",
- "sequence": 15,
- "speaker": "Francesco Enrico Speroni",
- "speaker_country": "Italy",
- "speech": """Mr President, as a Member of the Italian national Parliament for the\n(The Northern League for the Independence of Padania), I did not vote for Professor Prodi in Rome as I considered he would be completely useless as head of government. I was then proved right as he lost the vote of confidence of the Italian Parliament. Reckoning also that a Roman idiot would still be that stupid wherever he was, which, incidently, is reflected in the symbol on the list which bears his name for the election of this Parliament, I cannot for consistency\"s sake express my faith in the President of the Commission. As a native of the Po valley who is Italian only by passport, I am fortunately immune from the national Christian Democrat type of opportunism which brings Berlusconi together with Mastella and De Mita and sees in Prodi not the impartial President of the Commissioners uninfluenced by the States, but the lavish dispenser of favours to a wide and varied assortment of Southern Italian profiteers. Although I hold some of the Commissioners in high esteem, I recall the old mafioso Neapolitan saying: ‘A fish rots from the head downwards’ and I therefore have to express my negative opinion of the Prodi Presidency.""",
- "source_language": "Italian",
- "url": "http://purl.org/linkedpolitics/eu/plenary/1999-07-21-Speech-3-063",
+ 'date': '1999-07-20',
+ 'debate_title': 'Genoptagelse af sessionen',
+ 'debate_id': 'CRE-5-1999-07-20-FNL',
+ 'speaker': 'Giorgio Napolitano',
+ 'party': 'IND',
+ 'party_full': 'Independent',
+ 'party_national': 'Democratici di Sinistra',
+ 'speaker_country': 'Italy',
+ 'speaker_gender': 'Male',
+ 'speaker_birth_year': 1925,
+ 'speaker_id': '1103',
+ 'speech_original': 'Dichiaro ripresa la sessione interrotta il 7 maggio 1999 e '
+ "dichiaro aperta la seduta prevista all'articolo 10, paragrafo 3, "
+ "dell'Atto recante elezione dei rappresentanti al Parlamento "
+ "europeo a suffragio universale diretto nonché all'articolo 10, "
+ "paragrafo 3, del Regolamento del Parlamento. L'onorevole Crowley "
+ 'ha chiesto, pregiudizialmente, la parola.',
+ 'speech': 'I declare resumed the session adjourned on 7 May 1999 and open '
+ 'the sitting provided for in Article 10 (3) of the Act electing '
+ 'the representatives of the European Parliament by direct '
+ "universal suffrage and in Article 10 (3) of Parliament's Rules "
+ 'of Procedure. Mr Crowley has asked for the floor on a point of '
+ 'order.',
+ 'original_language': 'Italian',
+ 'sequence': 1,
+ 'source_archive': 'EUPDCorp',
},
{
- "id": "2017-07-06-Speech-4-146-000",
- "date": "2017-07-06",
- "debate_id": "2017-07-06_AgendaItem_13",
- "debate_title": "Composition of committees and delegations",
- "party": None,
- "sequence": 2,
- "source_language": "English",
- "speaker": "Ashley Fox",
- "speaker_country": "United Kingdom",
- "speech": """Mr President, yesterday afternoon we had a lively debate, under Rule 153, on the subject of a single seat for this Parliament. Unfortunately, under that rule, it was not possible to have a resolution, but it was the clear will of this House that we bring forward a report to propose a treaty change. So, as Mr Weber and Mr Pittella are in their seats, could they please take note of the view of this House and, when the matter comes to the Conference of Presidents, could they please authorise that report?""",
- "url": "http://www.europarl.europa.eu/plenary/EN/vod.html?mode=unit&vodLanguage=EN&startTime=20170706-12:02:01-324",
+ 'speaker': 'Brian Crowley',
+ 'speaker_country': 'Ireland',
+ 'sequence': 2,
},
+ {}, {}, {},
+ # API data
{
"date": "2024-11-13",
"debate_id": "MTG-PL-2024-11-13-PVCRE-ITM-17",
- "debate_title": "17. Fight against money laundering and terrorist financing: listing Russia as a high-risk third country in the EU (debate)",
+ "debate_title": "Fight against money laundering and terrorist financing: listing Russia as a high-risk third country in the EU (debate)",
"id": "MTG-PL-2024-11-13-OTH-2017005042457",
- "party": "European Conservatives and Reformists Group",
+ "party": 'ECR',
+ 'party_full': 'European Conservatives and Reformists',
+ 'party_national': None,
"party_id": "7037",
- "source_language": "English",
- "sequence": 1,
+ 'original_language': "English",
+ "sequence": 321,
"speaker": "Roberts Zīle",
"speaker_country": "Latvia",
+ 'speaker_gender': 'Male',
+ 'speaker_birth_year': 1958,
"speaker_id": "28615",
- "speech": "Thank you, Commissioner McGuinness, and I would also like to thank you for your work on the AML package and many other issues, also for today's issues. Thank you very much.",
- },
+ "speech": "Thank you, Commissioner McGuinness, and I would also like to thank you for your work on the AML package and many other issues, also for today's issues. Thank you very much.\n\nThe concludes the item.",
+ 'source_archive': 'European Parliament Open Data API',
+ }
],
- "n_documents": 3,
+ "n_documents": 6,
},
{
'name': 'parliament-sweden-swerik',
diff --git a/backend/corpora/parliament/description/euparl.md b/backend/corpora/parliament/description/euparl.md
index 4e592ed94..1a5fc6294 100644
--- a/backend/corpora/parliament/description/euparl.md
+++ b/backend/corpora/parliament/description/euparl.md
@@ -1,4 +1,28 @@
-The debates from the European Parliament, in English (translation), as provided by the [Talk of Europe](https://ssh.datastations.nl/dataset.xhtml?persistentId=doi:10.17026/dans-x62-ew3m&version=1.0) dataset. The dataset covers debates from July 1999 to July 2017.
+Debates from the European Parliament (EP). As the parliament of the European Union, the EP has representatives from all member states. Members are organised into political groups, which are broad alliances of national parties.
+
+## Source data
+
+The European Parliament corpus in People & Parliament is based two datasets: [EUPDCorp](https://doi.org/10.5281/zenodo.15056399) (CC-BY 4.0 International licence) is used for debates from 1999 to February 2024 (terms 5-9).
+
+Debates from February 2024 to January 2026 are sourced from the [European Parliament Open Data API](https://data.europarl.europa.eu/en/developer-corner/opendata-api) (CC-BY 4.0 International licence).
+
+**References:**
+
+- Mochtak, Michal (2025): Corpus of the EU Parliament Debates (EUPDCorp), 1999-2024, Zenodo, v1.0, https://doi.org/10.5281/zenodo.15056399
+
+## Notes
+
+### Language and translations
+
+Speakers in the European Parliament use a large number of different languages. The documents in the this corpus include both the original speech, and an English translation.
+
+Translations are taken from the source datasets (see above). Translations in the EUPDCorp dataset are machine-translated.
+
+### Parties
+
+The _party_ field specifies the political group of the speaker in the European Parliament. In addition, the _national party_ field specifies the speaker's party at the national level.
+
+Because the data is extracted from multiple datasets, the corpus may use a different name for the same political group before and after 2024.
### Image attribution
diff --git a/backend/corpora/parliament/euparl.py b/backend/corpora/parliament/euparl.py
index 619439152..b70e54dda 100644
--- a/backend/corpora/parliament/euparl.py
+++ b/backend/corpora/parliament/euparl.py
@@ -1,133 +1,35 @@
from datetime import datetime, timedelta
from functools import cache
-from itertools import chain
import logging
import os
-from typing import Optional, Tuple, Union
+from typing import Optional, Dict, List, Tuple, Union
+from urllib import parse
+import math
+import numbers
from bs4 import BeautifulSoup
from django.conf import settings
from langcodes import standardize_tag, Language
import requests
-from rdflib import Graph, Namespace, URIRef
-from rdflib.namespace import DCTERMS, FOAF, RDFS, RDF as RDFNS
-from ianalyzer_readers.extract import Backup, Combined, JSON, Metadata, RDF, Pass
-
-from addcorpus.es_mappings import keyword_mapping
-from addcorpus.python_corpora.corpus import (
- FieldDefinition,
- JSONCorpusDefinition,
- RDFCorpusDefinition,
-)
+from ianalyzer_readers.extract import Combined, JSON, Metadata, Pass, CSV, Constant
+from ianalyzer_readers.readers.core import Field
+from ianalyzer_readers.readers.json import JSONReader
+
+from addcorpus.es_mappings import keyword_mapping, main_content_mapping
+from addcorpus.python_corpora.corpus import FieldDefinition
from addcorpus.python_corpora.filters import MultipleChoiceFilter
from corpora.parliament.parliament import Parliament
import corpora.parliament.utils.field_defaults as field_defaults
from corpora.utils.constants import document_context
+from corpora.parliament.utils.rds_reader import RDSReader
logger = logging.getLogger('indexing')
-EVENTS_METADATA = 'Events_and_structure.ttl'
-MP_METADATA = 'MembersOfParliament_background.ttl'
-SPEECHES = 'English.ttl'
-
-# Namespaces of Linked Politics (NB: the purl links resolve to dead sites)
-LP_EU = Namespace('http://purl.org/linkedpolitics/eu/plenary/')
-LPV_EU = Namespace('http://purl.org/linkedpolitics/vocabulary/eu/plenary/')
-LP = Namespace('http://purl.org/linkedpolitics/')
-LPV = Namespace('http://purl.org/linkedpolitics/vocabulary/')
-
-def add_speaker_metadata(filename: str) -> dict:
- """Parse all relevant metadata out of MembersOfParliament ttl to dict"""
- speaker_dict = {}
- speaker_graph = Graph()
- speaker_graph.parse(filename)
- speaker_subjects = speaker_graph.subjects(object=LPV.MemberOfParliament)
- for speaker in speaker_subjects:
- try:
- name = speaker_graph.value(speaker, FOAF.name).value
- except AttributeError:
- # We cannot find the name of the speaker subject
- continue
- country_node = speaker_graph.value(speaker, LPV.countryOfRepresentation)
- country_name = speaker_graph.value(country_node, RDFS.label).value
- party_list = []
- speaker_functions = speaker_graph.objects(speaker, LPV.politicalFunction)
- for function in speaker_functions:
- function_type = speaker_graph.value(function, LPV.institution)
- if speaker_graph.value(function_type, RDFNS.type) == LPV.EUParty:
- party_labels = list(speaker_graph.objects(function_type, RDFS.label))
- party_acronym = min(party_labels, key=len)
- party_name = max(party_labels, key=len)
- date_start = speaker_graph.value(function, LPV.beginning)
- date_end = speaker_graph.value(function, LPV.end)
- party_list.append({
- 'party_acronym': party_acronym,
- 'party_name': party_name,
- 'date_start': date_start.value,
- 'date_end': date_end.value
- })
- speaker_dict.update({speaker: {
- 'name': name,
- 'country': country_name,
- 'parties': party_list
- }
- })
- return speaker_dict
-
-
-def get_identifier(input_string: str) -> str:
- return input_string.split('/')[-1]
-
def language_name(lang_code: str) -> str:
return Language.make(language=standardize_tag(lang_code)).display_name()
-def get_speaker(input_data: Tuple[URIRef, dict]) -> str:
- (speaker, speaker_dict) = input_data
- return speaker_dict.get(speaker).get('name')
-
-
-def get_speaker_country(input_data: Tuple[URIRef, dict]) -> str:
- (speaker, speaker_dict) = input_data
- return speaker_dict.get(speaker).get('country')
-
-
-def get_speaker_party(input_data: Tuple[str, datetime, dict]) -> str:
- ''' look up the which EU party the speaker was part of at the date of their speech '''
- (speaker, date, party_data) = input_data
- party_list = party_data.get(speaker).get('parties')
- return next(
- (
- f"{p['party_name'].value} ({p['party_acronym'].value})"
- for p in party_list
- if (date >= p["date_start"] and date <= p["date_end"])
- ),
- None,
- )
-
-
-def get_speech_index(input_data: Tuple[str, list]) -> int:
- ''' find index of speech in array of debate parts '''
- speech, speeches = input_data
- if not speech:
- return None
- return speeches.index(speech) + 1
-
-
-def get_speech_text(input_string: str) -> str:
- ''' remove leading language information, e.g., `(IT)`'''
- return input_string.split(') ')[-1]
-
-
-def get_uri(input_data: Union[URIRef, str]) -> str:
- ''' convert input from URIRef to string '''
- try:
- return input_data.n3().strip('<>')
- except:
- return input_data
-
-
class ParliamentEurope(Parliament):
title = 'People & Parliament (European Parliament)'
description = "Speeches from the European Parliament (EP)"
@@ -139,18 +41,21 @@ class ParliamentEurope(Parliament):
description_page = 'euparl.md'
image = 'euparl.jpeg'
min_date = datetime(year=1999, month=7, day=20)
- max_date = datetime.now()
+ max_date = getattr(settings, 'PP_EUPARL_MAX_DATE', datetime.now())
+ language_field = 'original_language_code'
@property
def subcorpora(self):
return [
- ParliamentEuropeFromRDF(),
+ EUPDCorpReader(),
ParliamentEuropeFromAPI(),
]
- def sources(self, start, end):
+ def sources(self, **kwargs):
for i, subcorpus in enumerate(self.subcorpora):
- for source in subcorpus.sources(start, end):
+ logger.info(f'Extracting subcorpus: {subcorpus.__class__.__name__}')
+
+ for source in subcorpus.sources(**kwargs):
filename, metadata = source
metadata["subcorpus"] = i
yield filename, metadata
@@ -169,18 +74,25 @@ def source2dicts(self, source, **kwargs):
debate_title = field_defaults.debate_title()
date = field_defaults.date(min_date, max_date)
party = field_defaults.party()
+ party_full = field_defaults.party_full()
party_id = field_defaults.party_id()
+ party_national = FieldDefinition(
+ name='party_national',
+ display_name='National party',
+ es_mapping=keyword_mapping(enable_full_text_search=True),
+ search_filter=MultipleChoiceFilter(),
+ visualizations=['resultscount', 'termfrequency'],
+ )
sequence = field_defaults.sequence()
- source_language = FieldDefinition(
- name='source_language',
- display_name='Source language',
- description='Original language of the speech',
+ original_language = field_defaults.language()
+ original_language.name = 'original_language'
+ original_language.display_name='Original language'
+ original_language.description = 'Original language of the speech'
+
+ original_language_code = FieldDefinition(
+ name='original_language_code',
es_mapping=keyword_mapping(),
- search_filter=MultipleChoiceFilter(
- description='Search only in speeches in the selected original languages',
- option_count=50,
- ),
- visualizations=['resultscount', 'termfrequency'],
+ hidden=True,
)
speaker = field_defaults.speaker()
@@ -196,9 +108,30 @@ def source2dicts(self, source, **kwargs):
),
visualizations=['resultscount', 'termfrequency'],
)
+ speaker_gender = field_defaults.speaker_gender()
+ speaker_birth_year = field_defaults.speaker_birth_year()
+
speech = field_defaults.speech(language='en')
+ speech.description = 'Speech translated to English'
+ speech.language = 'en'
+
+ speech_original = FieldDefinition(
+ name='speech_original',
+ display_name='Original speech',
+ description='Speech in the original language',
+ es_mapping=main_content_mapping(),
+ search_field_core=True,
+ display_type='text_content',
+ language='dynamic',
+ )
+
speech_id = field_defaults.speech_id()
- url = field_defaults.url()
+ source_archive = FieldDefinition(
+ name='source_archive',
+ display_name='Source archive',
+ description='Source dataset for this document',
+ es_mapping=keyword_mapping(),
+ )
def __init__(self):
self.fields = [
@@ -206,27 +139,58 @@ def __init__(self):
self.debate_id,
self.debate_title,
self.party,
+ self.party_full,
self.party_id,
+ self.party_national,
self.sequence,
- self.source_language,
self.speaker,
self.speaker_country,
+ self.speaker_gender,
+ self.speaker_birth_year,
self.speaker_id,
self.speech,
+ self.speech_original,
+ self.original_language,
+ self.original_language_code,
self.speech_id,
- self.url,
+ self.source_archive,
]
+def _api_url(path: str, query: Dict = dict()) -> str:
+ full_path = parse.urljoin('/api/v2/', path)
+ base_query = {
+ 'format': 'application/ld+json',
+ 'User-Agent': 'textcavator',
+ }
+ query_string = parse.urlencode(base_query | query)
+ url = parse.urlunsplit(['https', 'data.europarl.europa.eu', full_path, query_string, ''])
+ return url
+
+
def api_convert_xml(speech_xml: str) -> str:
- speech_soup = BeautifulSoup(speech_xml, 'lxml')
- return speech_soup.find('speech').find('p').text
+ speech_soup = BeautifulSoup(speech_xml, 'lxml-xml')
+ paragraphs = speech_soup.find_all('p')
+ return '\n\n'.join(p.text for p in paragraphs)
-def api_get_language(languages: list[str]) -> str:
- language = language_name(languages[0].split('/')[-1])
- return language
+def api_get_language(languages: List[str]) -> Optional[str]:
+ label, _ = _api_get_language_data(languages[0])
+ return label
+def _api_get_language_code(languages: List[str]):
+ _, code = _api_get_language_data(languages[0])
+ return code
+
+@cache
+def _api_get_language_data(url: str) -> Tuple[str, str] | Tuple[None, None]:
+ response = requests.get(url)
+ if response.status_code != 200:
+ return None, None
+ soup = BeautifulSoup(response.content, 'lxml-xml')
+ label = soup.find('skos:prefLabel', {'xml:lang': 'en'}).text
+ code = soup.find('skos:notation', {'rdf:datatype': 'http://publications.europa.eu/ontology/euvoc#ISO_639_1'}).text
+ return label, code
def api_get_speaker_id(participant: str) -> str:
return participant.split('/')[-1]
@@ -237,19 +201,19 @@ def api_get_preflabel(url: str) -> Optional[str]:
response = requests.get(url)
if response.status_code != 200:
return None
- soup = BeautifulSoup(response.content, 'lxml')
- return soup.find('skos:preflabel', {'xml:lang': 'en'}).text
+ soup = BeautifulSoup(response.content, 'lxml-xml')
+ return soup.find('skos:prefLabel', {'xml:lang': 'en'}).text
+
@cache
-def api_get_speaker_info(participant: str) -> dict:
+def api_get_speaker_info(participant: str) -> Optional[Dict]:
'''Query metadata about the speaker, unless it's already been queried before'''
speaker_id = api_get_speaker_id(participant)
- speaker_response = requests.get(
- f'https://data.europarl.europa.eu/api/v2/meps/{speaker_id}?format=application%2Fld%2Bjson'
- )
+ speaker_url = _api_url(f'meps/{speaker_id}')
+ speaker_response = requests.get(speaker_url)
if not speaker_response.status_code == 200:
- logger.warning(f"No response for {speaker_id}")
+ logger.warning(f"No response for person {speaker_id}")
return {}
else:
return speaker_response.json().get('data')[0]
@@ -258,295 +222,470 @@ def api_get_speaker_info(participant: str) -> dict:
def api_get_speaker_country(participant: str) -> Optional[str]:
speaker_metadata = api_get_speaker_info(participant)
citizenship = speaker_metadata.get('citizenship')
- return api_get_preflabel(citizenship)
+ if citizenship:
+ return api_get_preflabel(citizenship)
+
+
+def _api_get_speaker_gender(participant: str) -> Optional[str]:
+ speaker_metadata = api_get_speaker_info(participant)
+ gender_uri = speaker_metadata.get('hasGender')
+ if gender_uri:
+ return gender_uri.split('/')[-1].title()
+def _api_get_speaker_birth_year(participant: str) -> Optional[int]:
+ speaker_metadata = api_get_speaker_info(participant)
+ birth_date = speaker_metadata.get('bday')
+ if birth_date:
+ d = datetime.strptime(birth_date, '%Y-%m-%d')
+ return d.year
def api_get_speaker_name(participant: str) -> str:
speaker_metadata = api_get_speaker_info(participant)
given_name = speaker_metadata.get('givenName')
family_name = speaker_metadata.get('familyName')
- return f'{given_name} {family_name}'
+ if given_name or family_name:
+ return f'{given_name} {family_name}'
@cache
-def api_get_party_id(data) -> dict:
+def api_get_party_id(data: Tuple[str, datetime]) -> dict:
participant, date = data
+ return _api_select_party(participant, date, 'def/ep-entities/EU_POLITICAL_GROUP')
+
+def _api_select_party(participant: str, date: datetime, classification: str) -> Optional[str]:
speaker_metadata = api_get_speaker_info(participant)
- memberships = speaker_metadata.get('hasMembership')
+ memberships = speaker_metadata.get('hasMembership') or []
for membership in memberships:
- if (
- membership.get('membershipClassification')
- != 'def/ep-entities/EU_POLITICAL_GROUP'
- ):
+ if membership.get('membershipClassification') != classification:
continue
membership_period = membership.get('memberDuring')
end_date = membership_period.get('endDate', datetime.now().strftime('%Y-%m-%d'))
if membership_period.get('startDate') <= date <= end_date:
return membership.get('organization').split('/')[-1]
- return ''
+
+def _api_get_national_party_id(data: Tuple[str, datetime]) -> Optional[str]:
+ participant, date = data
+ return _api_select_party(participant, date, 'def/ep-entities/NATIONAL_POLITICAL_GROUP')
def api_get_party_name(data) -> Optional[str]:
party_id = api_get_party_id(data)
return api_get_party_name_from_id(party_id)
+def _api_get_national_party_name(data: Tuple[str, datetime]) -> Optional[str]:
+ party_id = _api_get_national_party_id(data)
+ return api_get_party_name_from_id(party_id, False)
+
+_party_name_replacements = {
+ 'The Left': 'GUENGL',
+ 'Verts/ALE': 'GEFA',
+ 'S&D': 'SOCPESPASD',
+}
+'Replaces some party labels with the ones used in the 1999-2024 datasets'
+
+@cache
+def api_get_party_name_from_id(party_id: str, replacements=True) -> str:
+ data = _api_get_party_metadata(party_id)
+ if data:
+ label = data.get('data')[0].get('label')
+ if replacements:
+ return _party_name_replacements.get(label, label)
+ return label
+
+
+def _api_get_party_full_name(data) -> Optional[str]:
+ party_id = api_get_party_id(data)
+ return _api_get_party_full_name_from_id(party_id)
+
@cache
-def api_get_party_name_from_id(party_id: str) -> str:
+def _api_get_party_full_name_from_id(party_id: str) -> str:
+ data = _api_get_party_metadata(party_id)
+ if data:
+ return data.get('data')[0].get('altLabel').get('en')
+
+@cache
+def _api_get_party_metadata(party_id: str) -> Dict:
if not party_id:
return None
- party_response = requests.get(
- f'https://data.europarl.europa.eu/api/v2/corporate-bodies/{party_id}?format=application%2Fld%2Bjson&language=en'
- )
+ party_url = _api_url(f'corporate-bodies/{party_id}', {'language': 'en'})
+ party_response = requests.get(party_url)
if party_response.status_code != 200:
return None
- return party_response.json().get('data')[0].get('prefLabel').get('en')
+ return party_response.json()
+
+def _api_speech_key(language_code: str):
+ return f'api:xmlFragment.{language_code}'
+
+
+def _api_get_original_speech(data):
+ _, code = _api_get_language_data(data['originalLanguage'][0])
+ return data.get(_api_speech_key(code))
+
+def _api_get_meeting_id(value: List[str]):
+ path = first(value)
+ if path:
+ return path.split('/')[-1]
def first(values):
if len(values):
return values[0]
-class ParliamentEuropeFromAPI(JSONCorpusDefinition):
+def _api_format_date(value: datetime):
+ return value.strftime('%Y-%m-%d')
+
+
+class _JSON(JSON):
+ '''
+ Edited JSON extractor that also accepts 0 keys to return the object as-is
+ '''
+ # TODO: make this change in ianalyzer_readers
+
+ def _apply(self, data: Union[str, dict], key_index: int = 0, **kwargs):
+ if not len(self.keys):
+ return data
+ return super()._apply(data, key_index, **kwargs)
+
+
+class ParliamentEuropeFromAPI(JSONReader):
"""
- Speeches of the European parliament, originally in or translated to English,
- provided through the Europarl Open Data API
+ Reader to extract speeches from the Europarl Open Data API
+
+ See https://data.europarl.europa.eu/en/developer-corner/opendata-api for API
+ documentation.
+
+ Extracts from 9/2/2024 (the end of EUPDCorp) until the present.
"""
- min_date = datetime(year=2024, month=7, day=7)
+ min_date = datetime(year=2024, month=2, day=9)
max_date = datetime.now()
- # Variables to hold interim metadata
- speaker_metadata = {}
- party_metadata = {}
record_path = ['data', 'recorded_in_a_realization_of']
meta = [
['data', 'had_participation', 'had_participant_person'],
['data', 'activity_id'],
+ ['data', 'activity_date'],
+ ['data', 'activity_label'],
+ ['data', 'inverse_consists_of'],
]
- def sources(self, start, end, **kwargs):
- date = self.min_date
- while date < self.max_date:
- date += timedelta(days=1)
- formatted_date = date.strftime('%Y-%m-%d')
- meeting_id = f'MTG-PL-{formatted_date}'
- response = requests.get(
- f'https://data.europarl.europa.eu/api/v2/meetings/{meeting_id}/activities?format=application%2Fld%2Bjson',
- headers={'accept': 'application/ld+json'},
- )
- if response.status_code != 200:
- continue
- meeting_data = response.json().get('data')
- metadata = {'date': formatted_date}
- for event in meeting_data:
- if event.get("had_activity_type") != "def/ep-activities/PLENARY_DEBATE":
- continue
- metadata['debate_id'] = event.get('activity_id')
- metadata['debate_title'] = event.get('activity_label').get('en')
-
- sequence_in_debate = 0
-
- for speech in event.get('consists_of'):
- speech_id = speech.split("/")[-1]
- speech_response = requests.get(
- f'https://data.europarl.europa.eu/api/v2/speeches/{speech_id}?include-output=xml_fragment&language=en&format=application%2Fld%2Bjson'
- )
- if speech_response.status_code != 200:
- continue
- sequence_in_debate += 1
- metadata['sequence'] = sequence_in_debate
- yield speech_response, metadata
-
- debate_id = field_defaults.debate_id()
- debate_id.extractor = Metadata('debate_id')
-
- debate_title = field_defaults.debate_title()
- debate_title.extractor = Metadata('debate_title')
+ def sources(self, start_date=min_date, end_date=max_date, offset=0, **kwargs):
+ # Uses the /speeches endpoint to request paginated speeches in the date range.
+ # Limitation is that the iteration is capped at 10.000 speeches, so the time
+ # interval is dynamically broken up into smaller time intervals as needed.
+ # Implicitly assumes that start_date < end_date, and that there are never more
+ # than 10.000 speeches in a single day.
+
+ limit = 50
+ url = _api_url('speeches', {
+ 'activity-type': 'PLENARY_DEBATE_SPEECH',
+ 'sitting-date': _api_format_date(start_date),
+ 'sitting-date-end': _api_format_date(end_date),
+ 'include-output': 'xml_fragment',
+ 'sort-by': 'sitting-date:asc,numbering:asc',
+ 'offset': offset,
+ 'limit': limit,
+ })
+ logger.info(url)
+ response = requests.get(url)
+ data = response.json()
+ total = data.get('meta').get('total')
+
+ if total == 10000:
+ # if results are capped, use a shorter range
+ split_end = end_date - ((end_date - start_date) / 2)
+ yield from self.sources(start_date, split_end, 0)
+ split_start = split_end + timedelta(days=1)
+ yield from self.sources(split_start, end_date)
+ else:
+ yield response, {}
+
+ if offset + limit < total:
+ # if we're not through results yet, move to the next page
+ next_offset = offset + limit
+ yield from self.sources(start_date, end_date, next_offset)
+
+
+ def iterate_data(self, data: Dict, metadata):
+ # overrides the JSON data iterator to do some manipulations on the data
+ # to ensure validity
+
+ # add empty debate ID if key does not exist...
+ ensure_debate_id = lambda item: { 'inverse_consists_of': [] } | item
+ # ... & filter speeches without speaker metadata
+ complete_speeches = [
+ ensure_debate_id(item) for item in data['data']
+ if 'had_participation' in item
+ ]
+ filtered_data = data | {'data': complete_speeches}
+ records = list(super().iterate_data(filtered_data, metadata))
+ # filter records without transcription data
+ filtered_records = [
+ record for record in records
+ if record['data'].get(_api_speech_key('en'))
+ ]
+ return filtered_records
- date = field_defaults.date(min_date, max_date)
- date.extractor = Metadata('date')
- party = field_defaults.party()
- party.extractor = Combined(
- JSON(
- "data.had_participation.had_participant_person",
- transform=first,
- ),
- Metadata('date'),
- transform=api_get_party_name,
+ _date_extractor = JSON(
+ 'data.activity_date',
)
- party_id = field_defaults.party_id()
- party_id.extractor = Combined(
- JSON(
- "data.had_participation.had_participant_person",
- transform=first
+ fields = [
+ Field(
+ name='debate_id',
+ extractor=JSON('data.inverse_consists_of', transform=_api_get_meeting_id),
),
- Metadata('date'),
- transform=api_get_party_id,
- )
-
- sequence = field_defaults.sequence()
- sequence.extractor = Metadata('sequence')
-
- source_language = field_defaults.language()
- source_language.name = 'source_language'
- source_language.extractor = JSON("originalLanguage", transform=api_get_language)
-
- speaker = field_defaults.speaker()
- speaker.extractor = Pass(
- JSON(
- "data.had_participation.had_participant_person",
- transform=first,
+ Field(
+ name='debate_title',
+ extractor=JSON('data.activity_label', 'en'),
),
- transform=api_get_speaker_name,
- )
-
- speaker_country = FieldDefinition(
- name='speaker_country',
- extractor=Pass(
- JSON(
- "data.had_participation.had_participant_person",
- transform=first,
+ Field(
+ name='date',
+ extractor=_date_extractor
+ ),
+ Field(
+ name='party',
+ extractor=Combined(
+ JSON(
+ "data.had_participation.had_participant_person",
+ transform=first,
+ ),
+ _date_extractor,
+ transform=api_get_party_name,
+ )
+ ),
+ Field(
+ name='party_full',
+ extractor=Combined(
+ JSON(
+ "data.had_participation.had_participant_person",
+ transform=first,
+ ),
+ _date_extractor,
+ transform=_api_get_party_full_name,
+ )
+ ),
+ Field(
+ name='party_id',
+ extractor=Combined(
+ JSON(
+ "data.had_participation.had_participant_person",
+ transform=first
+ ),
+ _date_extractor,
+ transform=api_get_party_id,
+ )
+ ),
+ Field(
+ name='party_national',
+ extractor=Combined(
+ JSON(
+ "data.had_participation.had_participant_person",
+ transform=first
+ ),
+ _date_extractor,
+ transform=_api_get_national_party_name,
+ )
+ ),
+ Field(
+ name='sequence',
+ extractor=JSON('numbering')
+ ),
+ Field(
+ name='original_language',
+ extractor=JSON("originalLanguage", transform=api_get_language)
+ ),
+ Field(
+ name='original_language_code',
+ extractor=JSON('originalLanguage', transform=_api_get_language_code)
+ ),
+ Field(
+ name='speaker',
+ extractor=Pass(
+ JSON(
+ "data.had_participation.had_participant_person",
+ transform=first,
+ ),
+ transform=api_get_speaker_name,
+ )
+ ),
+ Field(
+ name='speaker_country',
+ extractor=Pass(
+ JSON(
+ "data.had_participation.had_participant_person",
+ transform=first,
+ ),
+ transform=api_get_speaker_country,
),
- transform=api_get_speaker_country,
),
- )
-
- speaker_id = field_defaults.speaker_id()
- speaker_id.extractor = Pass(
- JSON(
- "data.had_participation.had_participant_person",
- transform=first,
+ Field(
+ name='speaker_gender',
+ extractor=Pass(
+ JSON(
+ 'data.had_participation.had_participant_person',
+ transform=first,
+ ),
+ transform=_api_get_speaker_gender,
+ )
+ ),
+ Field(
+ name='speaker_birth_year',
+ extractor=Pass(
+ JSON(
+ 'data.had_participation.had_participant_person',
+ transform=first,
+ ),
+ transform=_api_get_speaker_birth_year,
+ )
+ ),
+ Field(
+ name='speaker_id',
+ extractor=Pass(
+ JSON(
+ "data.had_participation.had_participant_person",
+ transform=first,
+ ),
+ transform=api_get_speaker_id,
+ )
+ ),
+ Field(
+ name='speech',
+ extractor=JSON(
+ _api_speech_key('en'),
+ transform=api_convert_xml,
+ )
+ ),
+ Field(
+ name='speech_original',
+ extractor=Pass(
+ _JSON(
+ transform=_api_get_original_speech
+ ),
+ transform=api_convert_xml,
+ )
+ ),
+ Field(
+ name='id',
+ extractor=JSON("data.activity_id")
+ ),
+ Field(
+ name='source_archive',
+ extractor=Constant('European Parliament Open Data API')
),
- transform=api_get_speaker_id,
- )
-
- speech = field_defaults.speech()
- speech.extractor = JSON(
- "api:xmlFragment.en",
- transform=api_convert_xml,
- )
-
- speech_id = field_defaults.speech_id()
- speech_id.extractor = JSON("data.activity_id")
-
- fields = [
- date,
- debate_id,
- debate_title,
- party,
- party_id,
- sequence,
- source_language,
- speaker,
- speaker_country,
- speaker_id,
- speech,
- speech_id,
]
-class ParliamentEuropeFromRDF(RDFCorpusDefinition):
- """
- Speeches of the European parliament, originally in or translated to English,
- provided as Linked Open Data by the "Talk of Europe" project
- """
-
- min_date = datetime(year=1999, month=7, day=20)
- max_date = datetime(year=2017, month=7, day=6)
-
- data_directory = settings.PP_EUPARL_DATA
+def _to_int(value) -> Optional[int]:
+ if (value or value == 0) and not math.isnan(value):
+ return int(value)
- def sources(self, start, end, **kwargs):
- metadata = {
- "speakers": add_speaker_metadata(
- os.path.join(self.data_directory, MP_METADATA)
- )
- }
- yield os.path.join(self.data_directory, SPEECHES), metadata
-
- def document_subjects(self, graph: Graph):
- """return all subjects which have either translated or spoken text"""
- return chain(
- graph.subjects(predicate=LPV.translatedText),
- graph.subjects(predicate=LPV.spokenText),
- )
+def _format_name(values) -> str:
+ return ' '.join(
+ value for value in filter(None, values)
+ )
- def data_from_file(self, filename: str) -> Graph:
- '''we combine the graphs in place, to keep memory load low'''
- graph = Graph()
- graph.parse(filename)
- graph.parse(os.path.join(self.data_directory, EVENTS_METADATA))
- return graph
+def _nan_to_none(value):
+ if not isinstance(value, numbers.Number) or not math.isnan(value):
+ return value
- date = field_defaults.date(min_date, max_date)
- date.extractor = RDF(DCTERMS.date, transform=lambda x: x.strftime('%Y-%m-%d'))
+def _format_gender(value):
+ if value == 1:
+ return 'Male'
+ if value == 0:
+ return 'Female'
- debate_id = field_defaults.debate_id()
- debate_id.extractor = RDF(DCTERMS.isPartOf, transform=get_identifier)
- debate_title = field_defaults.debate_title()
- debate_title.extractor = RDF(DCTERMS.isPartOf, DCTERMS.title)
-
- party = field_defaults.party()
- party.extractor = Combined(
- RDF(LPV.speaker),
- RDF(DCTERMS.date),
- Metadata('speakers'),
- transform=get_speaker_party,
- )
-
- sequence = field_defaults.sequence()
- sequence.extractor = Combined(
- RDF(),
- RDF(DCTERMS.isPartOf, DCTERMS.hasPart, multiple=True),
- transform=get_speech_index,
- )
+class EUPDCorpReader(RDSReader):
+ '''
+ Reader for the EUPDCorp dataset. Contains debates from 20/7/1999 to 8/2/2024
+ '''
- source_language = field_defaults.language()
- source_language.name = 'source_language'
- source_language.extractor = RDF(DCTERMS.language, transform=language_name)
+ data_directory = settings.PP_EUPARL_DATA
- speaker = field_defaults.speaker()
- speaker.extractor = Combined(
- RDF(LPV.speaker), Metadata('speakers'), transform=get_speaker
- )
+ def sources(self, **kwargs):
+ for filename in os.listdir(self.data_directory):
+ if filename.lower().endswith('.rds'):
+ yield os.path.join(self.data_directory, filename), {}
- speaker_country = FieldDefinition(
- name='speaker_country',
- extractor=Combined(
- RDF(LPV.speaker), Metadata('speakers'), transform=get_speaker_country
+ fields = [
+ Field(
+ name='date',
+ extractor=CSV('date'),
),
- )
-
- speech = field_defaults.speech(language='en')
- speech.extractor = Backup(
- RDF(
- LPV.spokenText,
+ Field(
+ name='debate_id',
+ extractor=CSV('file'),
),
- RDF(
- LPV.translatedText,
+ Field(
+ name='debate_title',
+ extractor=CSV('agenda'),
),
- transform=get_speech_text,
- )
-
- speech_id = field_defaults.speech_id()
- speech_id.extractor = RDF(transform=get_identifier)
-
- url = field_defaults.url()
- url.extractor = Backup(RDF(LPV.videoURI, transform=get_uri), RDF(transform=get_uri))
-
- fields = [
- date,
- debate_id,
- debate_title,
- party,
- sequence,
- source_language,
- speaker,
- speaker_country,
- speech,
- speech_id,
- url,
+ Field(
+ name='original_language',
+ extractor=CSV(
+ 'language',
+ transform=lambda value: language_name(value.lower()),
+ ),
+ ),
+ Field(
+ name='original_language_code',
+ extractor=CSV('language', transform=lambda value: value.lower())
+ ),
+ Field(
+ name='party',
+ extractor=CSV('epg_short', transform=_nan_to_none),
+ ),
+ Field(
+ name='party_full',
+ extractor=CSV('epg_long', transform=_nan_to_none),
+ ),
+ Field(
+ name='party_national',
+ extractor=CSV('party_name', transform=_nan_to_none),
+ ),
+ Field(
+ name='sequence',
+ extractor=CSV('doc_id', transform=int),
+ ),
+ Field(
+ name='speech',
+ extractor=CSV('speech_en'),
+ ),
+ Field(
+ name='speech_original',
+ extractor=CSV('speech'),
+ ),
+ Field(
+ name='speaker',
+ extractor=Combined(
+ CSV('firstname'),
+ CSV('lastname'),
+ transform=_format_name,
+ )
+ ),
+ Field(
+ name='speaker_id',
+ extractor=Pass(
+ CSV('mepid', transform=_to_int),
+ transform=str,
+ ),
+ ),
+ Field(
+ name='speaker_gender',
+ extractor=CSV('gender', transform=_format_gender)
+ ),
+ Field(
+ name='speaker_birth_year',
+ extractor=CSV('birth_year', transform=_to_int)
+ ),
+ Field(
+ name='speaker_country',
+ extractor=CSV('nationality', transform=_nan_to_none),
+ ),
+ Field(
+ name='source_archive',
+ extractor=Constant('EUPDCorp'),
+ )
]
diff --git a/backend/corpora/parliament/tests/data/euparl/api/MeetingResponse.json b/backend/corpora/parliament/tests/data/euparl/api/MeetingResponse.json
deleted file mode 100644
index 313e8391b..000000000
--- a/backend/corpora/parliament/tests/data/euparl/api/MeetingResponse.json
+++ /dev/null
@@ -1,58 +0,0 @@
-{
- "data": [
- {
- "id": "eli/dl/event/MTG-PL-2024-11-13-PVCRE-ITM-17",
- "type": "Activity",
- "activity_date": "2024-11-13",
- "activity_id": "MTG-PL-2024-11-13-PVCRE-ITM-17",
- "activity_label": {
- "pt": "17. Combate ao branqueamento de capitais e ao financiamento do terrorismo: aditamento da Rússia à lista de países terceiros de risco elevado da UE (debate)",
- "mt": "17. Il-ġlieda kontra l-ħasil tal-flus u l-finanzjament tat-terroriżmu: l-elenkar tar-Russja bħala pajjiż terz b’riskju għoli fl-UE (dibattitu)",
- "es": "17. Lucha contra el blanqueo de capitales y la financiación del terrorismo: inclusión de Rusia en la lista de la Unión de terceros países de alto riesgo (debate)",
- "hr": "17. Borba protiv pranja novca i financiranja terorizma: uvrštavanje Rusije na popis visokorizičnih trećih zemalja u EU-u (rasprava)",
- "fi": "17. Rahanpesun ja terrorismin rahoituksen torjuminen: Venäjän luokitteleminen EU:ssa suuririskiseksi kolmanneksi maaksi (keskustelu)",
- "et": "17. Rahapesu ja terrorismi rahastamise vastane võitlus: Venemaa kandmine suure riskiga kolmandate riikide ELi loetellu (arutelu)",
- "pl": "17. Walka z praniem pieniędzy i finansowaniem terroryzmu: wpisanie Rosji na listę państw trzecich wysokiego ryzyka w UE (debata)",
- "sv": "17. Bekämpning av penningtvätt och finansiering av terrorism: uppförande av Ryssland på förteckningen över högrisktredjeländer i EU (debatt)",
- "cs": "17. Boj proti praní peněz a financování terorismu: zařazení Ruska na seznam vysoce rizikových třetích zemí pro EU (rozprava)",
- "de": "17. Bekämpfung von Geldwäsche und Terrorismusfinanzierung: Aufnahme Russlands in die Liste der Drittländer mit hohem Risiko (Aussprache)",
- "ga": "17. An comhrac i gcoinne sciúradh airgid agus maoiniú sceimhlitheoireachta: an Rúis a liostú san Aontas mar thríú tír ardriosca (díospóireacht)",
- "el": "17. Καταπολέμηση της νομιμοποίησης εσόδων από παράνομες δραστηριότητες και της χρηματοδότησης της τρομοκρατίας: καταχώριση της Ρωσίας ως τρίτης χώρας υψηλού κινδύνου στην ΕΕ (συζήτηση)",
- "sl": "17. Boj proti pranju denarja in financiranju terorizma: uvrstitev Rusije na seznam EU tretjih držav z visokim tveganjem (razprava)",
- "sk": "17. Boj proti praniu špinavých peňazí a financovaniu terorizmu: zaradenie Ruska do zoznamu vysokorizikových tretích krajín pre EÚ (rozprava)",
- "it": "17. Lotta al riciclaggio e al finanziamento del terrorismo: inserire la Russia nell'elenco dei paesi terzi ad alto rischio dell'UE (discussione)",
- "fr": "17. Lutte contre le blanchiment de capitaux et le financement du terrorisme: inscription de la Russie sur la liste des pays tiers à haut risque de l'UE (débat)",
- "ro": "17. Combaterea spălării banilor și a finanțării terorismului: includerea Rusiei printre țările terțe cu grad de risc ridicat pentru UE (dezbatere)",
- "nl": "17. Strijd tegen witwassen en terrorismefinanciering: opname van Rusland in de EU-lijst van derde landen met een hoog risico (debat)",
- "lt": "17. Kova su pinigų plovimu ir terorizmo finansavimu: Rusijos įtraukimas į ES sudarytą didelės rizikos trečiųjų valstybių sąrašą (diskusijos)",
- "hu": "17. A pénzmosás és a terrorizmus finanszírozása elleni küzdelem: Oroszország kiemelt kockázatot jelentő harmadik országként való uniós jegyzékbe vétele (vita)",
- "bg": "17. Борба с изпирането на пари и финансирането на тероризма: включване на Русия в списъка на ЕС на високорисковите трети страни (разискване)",
- "lv": "17. Cīņa pret nelikumīgi iegūtu līdzekļu legalizāciju un terorisma finansēšanu: Krievijas iekļaušana ES izveidotajā augsta riska trešo valstu sarakstā (debates)",
- "da": "17. Bekæmpelse af hvidvask af penge og af finansiering af terrorisme: opførelse af Rusland på listen over højrisikotredjelande i EU (forhandling)",
- "en": "17. Fight against money laundering and terrorist financing: listing Russia as a high-risk third country in the EU (debate)"
- },
- "consists_of": [
- "eli/dl/event/MTG-PL-2024-11-13-OTH-2017005042457"
- ],
- "executed": [
- "eli/dl/event/MTG-PL-2024-11-13-OJ-ITM-D-16"
- ],
- "had_activity_type": "def/ep-activities/PLENARY_DEBATE",
- "recorded_in_a_realization_of": [
- "eli/dl/doc/PV-10-2024-11-13-ITM-017",
- "eli/dl/doc/CRE-10-2024-11-13-ITM-017"
- ],
- "inverse_consists_of": [
- "eli/dl/event/MTG-PL-2024-11-13",
- "eli/dl/proc/2024-2905"
- ]
- }
- ],
- "@context": [
- {
- "data": "@graph",
- "@base": "https://data.europarl.europa.eu/"
- },
- "https://data.europarl.europa.eu/api/v2/context.jsonld"
- ]
-}
diff --git a/backend/corpora/parliament/tests/data/euparl/rdf/English.ttl b/backend/corpora/parliament/tests/data/euparl/rdf/English.ttl
deleted file mode 100644
index f58eb00a2..000000000
--- a/backend/corpora/parliament/tests/data/euparl/rdf/English.ttl
+++ /dev/null
@@ -1,22 +0,0 @@
-@prefix foaf: .
-@prefix xsd: .
-@prefix rdf: .
-@prefix lpv_eu: .
-@prefix lpv: .
-@prefix lp_eu: .
-@prefix lp: .
-@prefix dcterms: .
-
-lp_eu:1999-07-21-Speech-3-063 lpv:translatedText "(IT) Mr President, as a Member of the Italian national Parliament for the\n(The Northern League for the Independence of Padania), I did not vote for Professor Prodi in Rome as I considered he would be completely useless as head of government. I was then proved right as he lost the vote of confidence of the Italian Parliament. Reckoning also that a Roman idiot would still be that stupid wherever he was, which, incidently, is reflected in the symbol on the list which bears his name for the election of this Parliament, I cannot for consistency\"s sake express my faith in the President of the Commission. As a native of the Po valley who is Italian only by passport, I am fortunately immune from the national Christian Democrat type of opportunism which brings Berlusconi together with Mastella and De Mita and sees in Prodi not the impartial President of the Commissioners uninfluenced by the States, but the lavish dispenser of favours to a wide and varied assortment of Southern Italian profiteers. Although I hold some of the Commissioners in high esteem, I recall the old mafioso Neapolitan saying: ‘A fish rots from the head downwards’ and I therefore have to express my negative opinion of the Prodi Presidency."@en .
-lp_eu:1999-07-21-Speech-3-063 lpv:unclassifiedMetadata "Lega Nord per l'indipendenza della Padania" .
-lp_eu:1999-07-21-Speech-3-063 lpv:unclassifiedMetadata "Speroni (NI)" .
-
-lp_eu:2017-07-06-Speech-4-146-000 lpv:spokenText "Mr President, yesterday afternoon we had a lively debate, under Rule 153, on the subject of a single seat for this Parliament. Unfortunately, under that rule, it was not possible to have a resolution, but it was the clear will of this House that we bring forward a report to propose a treaty change. So, as Mr Weber and Mr Pittella are in their seats, could they please take note of the view of this House and, when the matter comes to the Conference of Presidents, could they please authorise that report?"@en .
-lp_eu:2017-07-06-Speech-4-146-000 lpv:unclassifiedMetadata "(Applause)" .
-lp_eu:2017-07-06-Speech-4-146-000 lpv:unclassifiedMetadata "Ashley Fox (ECR )." .
-
-lp_eu:1999-07-21_AgendaItem_5 dcterms:title "Statement by Mr Prodi, President-elect of the Commission"@en .
-
-lp_eu:2009-03-24_AgendaItem_30 dcterms:title "EIB and EBRD annual reports for 2007 - Community guarantee to the European Investment Bank (debate)"@en .
-
-lp_eu:2017-07-06_AgendaItem_13 dcterms:title "Composition of committees and delegations"@en .
diff --git a/backend/corpora/parliament/tests/data/euparl/rdf/Events_and_structure.ttl b/backend/corpora/parliament/tests/data/euparl/rdf/Events_and_structure.ttl
deleted file mode 100644
index 5981bbcba..000000000
--- a/backend/corpora/parliament/tests/data/euparl/rdf/Events_and_structure.ttl
+++ /dev/null
@@ -1,98 +0,0 @@
-@prefix foaf: .
-@prefix xsd: .
-@prefix rdf: .
-@prefix lpv_eu: .
-@prefix lpv: .
-@prefix lp_eu: .
-@prefix lp: .
-@prefix dcterms: .
-
-lp_eu:1999-07-21-Speech-3-063 a lpv_eu:Speech .
-lp_eu:1999-07-21-Speech-3-063 dcterms:date "1999-07-21"^^xsd:date .
-lp_eu:1999-07-21-Speech-3-063 dcterms:isPartOf lp_eu:1999-07-21_AgendaItem_5 .
-lp_eu:1999-07-21-Speech-3-063 dcterms:language "it"^^xsd:language .
-lp_eu:1999-07-21-Speech-3-063 lpv:docno "en.19990721.5.3-063" .
-lp_eu:1999-07-21-Speech-3-063 lpv:hasSubsequent lp_eu:1999-07-21-Speech-3-064 .
-lp_eu:1999-07-21-Speech-3-063 lpv:speaker lp:EUmember_997 .
-
-lp_eu:2017-07-06-Speech-4-146-000 a lpv_eu:Speech .
-lp_eu:2017-07-06-Speech-4-146-000 dcterms:date "2017-07-06"^^xsd:date .
-lp_eu:2017-07-06-Speech-4-146-000 dcterms:isPartOf lp_eu:2017-07-06_AgendaItem_13 .
-lp_eu:2017-07-06-Speech-4-146-000 dcterms:language "en"^^xsd:language .
-lp_eu:2017-07-06-Speech-4-146-000 lpv:docno "en.20170706.13.4-146-000" .
-lp_eu:2017-07-06-Speech-4-146-000 lpv:hasSubsequent lp_eu:2017-07-06-Speech-4-147-000 .
-lp_eu:2017-07-06-Speech-4-146-000 lpv:speaker lp:EUmember_96957 .
-lp_eu:2017-07-06-Speech-4-146-000 lpv:videoURI .
-
-lp_eu:1999-07-21_AgendaItem_5 a lpv_eu:AgendaItem .
-lp_eu:1999-07-21_AgendaItem_5 dcterms:date "1999-07-21"^^xsd:date .
-lp_eu:1999-07-21_AgendaItem_5 dcterms:hasPart lp_eu:1999-07-21-Speech-3-049 .
-lp_eu:1999-07-21_AgendaItem_5 dcterms:hasPart lp_eu:1999-07-21-Speech-3-050 .
-lp_eu:1999-07-21_AgendaItem_5 dcterms:hasPart lp_eu:1999-07-21-Speech-3-051 .
-lp_eu:1999-07-21_AgendaItem_5 dcterms:hasPart lp_eu:1999-07-21-Speech-3-052 .
-lp_eu:1999-07-21_AgendaItem_5 dcterms:hasPart lp_eu:1999-07-21-Speech-3-053 .
-lp_eu:1999-07-21_AgendaItem_5 dcterms:hasPart lp_eu:1999-07-21-Speech-3-054 .
-lp_eu:1999-07-21_AgendaItem_5 dcterms:hasPart lp_eu:1999-07-21-Speech-3-055 .
-lp_eu:1999-07-21_AgendaItem_5 dcterms:hasPart lp_eu:1999-07-21-Speech-3-056 .
-lp_eu:1999-07-21_AgendaItem_5 dcterms:hasPart lp_eu:1999-07-21-Speech-3-057 .
-lp_eu:1999-07-21_AgendaItem_5 dcterms:hasPart lp_eu:1999-07-21-Speech-3-058 .
-lp_eu:1999-07-21_AgendaItem_5 dcterms:hasPart lp_eu:1999-07-21-Speech-3-059 .
-lp_eu:1999-07-21_AgendaItem_5 dcterms:hasPart lp_eu:1999-07-21-Speech-3-060 .
-lp_eu:1999-07-21_AgendaItem_5 dcterms:hasPart lp_eu:1999-07-21-Speech-3-061 .
-lp_eu:1999-07-21_AgendaItem_5 dcterms:hasPart lp_eu:1999-07-21-Speech-3-062 .
-lp_eu:1999-07-21_AgendaItem_5 dcterms:hasPart lp_eu:1999-07-21-Speech-3-063 .
-lp_eu:1999-07-21_AgendaItem_5 dcterms:hasPart lp_eu:1999-07-21-Speech-3-064 .
-lp_eu:1999-07-21_AgendaItem_5 dcterms:hasPart lp_eu:1999-07-21-Speech-3-065 .
-lp_eu:1999-07-21_AgendaItem_5 dcterms:hasPart lp_eu:1999-07-21-Speech-3-066 .
-lp_eu:1999-07-21_AgendaItem_5 dcterms:hasPart lp_eu:1999-07-21-Speech-3-067 .
-lp_eu:1999-07-21_AgendaItem_5 dcterms:hasPart lp_eu:1999-07-21-Speech-3-068 .
-lp_eu:1999-07-21_AgendaItem_5 dcterms:hasPart lp_eu:1999-07-21-Speech-3-069 .
-lp_eu:1999-07-21_AgendaItem_5 dcterms:hasPart lp_eu:1999-07-21-Speech-3-070 .
-lp_eu:1999-07-21_AgendaItem_5 dcterms:hasPart lp_eu:1999-07-21-Speech-3-071 .
-lp_eu:1999-07-21_AgendaItem_5 dcterms:hasPart lp_eu:1999-07-21-Speech-3-072 .
-lp_eu:1999-07-21_AgendaItem_5 dcterms:hasPart lp_eu:1999-07-21-Speech-3-996 .
-lp_eu:1999-07-21_AgendaItem_5 dcterms:isPartOf lp_eu:1999-07-21_SessionDay .
-lp_eu:1999-07-21_AgendaItem_5 lpv:docno "en.19990721.5" .
-lp_eu:1999-07-21_AgendaItem_5 lpv:hasSubsequent lp_eu:1999-07-21_AgendaItem_6 .
-
-lp_eu:2009-03-24_AgendaItem_30 a lpv_eu:AgendaItem .
-lp_eu:2009-03-24_AgendaItem_30 dcterms:date "2009-03-24"^^xsd:date .
-lp_eu:2009-03-24_AgendaItem_30 dcterms:hasPart lp_eu:2009-03-24-Speech-2-353 .
-lp_eu:2009-03-24_AgendaItem_30 dcterms:hasPart lp_eu:2009-03-24-Speech-2-354 .
-lp_eu:2009-03-24_AgendaItem_30 dcterms:hasPart lp_eu:2009-03-24-Speech-2-355 .
-lp_eu:2009-03-24_AgendaItem_30 dcterms:hasPart lp_eu:2009-03-24-Speech-2-356 .
-lp_eu:2009-03-24_AgendaItem_30 dcterms:hasPart lp_eu:2009-03-24-Speech-2-357 .
-lp_eu:2009-03-24_AgendaItem_30 dcterms:hasPart lp_eu:2009-03-24-Speech-2-358 .
-lp_eu:2009-03-24_AgendaItem_30 dcterms:hasPart lp_eu:2009-03-24-Speech-2-359 .
-lp_eu:2009-03-24_AgendaItem_30 dcterms:hasPart lp_eu:2009-03-24-Speech-2-360 .
-lp_eu:2009-03-24_AgendaItem_30 dcterms:hasPart lp_eu:2009-03-24-Speech-2-361 .
-lp_eu:2009-03-24_AgendaItem_30 dcterms:hasPart lp_eu:2009-03-24-Speech-2-362 .
-lp_eu:2009-03-24_AgendaItem_30 dcterms:hasPart lp_eu:2009-03-24-Speech-2-363 .
-lp_eu:2009-03-24_AgendaItem_30 dcterms:hasPart lp_eu:2009-03-24-Speech-2-364 .
-lp_eu:2009-03-24_AgendaItem_30 dcterms:hasPart lp_eu:2009-03-24-Speech-2-365 .
-lp_eu:2009-03-24_AgendaItem_30 dcterms:hasPart lp_eu:2009-03-24-Speech-2-366 .
-lp_eu:2009-03-24_AgendaItem_30 dcterms:hasPart lp_eu:2009-03-24-Speech-2-367 .
-lp_eu:2009-03-24_AgendaItem_30 dcterms:hasPart lp_eu:2009-03-24-Speech-2-368 .
-lp_eu:2009-03-24_AgendaItem_30 dcterms:hasPart lp_eu:2009-03-24-Speech-2-369 .
-lp_eu:2009-03-24_AgendaItem_30 dcterms:hasPart lp_eu:2009-03-24-Speech-2-370 .
-lp_eu:2009-03-24_AgendaItem_30 dcterms:hasPart lp_eu:2009-03-24-Speech-2-371 .
-lp_eu:2009-03-24_AgendaItem_30 dcterms:hasPart lp_eu:2009-03-24-Speech-2-372 .
-lp_eu:2009-03-24_AgendaItem_30 dcterms:hasPart lp_eu:2009-03-24-Speech-2-373 .
-lp_eu:2009-03-24_AgendaItem_30 dcterms:hasPart lp_eu:2009-03-24-Speech-2-374 .
-lp_eu:2009-03-24_AgendaItem_30 dcterms:hasPart lp_eu:2009-03-24-Speech-2-375 .
-lp_eu:2009-03-24_AgendaItem_30 dcterms:hasPart lp_eu:2009-03-24-Speech-2-376 .
-lp_eu:2009-03-24_AgendaItem_30 dcterms:hasPart lp_eu:2009-03-24-Speech-2-377 .
-lp_eu:2009-03-24_AgendaItem_30 dcterms:isPartOf lp_eu:2009-03-24_SessionDay .
-lp_eu:2009-03-24_AgendaItem_30 lpv:docno "en.20090324.30" .
-lp_eu:2009-03-24_AgendaItem_30 lpv:hasSubsequent lp_eu:2009-03-24_AgendaItem_31 .
-
-lp_eu:2017-07-06_AgendaItem_13 a lpv_eu:AgendaItem .
-lp_eu:2017-07-06_AgendaItem_13 dcterms:date "2017-07-06"^^xsd:date .
-lp_eu:2017-07-06_AgendaItem_13 dcterms:hasPart lp_eu:2017-07-06-Speech-4-145-000 .
-lp_eu:2017-07-06_AgendaItem_13 dcterms:hasPart lp_eu:2017-07-06-Speech-4-146-000 .
-lp_eu:2017-07-06_AgendaItem_13 dcterms:hasPart lp_eu:2017-07-06-Speech-4-147-000 .
-lp_eu:2017-07-06_AgendaItem_13 dcterms:hasPart lp_eu:2017-07-06-Speech-4-148-000 .
-lp_eu:2017-07-06_AgendaItem_13 dcterms:hasPart lp_eu:2017-07-06-Speech-4-149-000 .
-lp_eu:2017-07-06_AgendaItem_13 dcterms:isPartOf lp_eu:2017-07-06_SessionDay .
-lp_eu:2017-07-06_AgendaItem_13 lpv:docno "en.20170706.13" .
-lp_eu:2017-07-06_AgendaItem_13 lpv:hasSubsequent lp_eu:2017-07-06_AgendaItem_14 .
diff --git a/backend/corpora/parliament/tests/data/euparl/rdf/MembersOfParliament_background.ttl b/backend/corpora/parliament/tests/data/euparl/rdf/MembersOfParliament_background.ttl
deleted file mode 100644
index ea1cd2748..000000000
--- a/backend/corpora/parliament/tests/data/euparl/rdf/MembersOfParliament_background.ttl
+++ /dev/null
@@ -1,807 +0,0 @@
-@prefix foaf: .
-@prefix lp: .
-@prefix lpv: .
-@prefix ns1: .
-@prefix rdfs: .
-@prefix xsd: .
-
- a lpv:EUParty ;
- rdfs:label "AGRI",
- "European Democratic Group" ;
- lpv:acronym "AGRI" ;
- lpv:featuredRoleDescriptions "European Democratic Group - Chair",
- "European Democratic Group - Member",
- "European Democratic Group - Member of the Bureau",
- "European Democratic Group - Treasurer",
- "European Democratic Group - Vice-Chair" .
-
- a lpv:EUParty ;
- rdfs:label "ALDE",
- "Group of the Alliance of Liberals and Democrats for Europe" ;
- lpv:acronym "ALDE" ;
- lpv:featuredRoleDescriptions "Group of the Alliance of Liberals and Democrats for Europe -",
- "Group of the Alliance of Liberals and Democrats for Europe - Chair",
- "Group of the Alliance of Liberals and Democrats for Europe - Member",
- "Group of the Alliance of Liberals and Democrats for Europe - Member of the Bureau",
- "Group of the Alliance of Liberals and Democrats for Europe - Vice-Chair" .
-
- a lpv:EUParty ;
- rdfs:label "COM",
- "Communist and Allies Group" ;
- lpv:acronym "COM" ;
- lpv:featuredRoleDescriptions "Communist and Allies Group -",
- "Communist and Allies Group - Chair",
- "Communist and Allies Group - Member",
- "Communist and Allies Group - Treasurer",
- "Communist and Allies Group - Vice-Chair" .
-
- a lpv:EUParty ;
- rdfs:label "DR",
- "Technical Group of the European Right" ;
- lpv:acronym "DR" ;
- lpv:featuredRoleDescriptions "Technical Group of the European Right -",
- "Technical Group of the European Right - Chair",
- "Technical Group of the European Right - Member",
- "Technical Group of the European Right - Member of the Bureau",
- "Technical Group of the European Right - Treasurer",
- "Technical Group of the European Right - Vice-Chair" .
-
- a lpv:EUParty ;
- rdfs:label "EDA",
- "Group of the European Democratic Alliance" ;
- lpv:acronym "EDA" ;
- lpv:featuredRoleDescriptions "Group of the European Democratic Alliance - Chair",
- "Group of the European Democratic Alliance - Member",
- "Group of the European Democratic Alliance - Member of the Bureau",
- "Group of the European Democratic Alliance - Treasurer",
- "Group of the European Democratic Alliance - Vice-Chair" .
-
- a lpv:EUParty ;
- rdfs:label "EDD",
- "Group for a Europe of Democracies and Diversities" ;
- lpv:acronym "EDD" ;
- lpv:featuredRoleDescriptions "Group for a Europe of Democracies and Diversities - Chair",
- "Group for a Europe of Democracies and Diversities - Co-Chair",
- "Group for a Europe of Democracies and Diversities - Member",
- "Group for a Europe of Democracies and Diversities - Member of the Bureau" .
-
- a lpv:EUParty ;
- rdfs:label "EFDD",
- "Europe of Freedom and Direct Democracy Group" ;
- lpv:acronym "EFDD" ;
- lpv:featuredRoleDescriptions "Europe of Freedom and Direct Democracy Group - Chair of the Bureau",
- "Europe of Freedom and Direct Democracy Group - Co-Chair",
- "Europe of Freedom and Direct Democracy Group - Member",
- "Europe of Freedom and Direct Democracy Group - Member of the Bureau",
- "Europe of Freedom and Direct Democracy Group - Treasurer",
- "Europe of Freedom and Direct Democracy Group - Vice-Chair" .
-
- a lpv:EUParty ;
- rdfs:label "ELDR",
- "Group of the European Liberal, Democrat and Reform Party" ;
- lpv:acronym "ELDR" ;
- lpv:featuredRoleDescriptions "Group of the European Liberal, Democrat and Reform Party -",
- "Group of the European Liberal, Democrat and Reform Party - Chair",
- "Group of the European Liberal, Democrat and Reform Party - Member",
- "Group of the European Liberal, Democrat and Reform Party - Member of the Bureau",
- "Group of the European Liberal, Democrat and Reform Party - Treasurer",
- "Group of the European Liberal, Democrat and Reform Party - Vice-Chair" .
-
- a lpv:EUParty ;
- rdfs:label "EN",
- "Europe of Nations Group (Coordination Group)" ;
- lpv:acronym "EN" ;
- lpv:featuredRoleDescriptions "Europe of Nations Group (Coordination Group) -",
- "Europe of Nations Group (Coordination Group) - Chair",
- "Europe of Nations Group (Coordination Group) - Member",
- "Europe of Nations Group (Coordination Group) - Treasurer",
- "Europe of Nations Group (Coordination Group) - Vice-Chair" .
-
- a lpv:EUParty ;
- rdfs:label "EPD",
- "Group of European Progressive Democrats" ;
- lpv:acronym "EPD" ;
- lpv:featuredRoleDescriptions "Group of European Progressive Democrats - Chair",
- "Group of European Progressive Democrats - Member",
- "Group of European Progressive Democrats - Member of the Bureau",
- "Group of European Progressive Democrats - Treasurer",
- "Group of European Progressive Democrats - Vice-Chair" .
-
- a lpv:EUParty ;
- rdfs:label "EPP",
- "Group of the European People's Party (Christian Democrats)",
- "Group of the European People's Party (Christian-Democratic Group)" ;
- lpv:acronym "EPP" ;
- lpv:featuredRoleDescriptions "Group of the European People's Party (Christian Democrats) -",
- "Group of the European People's Party (Christian Democrats) - Chair",
- "Group of the European People's Party (Christian Democrats) - Member",
- "Group of the European People's Party (Christian Democrats) - Member of the Bureau",
- "Group of the European People's Party (Christian Democrats) - Vice-Chair",
- "Group of the European People's Party (Christian-Democratic Group) -",
- "Group of the European People's Party (Christian-Democratic Group) - Chair",
- "Group of the European People's Party (Christian-Democratic Group) - Member",
- "Group of the European People's Party (Christian-Democratic Group) - Member of the Bureau",
- "Group of the European People's Party (Christian-Democratic Group) - Treasurer",
- "Group of the European People's Party (Christian-Democratic Group) - Vice-Chair" .
-
- a lpv:EUParty ;
- rdfs:label "EPP-ED",
- "Group of the European People's Party (Christian Democrats) and European Democrats" ;
- lpv:acronym "EPP-ED" ;
- lpv:featuredRoleDescriptions "Group of the European People's Party (Christian Democrats) and European Democrats -",
- "Group of the European People's Party (Christian Democrats) and European Democrats - Chair",
- "Group of the European People's Party (Christian Democrats) and European Democrats - Member",
- "Group of the European People's Party (Christian Democrats) and European Democrats - Member of the Bureau",
- "Group of the European People's Party (Christian Democrats) and European Democrats - Treasurer",
- "Group of the European People's Party (Christian Democrats) and European Democrats - Vice-Chair" .
-
- a lpv:EUParty ;
- rdfs:label "ER",
- "Group of the European Right" ;
- lpv:acronym "ER" ;
- lpv:featuredRoleDescriptions "Group of the European Right -",
- "Group of the European Right - Chair",
- "Group of the European Right - Member",
- "Group of the European Right - Member of the Bureau",
- "Group of the European Right - Treasurer",
- "Group of the European Right - Vice-Chair" .
-
- a lpv:EUParty ;
- rdfs:label "ERA",
- "Group of the European Radical Alliance" ;
- lpv:acronym "ERA" ;
- lpv:featuredRoleDescriptions "Group of the European Radical Alliance - Chair",
- "Group of the European Radical Alliance - Member",
- "Group of the European Radical Alliance - Member of the Bureau",
- "Group of the European Radical Alliance - Treasurer" .
-
- a lpv:EUParty ;
- rdfs:label "Confederal Group of the European United Left",
- "EUL",
- "Group for the European United Left" ;
- lpv:acronym "EUL" ;
- lpv:featuredRoleDescriptions "Confederal Group of the European United Left - Chair",
- "Confederal Group of the European United Left - Member",
- "Confederal Group of the European United Left - Treasurer",
- "Confederal Group of the European United Left - Vice-Chair",
- "Group for the European United Left - Chair",
- "Group for the European United Left - Member",
- "Group for the European United Left - Member of the Bureau",
- "Group for the European United Left - Treasurer",
- "Group for the European United Left - Vice-Chair" .
-
- a lpv:EUParty ;
- rdfs:label "Confederal Group of the European United Left - Nordic Green Left",
- "Confederal Group of the European United Left/Nordic Green Left",
- "EUL/NGL" ;
- lpv:acronym "EUL/NGL" ;
- lpv:featuredRoleDescriptions "Confederal Group of the European United Left - Nordic Green Left -",
- "Confederal Group of the European United Left - Nordic Green Left - Chair",
- "Confederal Group of the European United Left - Nordic Green Left - Member",
- "Confederal Group of the European United Left - Nordic Green Left - Member of the Bureau",
- "Confederal Group of the European United Left - Nordic Green Left - Treasurer",
- "Confederal Group of the European United Left - Nordic Green Left - Vice-Chair",
- "Confederal Group of the European United Left/Nordic Green Left -",
- "Confederal Group of the European United Left/Nordic Green Left - Chair",
- "Confederal Group of the European United Left/Nordic Green Left - Member",
- "Confederal Group of the European United Left/Nordic Green Left - Member of the Bureau",
- "Confederal Group of the European United Left/Nordic Green Left - Treasurer",
- "Confederal Group of the European United Left/Nordic Green Left - Vice-Chair" .
-
- a lpv:EUParty ;
- rdfs:label "FE",
- "Forza Europa Group" ;
- lpv:acronym "FE" ;
- lpv:featuredRoleDescriptions "Forza Europa Group - Chair",
- "Forza Europa Group - Member",
- "Forza Europa Group - Member of the Bureau",
- "Forza Europa Group - Treasurer",
- "Forza Europa Group - Vice-Chair" .
-
- a lpv:EUParty ;
- rdfs:label "G",
- "The Green Group in the European Parliament" ;
- lpv:acronym "G" ;
- lpv:featuredRoleDescriptions "The Green Group in the European Parliament - Chair",
- "The Green Group in the European Parliament - Member",
- "The Green Group in the European Parliament - Member of the Bureau",
- "The Green Group in the European Parliament - Treasurer",
- "The Green Group in the European Parliament - Vice-Chair" .
-
- a lpv:EUParty ;
- rdfs:label "G/EFA",
- "Group of the Greens/European Free Alliance" ;
- lpv:acronym "G/EFA" ;
- lpv:featuredRoleDescriptions "Group of the Greens/European Free Alliance -",
- "Group of the Greens/European Free Alliance - Chair",
- "Group of the Greens/European Free Alliance - Co-Chair",
- "Group of the Greens/European Free Alliance - Member",
- "Group of the Greens/European Free Alliance - Member of the Bureau",
- "Group of the Greens/European Free Alliance - Treasurer",
- "Group of the Greens/European Free Alliance - Vice-Chair" .
-
- a lpv:EUParty ;
- rdfs:label "Group of Independents for a Europe of Nations",
- "I-EN" ;
- lpv:acronym "I-EN" ;
- lpv:featuredRoleDescriptions "Group of Independents for a Europe of Nations -",
- "Group of Independents for a Europe of Nations - Chair",
- "Group of Independents for a Europe of Nations - Co-Chair",
- "Group of Independents for a Europe of Nations - Member",
- "Group of Independents for a Europe of Nations - Treasurer",
- "Group of Independents for a Europe of Nations - Vice-Chair" .
-
- a lpv:EUParty ;
- rdfs:label "ITS",
- "Identity, Tradition and Sovereignty Group" ;
- lpv:acronym "ITS" ;
- lpv:featuredRoleDescriptions "Identity, Tradition and Sovereignty Group - Chair",
- "Identity, Tradition and Sovereignty Group - Member",
- "Identity, Tradition and Sovereignty Group - Member of the Bureau",
- "Identity, Tradition and Sovereignty Group - Treasurer",
- "Identity, Tradition and Sovereignty Group - Vice-Chair" .
-
- a lpv:EUParty ;
- rdfs:label "LD",
- "Liberal and Democratic Group" ;
- lpv:acronym "LD" ;
- lpv:featuredRoleDescriptions "Liberal and Democratic Group -",
- "Liberal and Democratic Group - Chair",
- "Liberal and Democratic Group - Member",
- "Liberal and Democratic Group - Treasurer",
- "Liberal and Democratic Group - Vice-Chair" .
-
- a lpv:EUParty ;
- rdfs:label "LDR",
- "Liberal and Democratic Reformist Group" ;
- lpv:acronym "LDR" ;
- lpv:featuredRoleDescriptions "Liberal and Democratic Reformist Group -",
- "Liberal and Democratic Reformist Group - Chair",
- "Liberal and Democratic Reformist Group - Member",
- "Liberal and Democratic Reformist Group - Treasurer",
- "Liberal and Democratic Reformist Group - Vice-Chair" .
-
- a lpv:EUParty ;
- rdfs:label "LU",
- "Left Unity" ;
- lpv:acronym "LU" ;
- lpv:featuredRoleDescriptions "Left Unity -",
- "Left Unity - Chair",
- "Left Unity - Member",
- "Left Unity - Treasurer",
- "Left Unity - Vice-Chair" .
-
- a lpv:EUParty ;
- rdfs:label "Group of the Party of European Socialists",
- "PES",
- "Socialist Group in the European Parliament" ;
- lpv:acronym "PES" ;
- lpv:featuredRoleDescriptions "Group of the Party of European Socialists -",
- "Group of the Party of European Socialists - Chair",
- "Group of the Party of European Socialists - Member",
- "Group of the Party of European Socialists - Member of the Bureau",
- "Group of the Party of European Socialists - Treasurer",
- "Group of the Party of European Socialists - Vice-Chair",
- "Socialist Group in the European Parliament -",
- "Socialist Group in the European Parliament - Chair",
- "Socialist Group in the European Parliament - Member",
- "Socialist Group in the European Parliament - Treasurer",
- "Socialist Group in the European Parliament - Vice-Chair" .
-
- a lpv:EUParty ;
- rdfs:label "Group of the Progressive Alliance of Socialists and Democrats in the European Parliament",
- "S&D" ;
- lpv:acronym "S&D" ;
- lpv:featuredRoleDescriptions "Group of the Progressive Alliance of Socialists and Democrats in the European Parliament -",
- "Group of the Progressive Alliance of Socialists and Democrats in the European Parliament - Chair",
- "Group of the Progressive Alliance of Socialists and Democrats in the European Parliament - Member",
- "Group of the Progressive Alliance of Socialists and Democrats in the European Parliament - Treasurer",
- "Group of the Progressive Alliance of Socialists and Democrats in the European Parliament - Vice-Chair" .
-
- a lpv:EUParty ;
- rdfs:label "SOC",
- "Socialist Group" ;
- lpv:acronym "SOC" ;
- lpv:featuredRoleDescriptions "Socialist Group -",
- "Socialist Group - Chair",
- "Socialist Group - Member",
- "Socialist Group - Member of the Bureau",
- "Socialist Group - Treasurer",
- "Socialist Group - Vice-Chair" .
-
- a lpv:EUParty ;
- rdfs:label "Group Union for Europe",
- "UFE" ;
- lpv:acronym "UFE" ;
- lpv:featuredRoleDescriptions "Group Union for Europe - Chair",
- "Group Union for Europe - Member",
- "Group Union for Europe - Member of the Bureau",
- "Group Union for Europe - Treasurer",
- "Group Union for Europe - Vice-Chair" .
-
-lp:EUmember_96957 a ns1:MemberOfParliament ;
- ns1:MEP_ID "96957" ;
- ns1:countryOfRepresentation lp:EUCountry_GB ;
- ns1:dateOfBirth "1969-11-15"^^xsd:date ;
- ns1:placeOfBirth "Sutton Coldfield" ;
- ns1:politicalFunction lp:pf00f88c83af0e95f9d4ba9f0c9bd0a093,
- lp:pf0f78c03fefe0985f764dea70022d0043,
- lp:pf2bdc66e4eb24629cd4d221b54b45a3ca,
- lp:pf350caf782f08b96e2a3af35fc5616001,
- lp:pf399a6d922ff4c20a852fc22d6600906e,
- lp:pf52bab8d1a349df571ebeb55761db513c,
- lp:pf58aecb3742c3fe35d5080e16645b07c8,
- lp:pf8240375d0714e974c78fb753d862122a,
- lp:pf99c4158caafcfba5bc9fda500f3d0c60,
- lp:pfba1033551486f93285992b1f262dc79e,
- lp:pfc8ae7a828c60553e27378b19a12a862a,
- lp:pfcedffd5e8d734d1203db8fa3f7038f78,
- lp:pfd9732399a8c6bbb7c5e041837244a2f8,
- lp:pfe61b1fb146891c9d4d0bbf88349d10f8,
- lp:pfe6b98484dd76e8c4c9e3e9783f2b0583,
- lp:pff56829256d54fb49a895889d87467924 ;
- foaf:name "Ashley Fox" .
-
-lp:EUmember_997 a ns1:MemberOfParliament ;
- ns1:MEP_ID "997" ;
- ns1:countryOfRepresentation lp:EUCountry_IT ;
- ns1:dateOfBirth "1946-10-04"^^xsd:date ;
- ns1:placeOfBirth "Busto Arsizio" ;
- ns1:politicalFunction lp:pf00850f07d83ff7511d816f2906631631,
- lp:pf1617b45a9e5df3163b8429577b4a3555,
- lp:pf18c223c3363102672b51b21c184056cc,
- lp:pf1ef5ada5f958b0aba640e490e460a221,
- lp:pf2170f06ac1f449772b48a5e844b1f7cd,
- lp:pf232468ecbffeb758cc38b17eb407a0e8,
- lp:pf27013a6352e31f1747cb0925a8d315a9,
- lp:pf2cff760ac2aa89d9fb6a7c65e2055670,
- lp:pf3520fdebb83d60437179f91787dfecf9,
- lp:pf36596b04e9f7439a17fd0764130a0a16,
- lp:pf4009f4a6d184651935c94eaf0e8e3b31,
- lp:pf42381eeb3b04b2383aa048ad07ce1723,
- lp:pf46b57676499000ff10b62596ebaaff0a,
- lp:pf4e79d2756b56075d1ba8ead84562bd8b,
- lp:pf50f29b8e60bb70630a741c75d9e15850,
- lp:pf5520a69a514cdd1f889ff24e68b34128,
- lp:pf57173b89fb6ac13826d452fc74067ff3,
- lp:pf5a2de253c92e0c12b84cac7c1e155666,
- lp:pf6356d7122a0fb25ece5db75f61c19671,
- lp:pf64ca0f3f6dde49e4a542560ed5122891,
- lp:pf6579712af153fc6ce1b0db2de821f92d,
- lp:pf76dd5ad131d30ed3306a78709e7ce251,
- lp:pf870c0cf3766606d20cec0aecf1851569,
- lp:pf8e8990b89425d1d5fefd0526973a771a,
- lp:pf8e9b064d23472496eb5097e9e61f664f,
- lp:pf9d156e058e9b318c9b9df62e3a5ab42a,
- lp:pfb592b70d3ae90102ecf4f9cf0dbbf362,
- lp:pfb8d606b79e721a9f0dd3232ebbe34ca4,
- lp:pfbb4b02d1622a4615842f6f422386345c,
- lp:pfc0aa2605dab67ed5619e571ffaa06fbc,
- lp:pfc4defbc2ab4682bb4ffda87d34391823,
- lp:pfd69065d8553a1a36e8aa0811ef83e0d3,
- lp:pfd941468c3faf619ad5d0a0156420880c,
- lp:pfddd269fab021f83ba0a89efc4298e439,
- lp:pfe33ac318848090cbc8bce7f6e4f26f6f,
- lp:pff4a2c78f09a9956180c64fe9dc17b9c1,
- lp:pff75a3ca6e96a14db43823be10fb693d2,
- lp:pffa15145f38d5a44e3ef93a4534a2df63,
- lp:pffeee7811d1a25e86cc33849665eeb484 ;
- foaf:name "Francesco Enrico Speroni" .
-
-lp:EUCountry_GB rdfs:label "United Kingdom"@en .
-
-lp:EUCountry_IT rdfs:label "Italy"@en .
-
- a lpv:EUParty ;
- rdfs:label "EFD",
- "Europe of freedom and democracy Group" ;
- lpv:acronym "EFD" ;
- lpv:featuredRoleDescriptions "Europe of freedom and democracy Group -",
- "Europe of freedom and democracy Group - Chair of the Bureau",
- "Europe of freedom and democracy Group - Co-Chair",
- "Europe of freedom and democracy Group - Member",
- "Europe of freedom and democracy Group - Vice-Chair" .
-
- a lpv:EUParty ;
- rdfs:label "IND/DEM",
- "Independence/Democracy Group" ;
- lpv:acronym "IND/DEM" ;
- lpv:featuredRoleDescriptions "Independence/Democracy Group - Chair",
- "Independence/Democracy Group - Chair of the Bureau",
- "Independence/Democracy Group - Co-Chair",
- "Independence/Democracy Group - Member",
- "Independence/Democracy Group - Member of the Bureau",
- "Independence/Democracy Group - Treasurer" .
-
- a lpv:EUParty ;
- rdfs:label "RBW",
- "Rainbow Group in the European Parliament",
- "Rainbow Group: Federation of the Green-Alternative European Links, Agelev-Ecolo, the Danish People's Movement against Membership of the European Community and the European Free Alliance in the European Parliament" ;
- lpv:acronym "RBW" ;
- lpv:featuredRoleDescriptions "Rainbow Group in the European Parliament - Chair",
- "Rainbow Group in the European Parliament - Member",
- "Rainbow Group in the European Parliament - Member of the Bureau",
- "Rainbow Group in the European Parliament - Treasurer",
- "Rainbow Group: Federation of the Green-Alternative European Links, Agelev-Ecolo, the Danish People's Movement against Membership of the European Community and the European Free Alliance in the European Parliament - Chair",
- "Rainbow Group: Federation of the Green-Alternative European Links, Agelev-Ecolo, the Danish People's Movement against Membership of the European Community and the European Free Alliance in the European Parliament - Member" .
-
- a lpv:EUParty ;
- rdfs:label "UEN",
- "Union for Europe of the Nations Group" ;
- lpv:acronym "UEN" ;
- lpv:featuredRoleDescriptions "Union for Europe of the Nations Group -",
- "Union for Europe of the Nations Group - Chair",
- "Union for Europe of the Nations Group - Co-Chair",
- "Union for Europe of the Nations Group - Member",
- "Union for Europe of the Nations Group - Treasurer",
- "Union for Europe of the Nations Group - Vice-Chair" .
-
-lp:pf00850f07d83ff7511d816f2906631631 a ns1:PoliticalFunction ;
- ns1:beginning "1999-07-21"^^xsd:date ;
- ns1:end "2002-01-14"^^xsd:date ;
- ns1:institution ;
- ns1:role .
-
-lp:pf00f88c83af0e95f9d4ba9f0c9bd0a093 a ns1:PoliticalFunction ;
- ns1:beginning "2014-07-01"^^xsd:date ;
- ns1:end "2017-03-31"^^xsd:date ;
- ns1:institution ;
- ns1:role .
-
-lp:pf0f78c03fefe0985f764dea70022d0043 a ns1:PoliticalFunction ;
- ns1:beginning "2012-01-25"^^xsd:date ;
- ns1:end "2014-06-30"^^xsd:date ;
- ns1:institution ;
- ns1:role .
-
-lp:pf1617b45a9e5df3163b8429577b4a3555 a ns1:PoliticalFunction ;
- ns1:beginning "2012-01-19"^^xsd:date ;
- ns1:end "2014-04-02"^^xsd:date ;
- ns1:institution ;
- ns1:role .
-
-lp:pf18c223c3363102672b51b21c184056cc a ns1:PoliticalFunction ;
- ns1:beginning "1991-10-10"^^xsd:date ;
- ns1:end "1992-01-14"^^xsd:date ;
- ns1:institution ;
- ns1:role .
-
-lp:pf1ef5ada5f958b0aba640e490e460a221 a ns1:PoliticalFunction ;
- ns1:beginning "2000-11-16"^^xsd:date ;
- ns1:end "2002-01-14"^^xsd:date ;
- ns1:institution ;
- ns1:role .
-
-lp:pf2170f06ac1f449772b48a5e844b1f7cd a ns1:PoliticalFunction ;
- ns1:beginning "1999-07-20"^^xsd:date ;
- ns1:end "1999-07-21"^^xsd:date ;
- ns1:institution ;
- ns1:role .
-
-lp:pf232468ecbffeb758cc38b17eb407a0e8 a ns1:PoliticalFunction ;
- ns1:beginning "1999-07-20"^^xsd:date ;
- ns1:end "2004-07-19"^^xsd:date ;
- ns1:institution ;
- ns1:role .
-
-lp:pf27013a6352e31f1747cb0925a8d315a9 a ns1:PoliticalFunction ;
- ns1:beginning "1992-01-15"^^xsd:date ;
- ns1:end "1992-10-25"^^xsd:date ;
- ns1:institution ;
- ns1:role .
-
-lp:pf2bdc66e4eb24629cd4d221b54b45a3ca a ns1:PoliticalFunction ;
- ns1:beginning "2009-09-15"^^xsd:date ;
- ns1:end "2012-01-18"^^xsd:date ;
- ns1:institution ;
- ns1:role .
-
-lp:pf2cff760ac2aa89d9fb6a7c65e2055670 a ns1:PoliticalFunction ;
- ns1:beginning "1989-07-26"^^xsd:date ;
- ns1:end "1991-10-09"^^xsd:date ;
- ns1:institution ;
- ns1:role .
-
-lp:pf350caf782f08b96e2a3af35fc5616001 a ns1:PoliticalFunction ;
- ns1:beginning "2009-07-21"^^xsd:date ;
- ns1:end "2012-01-18"^^xsd:date ;
- ns1:institution ;
- ns1:role .
-
-lp:pf3520fdebb83d60437179f91787dfecf9 a ns1:PoliticalFunction ;
- ns1:beginning "2007-01-31"^^xsd:date ;
- ns1:end "2009-07-13"^^xsd:date ;
- ns1:institution ;
- ns1:role .
-
-lp:pf36596b04e9f7439a17fd0764130a0a16 a ns1:PoliticalFunction ;
- ns1:beginning "1992-01-15"^^xsd:date ;
- ns1:end "1994-05-11"^^xsd:date ;
- ns1:institution ;
- ns1:role .
-
-lp:pf399a6d922ff4c20a852fc22d6600906e a ns1:PoliticalFunction ;
- ns1:beginning "2014-07-01"^^xsd:date ;
- ns1:end "2017-03-31"^^xsd:date ;
- ns1:institution ;
- ns1:role .
-
-lp:pf4009f4a6d184651935c94eaf0e8e3b31 a ns1:PoliticalFunction ;
- ns1:beginning "2007-01-15"^^xsd:date ;
- ns1:end "2007-01-30"^^xsd:date ;
- ns1:institution ;
- ns1:role .
-
-lp:pf42381eeb3b04b2383aa048ad07ce1723 a ns1:PoliticalFunction ;
- ns1:beginning "2009-07-14"^^xsd:date ;
- ns1:end "2014-06-30"^^xsd:date ;
- ns1:institution ;
- ns1:role .
-
-lp:pf46b57676499000ff10b62596ebaaff0a a ns1:PoliticalFunction ;
- ns1:beginning "2002-01-17"^^xsd:date ;
- ns1:end "2004-07-19"^^xsd:date ;
- ns1:institution ;
- ns1:role .
-
-lp:pf4e79d2756b56075d1ba8ead84562bd8b a ns1:PoliticalFunction ;
- ns1:beginning "2009-07-16"^^xsd:date ;
- ns1:end "2011-10-04"^^xsd:date ;
- ns1:institution ;
- ns1:role .
-
-lp:pf50f29b8e60bb70630a741c75d9e15850 a ns1:PoliticalFunction ;
- ns1:beginning "2004-07-20"^^xsd:date ;
- ns1:end "2004-07-20"^^xsd:date ;
- ns1:institution ;
- ns1:role .
-
-lp:pf52bab8d1a349df571ebeb55761db513c a ns1:PoliticalFunction ;
- ns1:beginning "2012-01-19"^^xsd:date ;
- ns1:end "2012-01-24"^^xsd:date ;
- ns1:institution ;
- ns1:role .
-
-lp:pf5520a69a514cdd1f889ff24e68b34128 a ns1:PoliticalFunction ;
- ns1:beginning "2001-10-03"^^xsd:date ;
- ns1:end "2004-07-19"^^xsd:date ;
- ns1:institution ;
- ns1:role .
-
-lp:pf57173b89fb6ac13826d452fc74067ff3 a ns1:PoliticalFunction ;
- ns1:beginning "1989-07-26"^^xsd:date ;
- ns1:end "1992-01-14"^^xsd:date ;
- ns1:institution ;
- ns1:role .
-
-lp:pf58aecb3742c3fe35d5080e16645b07c8 a ns1:PoliticalFunction ;
- ns1:beginning "2011-03-09"^^xsd:date ;
- ns1:end "2014-06-30"^^xsd:date ;
- ns1:institution ;
- ns1:role .
-
-lp:pf5a2de253c92e0c12b84cac7c1e155666 a ns1:PoliticalFunction ;
- ns1:beginning "2004-07-20"^^xsd:date ;
- ns1:end "2009-07-13"^^xsd:date ;
- ns1:institution ;
- ns1:role .
-
-lp:pf6356d7122a0fb25ece5db75f61c19671 a ns1:PoliticalFunction ;
- ns1:beginning "1989-07-26"^^xsd:date ;
- ns1:end "1992-01-14"^^xsd:date ;
- ns1:institution ;
- ns1:role .
-
-lp:pf64ca0f3f6dde49e4a542560ed5122891 a ns1:PoliticalFunction ;
- ns1:beginning "1992-10-26"^^xsd:date ;
- ns1:end "1994-05-11"^^xsd:date ;
- ns1:institution ;
- ns1:role .
-
-lp:pf6579712af153fc6ce1b0db2de821f92d a ns1:PoliticalFunction ;
- ns1:beginning "2004-09-14"^^xsd:date ;
- ns1:end "2007-01-14"^^xsd:date ;
- ns1:institution ;
- ns1:role .
-
-lp:pf76dd5ad131d30ed3306a78709e7ce251 a ns1:PoliticalFunction ;
- ns1:beginning "2006-04-27"^^xsd:date ;
- ns1:end "2006-12-12"^^xsd:date ;
- ns1:institution ;
- ns1:role .
-
-lp:pf8240375d0714e974c78fb753d862122a a ns1:PoliticalFunction ;
- ns1:beginning "2014-09-16"^^xsd:date ;
- ns1:end "2014-11-11"^^xsd:date ;
- ns1:institution ;
- ns1:role .
-
-lp:pf870c0cf3766606d20cec0aecf1851569 a ns1:PoliticalFunction ;
- ns1:beginning "1994-04-21"^^xsd:date ;
- ns1:end "1994-05-11"^^xsd:date ;
- ns1:institution ;
- ns1:role .
-
-lp:pf8e8990b89425d1d5fefd0526973a771a a ns1:PoliticalFunction ;
- ns1:beginning "2007-01-15"^^xsd:date ;
- ns1:end "2007-01-30"^^xsd:date ;
- ns1:institution ;
- ns1:role .
-
-lp:pf8e9b064d23472496eb5097e9e61f664f a ns1:PoliticalFunction ;
- ns1:beginning "1989-07-25"^^xsd:date ;
- ns1:end "1994-05-11"^^xsd:date ;
- ns1:institution ;
- ns1:role .
-
-lp:pf99c4158caafcfba5bc9fda500f3d0c60 a ns1:PoliticalFunction ;
- ns1:beginning "2012-01-19"^^xsd:date ;
- ns1:end "2014-06-30"^^xsd:date ;
- ns1:institution ;
- ns1:role .
-
-lp:pf9d156e058e9b318c9b9df62e3a5ab42a a ns1:PoliticalFunction ;
- ns1:beginning "2004-07-21"^^xsd:date ;
- ns1:end "2007-01-14"^^xsd:date ;
- ns1:institution ;
- ns1:role .
-
-lp:pfb592b70d3ae90102ecf4f9cf0dbbf362 a ns1:PoliticalFunction ;
- ns1:beginning "2010-01-07"^^xsd:date ;
- ns1:end "2012-01-18"^^xsd:date ;
- ns1:institution ;
- ns1:role .
-
-lp:pfb8d606b79e721a9f0dd3232ebbe34ca4 a ns1:PoliticalFunction ;
- ns1:beginning "2006-12-13"^^xsd:date ;
- ns1:end "2009-07-13"^^xsd:date ;
- ns1:institution ;
- ns1:role .
-
-lp:pfba1033551486f93285992b1f262dc79e a ns1:PoliticalFunction ;
- ns1:beginning "2009-07-14"^^xsd:date ;
- ns1:end "2011-03-08"^^xsd:date ;
- ns1:institution ;
- ns1:role .
-
-lp:pfbb4b02d1622a4615842f6f422386345c a ns1:PoliticalFunction ;
- ns1:beginning "2009-07-16"^^xsd:date ;
- ns1:end "2012-01-18"^^xsd:date ;
- ns1:institution ;
- ns1:role .
-
-lp:pfc0aa2605dab67ed5619e571ffaa06fbc a ns1:PoliticalFunction ;
- ns1:beginning "2007-01-31"^^xsd:date ;
- ns1:end "2009-07-13"^^xsd:date ;
- ns1:institution ;
- ns1:role .
-
-lp:pfc4defbc2ab4682bb4ffda87d34391823 a ns1:PoliticalFunction ;
- ns1:beginning "2002-01-17"^^xsd:date ;
- ns1:end "2004-07-19"^^xsd:date ;
- ns1:institution ;
- ns1:role .
-
-lp:pfc8ae7a828c60553e27378b19a12a862a a ns1:PoliticalFunction ;
- ns1:beginning "2014-07-01"^^xsd:date ;
- ns1:end "2017-03-31"^^xsd:date ;
- ns1:institution ;
- ns1:role .
-
-lp:pfcedffd5e8d734d1203db8fa3f7038f78 a ns1:PoliticalFunction ;
- ns1:beginning "2009-07-16"^^xsd:date ;
- ns1:end "2011-02-06"^^xsd:date ;
- ns1:institution ;
- ns1:role .
-
-lp:pfd69065d8553a1a36e8aa0811ef83e0d3 a ns1:PoliticalFunction ;
- ns1:beginning "1992-01-15"^^xsd:date ;
- ns1:end "1994-05-11"^^xsd:date ;
- ns1:institution ;
- ns1:role .
-
-lp:pfd941468c3faf619ad5d0a0156420880c a ns1:PoliticalFunction ;
- ns1:beginning "2007-01-31"^^xsd:date ;
- ns1:end "2009-07-13"^^xsd:date ;
- ns1:institution ;
- ns1:role .
-
-lp:pfd9732399a8c6bbb7c5e041837244a2f8 a ns1:PoliticalFunction ;
- ns1:beginning "2012-01-19"^^xsd:date ;
- ns1:end "2014-06-30"^^xsd:date ;
- ns1:institution ;
- ns1:role .
-
-lp:pfddd269fab021f83ba0a89efc4298e439 a ns1:PoliticalFunction ;
- ns1:beginning "1999-09-09"^^xsd:date ;
- ns1:end "1999-09-16"^^xsd:date ;
- ns1:institution ;
- ns1:role .
-
-lp:pfe33ac318848090cbc8bce7f6e4f26f6f a ns1:PoliticalFunction ;
- ns1:beginning "1999-07-22"^^xsd:date ;
- ns1:end "2001-10-02"^^xsd:date ;
- ns1:institution ;
- ns1:role .
-
-lp:pfe61b1fb146891c9d4d0bbf88349d10f8 a ns1:PoliticalFunction ;
- ns1:beginning "2009-07-14"^^xsd:date ;
- ns1:end "2014-06-30"^^xsd:date ;
- ns1:institution ;
- ns1:role .
-
-lp:pfe6b98484dd76e8c4c9e3e9783f2b0583 a ns1:PoliticalFunction ;
- ns1:beginning "2011-02-07"^^xsd:date ;
- ns1:end "2012-01-18"^^xsd:date ;
- ns1:institution ;
- ns1:role .
-
-lp:pff4a2c78f09a9956180c64fe9dc17b9c1 a ns1:PoliticalFunction ;
- ns1:beginning "2004-07-21"^^xsd:date ;
- ns1:end "2006-04-26"^^xsd:date ;
- ns1:institution ;
- ns1:role .
-
-lp:pff56829256d54fb49a895889d87467924 a ns1:PoliticalFunction ;
- ns1:beginning "2014-07-01"^^xsd:date ;
- ns1:end "2017-03-31"^^xsd:date ;
- ns1:institution ;
- ns1:role .
-
-lp:pff75a3ca6e96a14db43823be10fb693d2 a ns1:PoliticalFunction ;
- ns1:beginning "2009-07-14"^^xsd:date ;
- ns1:end "2014-06-30"^^xsd:date ;
- ns1:institution ;
- ns1:role .
-
-lp:pffa15145f38d5a44e3ef93a4534a2df63 a ns1:PoliticalFunction ;
- ns1:beginning "2004-07-21"^^xsd:date ;
- ns1:end "2006-04-26"^^xsd:date ;
- ns1:institution ;
- ns1:role .
-
-lp:pffeee7811d1a25e86cc33849665eeb484 a ns1:PoliticalFunction ;
- ns1:beginning "1989-07-25"^^xsd:date ;
- ns1:end "1994-04-20"^^xsd:date ;
- ns1:institution ;
- ns1:role .
-
- a lpv:EUParty ;
- rdfs:label "Group for the Technical Coordination and Defence of Indipendent Groups and Members",
- "TGI",
- "Technical Coordination and Defence of Independent Groups and Members",
- "Technical Group of Independent Members - mixed group" ;
- lpv:acronym "TGI" ;
- lpv:featuredRoleDescriptions "Group for the Technical Coordination and Defence of Indipendent Groups and Members - Chair",
- "Group for the Technical Coordination and Defence of Indipendent Groups and Members - Member",
- "Group for the Technical Coordination and Defence of Indipendent Groups and Members - Member of the Bureau",
- "Group for the Technical Coordination and Defence of Indipendent Groups and Members - Vice-Chair",
- "Technical Coordination and Defence of Independent Groups and Members - Member",
- "Technical Coordination and Defence of Independent Groups and Members - Member of the Bureau",
- "Technical Group of Independent Members - mixed group - Co-Chair",
- "Technical Group of Independent Members - mixed group - Member",
- "Technical Group of Independent Members - mixed group - Member of the Bureau",
- "Technical Group of Independent Members - mixed group - Treasurer" .
-
- a lpv:EUParty ;
- rdfs:label "ECR",
- "European Conservatives and Reformists Group" ;
- lpv:acronym "ECR" ;
- lpv:featuredRoleDescriptions "European Conservatives and Reformists Group -",
- "European Conservatives and Reformists Group - Chair",
- "European Conservatives and Reformists Group - Co-treasurer",
- "European Conservatives and Reformists Group - Member",
- "European Conservatives and Reformists Group - Member of the Bureau",
- "European Conservatives and Reformists Group - Treasurer",
- "European Conservatives and Reformists Group - Vice-Chair" .
-
- a lpv:EUParty ;
- rdfs:label "NA",
- "Non-attached",
- "Non-attached Members" ;
- lpv:acronym "NA" ;
- lpv:featuredRoleDescriptions "Non-attached -",
- "Non-attached - Member",
- "Non-attached Members -",
- "Non-attached Members - Member" .
-
diff --git a/backend/corpora/parliament/tests/data/euparl/rds/sample.rds b/backend/corpora/parliament/tests/data/euparl/rds/sample.rds
new file mode 100644
index 000000000..57bca9e47
Binary files /dev/null and b/backend/corpora/parliament/tests/data/euparl/rds/sample.rds differ
diff --git a/backend/corpora/parliament/utils/rds_reader.py b/backend/corpora/parliament/utils/rds_reader.py
new file mode 100644
index 000000000..08f1122a8
--- /dev/null
+++ b/backend/corpora/parliament/utils/rds_reader.py
@@ -0,0 +1,23 @@
+from typing import Iterable, Dict
+
+import pyreadr
+import pandas
+
+from ianalyzer_readers.readers.core import Reader
+
+
+class RDSReader(Reader):
+ def data_from_file(self, path) -> Iterable[Dict]:
+ result = pyreadr.read_r(path)
+ for value in result.values():
+ data: pandas.DataFrame = value
+
+ for _, row in data.iterrows():
+ yield {
+ index: value
+ for index, value in row.items()
+ }
+
+ def iterate_data(self, data: Iterable[Dict], metadata):
+ for row in data:
+ yield {'rows': [row]} # this format is for compatability with the CSV extractor
diff --git a/backend/requirements.in b/backend/requirements.in
index 25a97e55e..4d4fe08e6 100644
--- a/backend/requirements.in
+++ b/backend/requirements.in
@@ -29,3 +29,4 @@ flower
ianalyzer_readers
jsonschema
Pillow
+pyreadr
diff --git a/backend/requirements.txt b/backend/requirements.txt
index 4c636b72b..e6b18cb12 100644
--- a/backend/requirements.txt
+++ b/backend/requirements.txt
@@ -2,7 +2,7 @@
# This file is autogenerated by pip-compile with Python 3.12
# by the following command:
#
-# pip-compile --cert=None --client-cert=None --index-url=None --pip-args=None
+# pip-compile
#
amqp==5.3.1
# via kombu
@@ -54,7 +54,7 @@ defusedxml==0.7.1
# djangosaml2
# pysaml2
# python3-openid
-dj-rest-auth[with-social,with_social]==4.0.1
+dj-rest-auth[with-social]==4.0.1
# via -r requirements.in
django==4.2.27
# via
@@ -146,6 +146,7 @@ pandas==2.3.3
# via
# -r requirements.in
# ianalyzer-readers
+ # pyreadr
pillow==11.3.0
# via -r requirements.in
pluggy==1.6.0
@@ -168,6 +169,8 @@ pyparsing==3.2.5
# via rdflib
pypdf==6.6.2
# via -r requirements.in
+pyreadr==0.5.4
+ # via -r requirements.in
pysaml2==7.5.2
# via djangosaml2
pytest==8.4.2