API Documentation

This part of the project documentation focuses on an information-oriented approach. Use it as a reference for the technical implementation of the pylobid project code.

pylobid

main module

GNDAPIError

Bases: Exception

Broad exception if something unexpected happens.

Source code in src/pylobid/pylobid.py
17
18
class GNDAPIError(Exception):
    """Broad exception if something unexpected happens."""

GNDIdError

Bases: ValueError

Exception raised if the GND-ID is invalid.

Source code in src/pylobid/pylobid.py
 9
10
class GNDIdError(ValueError):
    """Exception raised if the GND-ID is invalid."""

GNDNotFoundError

Bases: Exception

Exception raised if the API returns Not Found for a GND-ID.

Source code in src/pylobid/pylobid.py
13
14
class GNDNotFoundError(Exception):
    """Exception raised if the API returns Not Found for a GND-ID."""

PyLobidClient

Main Class to interact with LOBID-API.

Source code in src/pylobid/pylobid.py
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
class PyLobidClient:
    """Main Class to interact with LOBID-API."""

    def factory(self):
        """Return a matching instance for the GND URL or ID.

        - Type `PlaceOrGeographicName` returns a `PyLobidPlace` instance.
        - Type `CorporateBody` returns a `PyLobidOrg` instance.
        - Type `Person` returns a `PyLobidPerson` instance.
        - Type `Work` returns a `PyLobidWork` instance.
        - All other types a `PyLobidPerson` instance

        :return: An matching object for the GND URL or Id
        :rtype: `PyLobidPlace`, `PyLobidOrg`, `PyLobidPerson`, `PyLobidPerson`
        """
        if self.ent_dict == {}:
            raise ValueError(f"No data found for {self.gnd_url}")
        if not self.ent_type:
            raise ValueError(f"Unknown type for {self.gnd_url}")
        if self.is_person:
            output = PyLobidPerson(gnd_id=None, fetch_related=self.fetch_related)
            output.process_data(data=self.ent_dict)
        elif self.is_org:
            output = PyLobidOrg(gnd_id=None)
            output.process_data(data=self.ent_dict)
        elif self.is_work:
            output = PyLobidWork(gnd_id=None)
            output.process_data(data=self.ent_dict)
        elif self.is_place:
            output = PyLobidPlace(gnd_id=None)
            output.process_data(data=self.ent_dict)
        else:
            return self
        return output

    @property
    def gnd_id(self) -> str:
        """Return the GND ID, e.g. 118650130."""
        return self.__gnd_id

    @property
    def gnd_url(self) -> str:
        """Return the GND URL e.g. http://d-nb.info/gnd/118650130"""
        return f"{self.BASE_URL}/{self.gnd_id}" if self.gnd_id is not None else False

    @property
    def is_place(self) -> bool:
        """Return True if this instance is a place entity, False otherwise."""
        return "PlaceOrGeographicName" in self.ent_type

    @property
    def is_org(self) -> bool:
        """Return True if this instance is an organization entity, False otherwise."""
        return "CorporateBody" in self.ent_type

    @property
    def is_person(self) -> bool:
        """Return True if this instance is a person entity, False otherwise."""
        return "Person" in self.ent_type

    @property
    def is_work(self) -> bool:
        """Return True if this instance is a work entity, False otherwise."""
        return "Work" in self.ent_type

    @property
    def ent_type(self) -> list:
        """Return the entity type."""
        return self.ent_dict.get("type", [])

    @property
    def same_as(self) -> list:
        """Return a list of alternative norm-data-ids."""
        return self.get_same_as()

    @property
    def alt_names(self) -> list:
        """Return a list of alternative names."""
        return self.get_alt_names()

    @property
    def pref_name(self) -> str:
        """Return the preferred name."""
        return self.get_pref_name()

    def extract_id(self, url: str) -> str:
        """Extract the GND-ID from an GND-URL.

        :param url: A GND-URL, e.g. http://d-nb.info/gnd/118650130
        :type url: str

        :raises: GNDIdError if no GND-ID is found.
        :return: The GND-ID, e.g. 118650130
        :rtype: str
        """
        gnd_id = re.search(self.ID_PATTERN, url)
        if gnd_id is None:
            raise GNDIdError(f'Could not find GND-ID in "{url}"')
        return gnd_id.group()

    def get_entity_lobid_url(self, url: str) -> str:
        """creates a lobid-entity URL from an GND-URL

        :param url: A GND-URL, e.g. http://d-nb.info/gnd/118650130
        :type url: str

        :return: A LOBID-ENTITY-URL, e.g. http://lobid.org/gnd/116000562
        :rtype: str
        """
        self.__gnd_id = self.extract_id(url)
        return self.gnd_url

    def get_entity_json(self, url: str = None) -> dict:
        """Get the LOBID-JSON response of a given GND-URL.

        :param url: A GND_URL
        :type url: str, optional

        :raises: GNDNotFoundError, GNDAPIError
        :return: The matching JSON representation fetched from LOBID
        :rtype: dict
        """
        url = self.gnd_url if url is None else self.get_entity_lobid_url(url)
        response = requests.get(url, headers={"Accept": "application/json"})
        if response.status_code == 404:
            raise GNDNotFoundError(
                f'Could not find a GND Entity for ID "{self.gnd_id}"'
            )
        if not response.ok:
            raise GNDAPIError(f"GND API error code: {response.status_code}")
        return response.json()

    def get_same_as(self) -> list:
        """Get the list of alternative norm-data-ids.

        :return: A list of tuples like ('GeoNames', 'http://sws.geonames.org/2782067'),
        :rtype: list
        """
        return [
            (x["collection"].get("abbr", "no_abbr"), x["id"])
            for x in self.ent_dict["sameAs"]
        ]

    def get_pref_name(self) -> str:
        """Get the preferred name.

        :return: The preferred Name vale, e.g. 'Assmann, Richard'
        :rtype: str
        """
        result = self.ent_dict.get("preferredName", "")
        return result

    def get_alt_names(self) -> list:
        """Get the list of alternative names.

        :return: a list of alternative names
        :rtype: list
        """
        ent_dict = self.ent_dict
        return next(
            iter([match.value for match in self.pref_alt_names_xpath.find(ent_dict)]),
            [],
        )

    def __str__(self) -> str:
        return self.BASE_URL

    def __repr__(self) -> str:
        return f"<PyLobidClient {self.gnd_url}>"

    def __init__(self, gnd_id: str = None, fetch_related: bool = False) -> None:
        """Class constructor."""
        self.BASE_URL = "http://lobid.org/gnd"
        self.ID_PATTERN = r"([0-9]\w*-*\w*)"
        self.coords_xpath = parse("$..hasGeometry")
        self.coords_regex = r"[+|-]\d+(?:\.\d*)?"
        self.pref_alt_names_xpath = parse("$.variantName")
        self.fetch_related = fetch_related
        self.__gnd_id = None
        self.ent_dict = {}
        self.process_data(gnd_id=gnd_id)

    def process_data(self, gnd_id: str = None, data: dict = None) -> None:
        """Fetch and/or process entity data.

        The arguments `gnd_id` and `data` are mutually exclusive.

        :param gnd_id: any kind of GND_URI/URL
        :type gnd_id: str, optional
        :param data: an already fetched ent_dict
        :type data: dict, optional
        """
        if data is not None and gnd_id is not None:
            raise ValueError("gnd_id and data mutually exclusive parameters")
        if data is not None and "id" in data:
            _ = self.get_entity_lobid_url(data.get("id"))
            self.ent_dict = data
        elif gnd_id is not None:
            _ = self.get_entity_lobid_url(gnd_id)
            self.ent_dict = self.get_entity_json()

alt_names property

Return a list of alternative names.

ent_type property

Return the entity type.

gnd_id property

Return the GND ID, e.g. 118650130.

gnd_url property

Return the GND URL e.g. http://d-nb.info/gnd/118650130

is_org property

Return True if this instance is an organization entity, False otherwise.

is_person property

Return True if this instance is a person entity, False otherwise.

is_place property

Return True if this instance is a place entity, False otherwise.

is_work property

Return True if this instance is a work entity, False otherwise.

pref_name property

Return the preferred name.

same_as property

Return a list of alternative norm-data-ids.

__init__(gnd_id=None, fetch_related=False)

Class constructor.

Source code in src/pylobid/pylobid.py
191
192
193
194
195
196
197
198
199
200
201
def __init__(self, gnd_id: str = None, fetch_related: bool = False) -> None:
    """Class constructor."""
    self.BASE_URL = "http://lobid.org/gnd"
    self.ID_PATTERN = r"([0-9]\w*-*\w*)"
    self.coords_xpath = parse("$..hasGeometry")
    self.coords_regex = r"[+|-]\d+(?:\.\d*)?"
    self.pref_alt_names_xpath = parse("$.variantName")
    self.fetch_related = fetch_related
    self.__gnd_id = None
    self.ent_dict = {}
    self.process_data(gnd_id=gnd_id)

extract_id(url)

Extract the GND-ID from an GND-URL.

:param url: A GND-URL, e.g. http://d-nb.info/gnd/118650130 :type url: str

:raises: GNDIdError if no GND-ID is found. :return: The GND-ID, e.g. 118650130 :rtype: str

Source code in src/pylobid/pylobid.py
106
107
108
109
110
111
112
113
114
115
116
117
118
119
def extract_id(self, url: str) -> str:
    """Extract the GND-ID from an GND-URL.

    :param url: A GND-URL, e.g. http://d-nb.info/gnd/118650130
    :type url: str

    :raises: GNDIdError if no GND-ID is found.
    :return: The GND-ID, e.g. 118650130
    :rtype: str
    """
    gnd_id = re.search(self.ID_PATTERN, url)
    if gnd_id is None:
        raise GNDIdError(f'Could not find GND-ID in "{url}"')
    return gnd_id.group()

factory()

Return a matching instance for the GND URL or ID.

  • Type PlaceOrGeographicName returns a PyLobidPlace instance.
  • Type CorporateBody returns a PyLobidOrg instance.
  • Type Person returns a PyLobidPerson instance.
  • Type Work returns a PyLobidWork instance.
  • All other types a PyLobidPerson instance

:return: An matching object for the GND URL or Id :rtype: PyLobidPlace, PyLobidOrg, PyLobidPerson, PyLobidPerson

Source code in src/pylobid/pylobid.py
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
def factory(self):
    """Return a matching instance for the GND URL or ID.

    - Type `PlaceOrGeographicName` returns a `PyLobidPlace` instance.
    - Type `CorporateBody` returns a `PyLobidOrg` instance.
    - Type `Person` returns a `PyLobidPerson` instance.
    - Type `Work` returns a `PyLobidWork` instance.
    - All other types a `PyLobidPerson` instance

    :return: An matching object for the GND URL or Id
    :rtype: `PyLobidPlace`, `PyLobidOrg`, `PyLobidPerson`, `PyLobidPerson`
    """
    if self.ent_dict == {}:
        raise ValueError(f"No data found for {self.gnd_url}")
    if not self.ent_type:
        raise ValueError(f"Unknown type for {self.gnd_url}")
    if self.is_person:
        output = PyLobidPerson(gnd_id=None, fetch_related=self.fetch_related)
        output.process_data(data=self.ent_dict)
    elif self.is_org:
        output = PyLobidOrg(gnd_id=None)
        output.process_data(data=self.ent_dict)
    elif self.is_work:
        output = PyLobidWork(gnd_id=None)
        output.process_data(data=self.ent_dict)
    elif self.is_place:
        output = PyLobidPlace(gnd_id=None)
        output.process_data(data=self.ent_dict)
    else:
        return self
    return output

get_alt_names()

Get the list of alternative names.

:return: a list of alternative names :rtype: list

Source code in src/pylobid/pylobid.py
173
174
175
176
177
178
179
180
181
182
183
def get_alt_names(self) -> list:
    """Get the list of alternative names.

    :return: a list of alternative names
    :rtype: list
    """
    ent_dict = self.ent_dict
    return next(
        iter([match.value for match in self.pref_alt_names_xpath.find(ent_dict)]),
        [],
    )

get_entity_json(url=None)

Get the LOBID-JSON response of a given GND-URL.

:param url: A GND_URL :type url: str, optional

:raises: GNDNotFoundError, GNDAPIError :return: The matching JSON representation fetched from LOBID :rtype: dict

Source code in src/pylobid/pylobid.py
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
def get_entity_json(self, url: str = None) -> dict:
    """Get the LOBID-JSON response of a given GND-URL.

    :param url: A GND_URL
    :type url: str, optional

    :raises: GNDNotFoundError, GNDAPIError
    :return: The matching JSON representation fetched from LOBID
    :rtype: dict
    """
    url = self.gnd_url if url is None else self.get_entity_lobid_url(url)
    response = requests.get(url, headers={"Accept": "application/json"})
    if response.status_code == 404:
        raise GNDNotFoundError(
            f'Could not find a GND Entity for ID "{self.gnd_id}"'
        )
    if not response.ok:
        raise GNDAPIError(f"GND API error code: {response.status_code}")
    return response.json()

get_entity_lobid_url(url)

creates a lobid-entity URL from an GND-URL

:param url: A GND-URL, e.g. http://d-nb.info/gnd/118650130 :type url: str

:return: A LOBID-ENTITY-URL, e.g. http://lobid.org/gnd/116000562 :rtype: str

Source code in src/pylobid/pylobid.py
121
122
123
124
125
126
127
128
129
130
131
def get_entity_lobid_url(self, url: str) -> str:
    """creates a lobid-entity URL from an GND-URL

    :param url: A GND-URL, e.g. http://d-nb.info/gnd/118650130
    :type url: str

    :return: A LOBID-ENTITY-URL, e.g. http://lobid.org/gnd/116000562
    :rtype: str
    """
    self.__gnd_id = self.extract_id(url)
    return self.gnd_url

get_pref_name()

Get the preferred name.

:return: The preferred Name vale, e.g. 'Assmann, Richard' :rtype: str

Source code in src/pylobid/pylobid.py
164
165
166
167
168
169
170
171
def get_pref_name(self) -> str:
    """Get the preferred name.

    :return: The preferred Name vale, e.g. 'Assmann, Richard'
    :rtype: str
    """
    result = self.ent_dict.get("preferredName", "")
    return result

get_same_as()

Get the list of alternative norm-data-ids.

:return: A list of tuples like ('GeoNames', 'http://sws.geonames.org/2782067'), :rtype: list

Source code in src/pylobid/pylobid.py
153
154
155
156
157
158
159
160
161
162
def get_same_as(self) -> list:
    """Get the list of alternative norm-data-ids.

    :return: A list of tuples like ('GeoNames', 'http://sws.geonames.org/2782067'),
    :rtype: list
    """
    return [
        (x["collection"].get("abbr", "no_abbr"), x["id"])
        for x in self.ent_dict["sameAs"]
    ]

process_data(gnd_id=None, data=None)

Fetch and/or process entity data.

The arguments gnd_id and data are mutually exclusive.

:param gnd_id: any kind of GND_URI/URL :type gnd_id: str, optional :param data: an already fetched ent_dict :type data: dict, optional

Source code in src/pylobid/pylobid.py
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
def process_data(self, gnd_id: str = None, data: dict = None) -> None:
    """Fetch and/or process entity data.

    The arguments `gnd_id` and `data` are mutually exclusive.

    :param gnd_id: any kind of GND_URI/URL
    :type gnd_id: str, optional
    :param data: an already fetched ent_dict
    :type data: dict, optional
    """
    if data is not None and gnd_id is not None:
        raise ValueError("gnd_id and data mutually exclusive parameters")
    if data is not None and "id" in data:
        _ = self.get_entity_lobid_url(data.get("id"))
        self.ent_dict = data
    elif gnd_id is not None:
        _ = self.get_entity_lobid_url(gnd_id)
        self.ent_dict = self.get_entity_json()

PyLobidOrg

Bases: PyLobidClient

A python class representing an Organisation Entity.

Source code in src/pylobid/pylobid.py
255
256
257
258
259
260
261
262
263
264
class PyLobidOrg(PyLobidClient):
    """A python class representing an Organisation Entity."""

    @property
    def located_in(self) -> list:
        """Return a list of locations."""
        return self.ent_dict.get("placeOfBusiness", [])

    def __repr__(self) -> str:
        return f"<PyLobidOrg {self.gnd_url}>"

located_in property

Return a list of locations.

PyLobidPerson

Bases: PyLobidClient

A python class representing a Person Entity.

Source code in src/pylobid/pylobid.py
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
class PyLobidPerson(PyLobidClient):
    """A python class representing a Person Entity."""

    def get_life_dates(self) -> dict:
        """Get birth- and death dates.

        :return: A dict with keys birth_date_str and death_date_str
        :rtype: dict
        """
        return {
            "birth_date_str": next(iter(self.ent_dict.get("dateOfBirth", [])), ""),
            "death_date_str": next(iter(self.ent_dict.get("dateOfDeath", [])), ""),
        }

    def place_of_values(self, place_of: str = "Birth") -> dict:
        """Find values for PlaceOfBirth/Death.

        :param place_of: Passed in value concatenates to 'PlaceOfBirth|Death' \
        defaults to 'Birth'
        :type place_of: str

        :return: The ID of the Place
        :rtype: dict
        """
        value = f"placeOf{place_of}"
        result = self.ent_dict.get(value, False)
        return result[0] if isinstance(result, list) else {}

    def place_of_dict(self, place_of: str = "Birth") -> dict:
        """Get the LOBID-JSON of a PlaceOfBirth|Death (if present).

        :param place_of: Passed in value concatenates to 'PlaceOfBirth|Death' \
        defaults to 'Birth'
        :type place_of: str

        :return: The LOBID-JSON of the PlaceOfBirth|Death
        :rtype: dict
        """
        place_id = self.place_of_values(place_of).get("id")
        return {} if place_id is None else PyLobidPlace(place_id).ent_dict

    def get_coords_str(self, place_of: str = "Birth") -> str:
        """Get a string of coordinates.

        :param place_of: Passed in value concatenates to 'PlaceOfBirth|Death' \
        defaults to 'Birth'
        :type place_of: str

        :return: A string containing coordinates
        :rtype: str
        """
        place_of_key = "pylobid_born" if place_of == "Birth" else "pylobid_died"
        ent_dict = self.ent_dict.get(place_of_key, {})
        coords_str = f"{[match.value for match in self.coords_xpath.find(ent_dict)]}"
        return coords_str

    def get_coords(self, place_of: str = "Birth") -> list:
        """Get a list of coordinates.

        :param place_of: Passed in value concatenates to 'PlaceOfBirth|Death' \
        defaults to 'Birth'
        :type place_of: str

        :return: A list of longitude, latitude coords like ['+009.689780', '+051.210970']
        :rtype: list
        """
        coords_str = self.get_coords_str(place_of=place_of)
        return extract_coords(coords_str)

    def get_place_alt_name(self, place_of: str = "Birth") -> list:
        """Get the list of alternative names.

        :param place_of: Passed in value concatenates to 'PlaceOfBirth|Death' \
        defaults to 'Birth'
        :type place_of: str

        :return: a list of alternative names
        :rtype: list
        """
        place_of_key = "pylobid_born" if place_of == "Birth" else "pylobid_died"
        ent_dict = self.ent_dict.get(place_of_key, {})
        return next(
            iter([match.value for match in self.pref_alt_names_xpath.find(ent_dict)]),
            [],
        )

    def __str__(self) -> str:
        return self.gnd_url

    def __repr__(self) -> str:
        return f"<PyLobidPerson {self.gnd_url}>"

    def process_data(self, gnd_id: str = None, data: dict = None) -> None:
        """Fetch and/or process entity data.

        The arguments `gnd_id` and `data` are mutually exclusive.

        :param gnd_id: any kind of GND_URI/URL
        :type gnd_id: str, optional
        :param data: an already fetched ent_dict
        :type data: dict, optional
        """
        super().process_data(gnd_id=gnd_id, data=data)
        if self.ent_dict == {}:
            return
        if self.is_person:
            self.ent_dict.update(pylobid_born={}, pylobid_died={})
        self.pref_name_xpath = parse("$.preferredName")
        if self.fetch_related and self.is_person:
            self.ent_dict["pylobid_born"] = self.place_of_dict()
            if self.place_of_values().get("id", "") == self.place_of_values(
                place_of="Death"
            ).get("id", ""):
                self.ent_dict["pylobid_died"] = self.ent_dict["pylobid_born"]
            else:
                self.ent_dict["pylobid_died"] = self.place_of_dict(place_of="Death")

        self.birth_place = {
            "person_id": self.gnd_id,
            "name": self.place_of_values().get("label", ""),
            "id": self.place_of_values().get("id", ""),
            "coords": self.get_coords(),
            "alt_names": self.get_place_alt_name(),
        }
        self.death_place = {
            "person_id": self.gnd_id,
            "name": self.place_of_values(place_of="Death").get("label", ""),
            "id": self.place_of_values(place_of="Death").get("id", ""),
            "coords": self.get_coords(place_of="Death"),
            "alt_names": self.get_place_alt_name(place_of="Death"),
        }
        self.life_span = self.get_life_dates()

get_coords(place_of='Birth')

Get a list of coordinates.

:param place_of: Passed in value concatenates to 'PlaceOfBirth|Death' defaults to 'Birth' :type place_of: str

:return: A list of longitude, latitude coords like ['+009.689780', '+051.210970'] :rtype: list

Source code in src/pylobid/pylobid.py
377
378
379
380
381
382
383
384
385
386
387
388
def get_coords(self, place_of: str = "Birth") -> list:
    """Get a list of coordinates.

    :param place_of: Passed in value concatenates to 'PlaceOfBirth|Death' \
    defaults to 'Birth'
    :type place_of: str

    :return: A list of longitude, latitude coords like ['+009.689780', '+051.210970']
    :rtype: list
    """
    coords_str = self.get_coords_str(place_of=place_of)
    return extract_coords(coords_str)

get_coords_str(place_of='Birth')

Get a string of coordinates.

:param place_of: Passed in value concatenates to 'PlaceOfBirth|Death' defaults to 'Birth' :type place_of: str

:return: A string containing coordinates :rtype: str

Source code in src/pylobid/pylobid.py
362
363
364
365
366
367
368
369
370
371
372
373
374
375
def get_coords_str(self, place_of: str = "Birth") -> str:
    """Get a string of coordinates.

    :param place_of: Passed in value concatenates to 'PlaceOfBirth|Death' \
    defaults to 'Birth'
    :type place_of: str

    :return: A string containing coordinates
    :rtype: str
    """
    place_of_key = "pylobid_born" if place_of == "Birth" else "pylobid_died"
    ent_dict = self.ent_dict.get(place_of_key, {})
    coords_str = f"{[match.value for match in self.coords_xpath.find(ent_dict)]}"
    return coords_str

get_life_dates()

Get birth- and death dates.

:return: A dict with keys birth_date_str and death_date_str :rtype: dict

Source code in src/pylobid/pylobid.py
324
325
326
327
328
329
330
331
332
333
def get_life_dates(self) -> dict:
    """Get birth- and death dates.

    :return: A dict with keys birth_date_str and death_date_str
    :rtype: dict
    """
    return {
        "birth_date_str": next(iter(self.ent_dict.get("dateOfBirth", [])), ""),
        "death_date_str": next(iter(self.ent_dict.get("dateOfDeath", [])), ""),
    }

get_place_alt_name(place_of='Birth')

Get the list of alternative names.

:param place_of: Passed in value concatenates to 'PlaceOfBirth|Death' defaults to 'Birth' :type place_of: str

:return: a list of alternative names :rtype: list

Source code in src/pylobid/pylobid.py
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
def get_place_alt_name(self, place_of: str = "Birth") -> list:
    """Get the list of alternative names.

    :param place_of: Passed in value concatenates to 'PlaceOfBirth|Death' \
    defaults to 'Birth'
    :type place_of: str

    :return: a list of alternative names
    :rtype: list
    """
    place_of_key = "pylobid_born" if place_of == "Birth" else "pylobid_died"
    ent_dict = self.ent_dict.get(place_of_key, {})
    return next(
        iter([match.value for match in self.pref_alt_names_xpath.find(ent_dict)]),
        [],
    )

place_of_dict(place_of='Birth')

Get the LOBID-JSON of a PlaceOfBirth|Death (if present).

:param place_of: Passed in value concatenates to 'PlaceOfBirth|Death' defaults to 'Birth' :type place_of: str

:return: The LOBID-JSON of the PlaceOfBirth|Death :rtype: dict

Source code in src/pylobid/pylobid.py
349
350
351
352
353
354
355
356
357
358
359
360
def place_of_dict(self, place_of: str = "Birth") -> dict:
    """Get the LOBID-JSON of a PlaceOfBirth|Death (if present).

    :param place_of: Passed in value concatenates to 'PlaceOfBirth|Death' \
    defaults to 'Birth'
    :type place_of: str

    :return: The LOBID-JSON of the PlaceOfBirth|Death
    :rtype: dict
    """
    place_id = self.place_of_values(place_of).get("id")
    return {} if place_id is None else PyLobidPlace(place_id).ent_dict

place_of_values(place_of='Birth')

Find values for PlaceOfBirth/Death.

:param place_of: Passed in value concatenates to 'PlaceOfBirth|Death' defaults to 'Birth' :type place_of: str

:return: The ID of the Place :rtype: dict

Source code in src/pylobid/pylobid.py
335
336
337
338
339
340
341
342
343
344
345
346
347
def place_of_values(self, place_of: str = "Birth") -> dict:
    """Find values for PlaceOfBirth/Death.

    :param place_of: Passed in value concatenates to 'PlaceOfBirth|Death' \
    defaults to 'Birth'
    :type place_of: str

    :return: The ID of the Place
    :rtype: dict
    """
    value = f"placeOf{place_of}"
    result = self.ent_dict.get(value, False)
    return result[0] if isinstance(result, list) else {}

process_data(gnd_id=None, data=None)

Fetch and/or process entity data.

The arguments gnd_id and data are mutually exclusive.

:param gnd_id: any kind of GND_URI/URL :type gnd_id: str, optional :param data: an already fetched ent_dict :type data: dict, optional

Source code in src/pylobid/pylobid.py
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
def process_data(self, gnd_id: str = None, data: dict = None) -> None:
    """Fetch and/or process entity data.

    The arguments `gnd_id` and `data` are mutually exclusive.

    :param gnd_id: any kind of GND_URI/URL
    :type gnd_id: str, optional
    :param data: an already fetched ent_dict
    :type data: dict, optional
    """
    super().process_data(gnd_id=gnd_id, data=data)
    if self.ent_dict == {}:
        return
    if self.is_person:
        self.ent_dict.update(pylobid_born={}, pylobid_died={})
    self.pref_name_xpath = parse("$.preferredName")
    if self.fetch_related and self.is_person:
        self.ent_dict["pylobid_born"] = self.place_of_dict()
        if self.place_of_values().get("id", "") == self.place_of_values(
            place_of="Death"
        ).get("id", ""):
            self.ent_dict["pylobid_died"] = self.ent_dict["pylobid_born"]
        else:
            self.ent_dict["pylobid_died"] = self.place_of_dict(place_of="Death")

    self.birth_place = {
        "person_id": self.gnd_id,
        "name": self.place_of_values().get("label", ""),
        "id": self.place_of_values().get("id", ""),
        "coords": self.get_coords(),
        "alt_names": self.get_place_alt_name(),
    }
    self.death_place = {
        "person_id": self.gnd_id,
        "name": self.place_of_values(place_of="Death").get("label", ""),
        "id": self.place_of_values(place_of="Death").get("id", ""),
        "coords": self.get_coords(place_of="Death"),
        "alt_names": self.get_place_alt_name(place_of="Death"),
    }
    self.life_span = self.get_life_dates()

PyLobidPlace

Bases: PyLobidClient

A python class representing a Place Entity.

Source code in src/pylobid/pylobid.py
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
class PyLobidPlace(PyLobidClient):
    """A python class representing a Place Entity."""

    def get_coords_str(self) -> str:
        """Get a string of coordinates.

        :return: A string containing coordinates
        :rtype: str
        """
        coords_str = (
            f"{[match.value for match in self.coords_xpath.find(self.ent_dict)]}"
        )
        return coords_str

    def get_coords(self) -> list:
        """Get a list of coordinates.

        :return: A list of longitude, latitude coords like ['+009.689780', '+051.210970']
        :rtype: list
        """
        coords_str = self.get_coords_str()
        return extract_coords(coords_str)

    @property
    def coords(self) -> list:
        """Return a list of coordinates."""
        return self.get_coords()

    def __repr__(self) -> str:
        return f"<PyLobidPlace {self.gnd_url}>"

coords property

Return a list of coordinates.

get_coords()

Get a list of coordinates.

:return: A list of longitude, latitude coords like ['+009.689780', '+051.210970'] :rtype: list

Source code in src/pylobid/pylobid.py
237
238
239
240
241
242
243
244
def get_coords(self) -> list:
    """Get a list of coordinates.

    :return: A list of longitude, latitude coords like ['+009.689780', '+051.210970']
    :rtype: list
    """
    coords_str = self.get_coords_str()
    return extract_coords(coords_str)

get_coords_str()

Get a string of coordinates.

:return: A string containing coordinates :rtype: str

Source code in src/pylobid/pylobid.py
226
227
228
229
230
231
232
233
234
235
def get_coords_str(self) -> str:
    """Get a string of coordinates.

    :return: A string containing coordinates
    :rtype: str
    """
    coords_str = (
        f"{[match.value for match in self.coords_xpath.find(self.ent_dict)]}"
    )
    return coords_str

PyLobidWork

Bases: PyLobidClient

A python class representing a Work Entity

Source code in src/pylobid/pylobid.py
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
class PyLobidWork(PyLobidClient):
    """A python class representing a Work Entity"""

    @property
    def creators(self) -> list:
        """provides a list of dicts providing information of all persons
        involved in the creation of the work and their role

        Returns:
            list: _description_
        """
        creators = []
        for y in ["firstAuthor", "author", "firstComposer", "librettist"]:
            for x in self.ent_dict.get(y, []):
                x["role"] = y
                creators.append(x)
        return creators

    @property
    def date_of_creation(self) -> str:
        """returns the date of the works creations using `dateOfPublication`
        if `dateOfPublication` is not provided `dateOfProduction` is used

        Returns:
            str: the prodcution or publication date of the work
        """
        date = ""
        for x in ["dateOfPublication", "dateOfProduction"]:
            try:
                date = self.ent_dict[x][0]
                break
            except (KeyError, IndexError):
                continue
        return date

    @property
    def date_of_production(self) -> str:
        """returns the date of the works creations using `dateOfProduction`

        Returns:
            str: the prodcution date of the work
        """
        return self.ent_dict.get("dateOfProduction", [""])[0]

    @property
    def date_of_publication(self) -> str:
        """returns the date of the works creations using `dateOfPublication`

        Returns:
            str: the publication date of the work
        """
        return self.ent_dict.get("dateOfPublication", [""])[0]

creators property

provides a list of dicts providing information of all persons involved in the creation of the work and their role

Returns:
  • list( list ) –

    description

date_of_creation property

returns the date of the works creations using dateOfPublication if dateOfPublication is not provided dateOfProduction is used

Returns:
  • str( str ) –

    the prodcution or publication date of the work

date_of_production property

returns the date of the works creations using dateOfProduction

Returns:
  • str( str ) –

    the prodcution date of the work

date_of_publication property

returns the date of the works creations using dateOfPublication

Returns:
  • str( str ) –

    the publication date of the work

pylobid.utils

some (one) utility function

extract_coords(some_str)

Utility function to extract coordinates from a (WKT) string

:param some_str: A string providing coordinates :type some_str: str

:return: A list with the coordinates :rtype: list

Source code in src/pylobid/utils.py
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
def extract_coords(some_str: str) -> list:
    """Utility function to extract coordinates from a (WKT) string

    :param some_str: A string providing coordinates
    :type some_str: str

    :return: A list with the coordinates
    :rtype: list

    """
    regex = r"[+|-]\d+(?:\.\d*)?"
    matches = re.findall(regex, some_str, re.MULTILINE)
    return matches

pylobid.validators

WTForms GND validator module.

WTForms GND validator module.

GNDOrgEntity

Bases: GNDValidator

Validator for org. entities.

:param: Message to display if validation fails. :raises: ValidationError is the GND type does not match the set entity type.

Source code in src/pylobid/validators.py
74
75
76
77
78
79
80
81
82
83
84
class GNDOrgEntity(GNDValidator):
    """Validator for org. entities.

    :param: Message to display if validation fails.
    :raises: ValidationError is the GND type does not match the set entity type.
    """

    def __init__(self, message: str = None) -> None:
        """Class constructor."""
        super().__init__(entity_flag="is_org", message=message)
        self.message = message or "The provided GND ID is not an organization entity"

__init__(message=None)

Class constructor.

Source code in src/pylobid/validators.py
81
82
83
84
def __init__(self, message: str = None) -> None:
    """Class constructor."""
    super().__init__(entity_flag="is_org", message=message)
    self.message = message or "The provided GND ID is not an organization entity"

GNDPersonEntity

Bases: GNDValidator

Validator class for person entities.

:param: Message to display if validation fails. :raises: ValidationError is the GND type does not match the set entity type.

Source code in src/pylobid/validators.py
61
62
63
64
65
66
67
68
69
70
71
class GNDPersonEntity(GNDValidator):
    """Validator class for person entities.

    :param: Message to display if validation fails.
    :raises: ValidationError is the GND type does not match the set entity type.
    """

    def __init__(self, message: str = None) -> None:
        """Class constructor."""
        super().__init__(entity_flag="is_person")
        self.message = message or "The provided GND ID is not a person entity"

__init__(message=None)

Class constructor.

Source code in src/pylobid/validators.py
68
69
70
71
def __init__(self, message: str = None) -> None:
    """Class constructor."""
    super().__init__(entity_flag="is_person")
    self.message = message or "The provided GND ID is not a person entity"

GNDPlaceEntity

Bases: GNDValidator

Validator class for place entities.

:param: Message to display if validation fails. :raises: ValidationError is the GND type does not match the set entity type.

Source code in src/pylobid/validators.py
48
49
50
51
52
53
54
55
56
57
58
class GNDPlaceEntity(GNDValidator):
    """Validator class for place entities.

    :param: Message to display if validation fails.
    :raises: ValidationError is the GND type does not match the set entity type.
    """

    def __init__(self, message: str = None) -> None:
        """Class constructor."""
        super().__init__(entity_flag="is_place")
        self.message = message or "The provided GND ID is not a place entity"

__init__(message=None)

Class constructor.

Source code in src/pylobid/validators.py
55
56
57
58
def __init__(self, message: str = None) -> None:
    """Class constructor."""
    super().__init__(entity_flag="is_place")
    self.message = message or "The provided GND ID is not a place entity"

GNDValidator

Base class for GND validators.

:param: Message to display if validation fails. :raises: ValidationError is the GND type does not match the set entity type.

Source code in src/pylobid/validators.py
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
class GNDValidator:
    """Base class for GND validators.

    :param: Message to display if validation fails.
    :raises: ValidationError is the GND type does not match the set entity type.
    """

    def __init__(self, entity_flag: str = None, message: str = None) -> None:
        """Class constructor."""
        self.entity_flag = entity_flag
        self.message = message

    def __call__(self, form: wtforms.form.Form, field: GNDWTFormsFields) -> None:
        """Class call method.

        :param form: A WTForms Form instance.
        :param field: A WTForm Form Field instance.
        :raises: ValidationError is the GND type does not match the set entity type.
        """
        try:
            gnd_entity = pylobid.PyLobidClient(field.data).factory()
        except pylobid.GNDIdError as error:
            raise wtforms.validators.ValidationError(
                f"{field.data} is not a valid GND Id/URL"
            ) from error
        except pylobid.GNDNotFoundError as error:
            raise wtforms.validators.ValidationError(error) from error
        if not gnd_entity.ent_type:
            raise wtforms.validators.ValidationError(
                f"Unknown GND type for {gnd_entity.gnd_url}"
            )
        if self.entity_flag is not None and not getattr(
            gnd_entity, self.entity_flag, False
        ):
            self.message = f"Entity type {gnd_entity.ent_type}"
            raise wtforms.validators.ValidationError(self.message)

__call__(form, field)

Class call method.

:param form: A WTForms Form instance. :param field: A WTForm Form Field instance. :raises: ValidationError is the GND type does not match the set entity type.

Source code in src/pylobid/validators.py
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
def __call__(self, form: wtforms.form.Form, field: GNDWTFormsFields) -> None:
    """Class call method.

    :param form: A WTForms Form instance.
    :param field: A WTForm Form Field instance.
    :raises: ValidationError is the GND type does not match the set entity type.
    """
    try:
        gnd_entity = pylobid.PyLobidClient(field.data).factory()
    except pylobid.GNDIdError as error:
        raise wtforms.validators.ValidationError(
            f"{field.data} is not a valid GND Id/URL"
        ) from error
    except pylobid.GNDNotFoundError as error:
        raise wtforms.validators.ValidationError(error) from error
    if not gnd_entity.ent_type:
        raise wtforms.validators.ValidationError(
            f"Unknown GND type for {gnd_entity.gnd_url}"
        )
    if self.entity_flag is not None and not getattr(
        gnd_entity, self.entity_flag, False
    ):
        self.message = f"Entity type {gnd_entity.ent_type}"
        raise wtforms.validators.ValidationError(self.message)

__init__(entity_flag=None, message=None)

Class constructor.

Source code in src/pylobid/validators.py
17
18
19
20
def __init__(self, entity_flag: str = None, message: str = None) -> None:
    """Class constructor."""
    self.entity_flag = entity_flag
    self.message = message