Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add search APIs #14

Merged
merged 8 commits into from
Dec 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 35 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,25 +30,49 @@ python3 -m pip install brreg
- [Issue tracker](https://github.com/jodal/python-brreg/issues)
- [Contributors](https://github.com/jodal/python-brreg/graphs/contributors)

## Development status
## Features

This project was originally developed in 2019 while I worked at Otovo.
Eventually, it was never used there, and at the end of 2023, I got the project
back under my control.
### Enhetsregistret

I intend to brush the project up with modern project tooling and typing hints,
making it a good foundation to build upon, and will release a 1.0 release as
soon as that is done.
The `brreg.enhetsregisteret` part of this library wraps the open
[Enhetsregistret API](https://data.brreg.no/enhetsregisteret/api/docs/index.html).

This is a list of all features this library could implement on top of this API.
However, I will not attempt to make the project cover all parts of
Brønnøysundregisterene's API. I am open to requests, so that time is spent
on the parts of the API that there is an actual demand for.
Brønnøysundregisterene's API. I am open to requests, so that time is spent on
the parts of the API that there is an actual demand for.

- Enheter
- Search -- Implemented
- Get one by organization number -- Implemented
- Get one's roles by organization number -- Planned
- Get all updates since given time -- Request if needed
- Underenheter
- Search -- Implemented
- Get one by organization number -- Implemented
- Get all updates since given time -- Request if needed
- Organisasjonsform
- Get all -- Request if needed
- Rolletype
- Get all -- Request if needed
- Get one -- Request if needed
- Rollegrupetype
- Get all -- Request if needed
- Get one -- Request if needed
- Representant
- Get all -- Request if needed
- Get one -- Request if needed
- Kommuner
- Get all -- Request if needed
- Matrikkelenhet
- Get one by matrikkelnummer -- Request if needed
- Get one by matrikkelenhet-ID -- Request if needed

## License

`python-brreg` is copyright
Copyright
2019 [Otovo ASA](https://www.otovo.com/),
2023 Stein Magnus Jodal and contributors.

`python-brreg` is licensed under the
Licensed under the
[Apache License, Version 2.0](https://www.apache.org/licenses/LICENSE-2.0).
39 changes: 36 additions & 3 deletions docs/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,44 @@ Exceptions
Enhetsregisteret
================

.. automodule:: brreg.enhetsregisteret
.. module:: brreg.enhetsregisteret

Client
------

.. autoclass:: brreg.enhetsregisteret.Client
:members:

Query objects
-------------

.. autoclass:: brreg.enhetsregisteret.Query
:members:
:exclude-members: model_config, model_fields

.. autoclass:: brreg.enhetsregisteret.EnhetQuery
:members:
:exclude-members: model_config, model_fields

.. autoclass:: brreg.enhetsregisteret.UnderenhetQuery
:members:
:exclude-members: model_config, model_fields

Response objects
----------------

.. autoclass:: brreg.enhetsregisteret.Page
:members:
:exclude-members: model_config, model_fields

.. autoclass:: brreg.enhetsregisteret.EnhetPage
:members:
:exclude-members: model_config, model_fields

.. autoclass:: brreg.enhetsregisteret.UnderenhetPage
:members:
:exclude-members: model_config, model_fields

.. autoclass:: brreg.enhetsregisteret.Enhet
:members:
:exclude-members: model_config, model_fields
Expand All @@ -37,11 +70,11 @@ Enhetsregisteret
:members:
:exclude-members: model_config, model_fields

.. autoclass:: brreg.enhetsregisteret.InstitusjonellSektorkode
.. autoclass:: brreg.enhetsregisteret.InstitusjonellSektor
:members:
:exclude-members: model_config, model_fields

.. autoclass:: brreg.enhetsregisteret.Naeringskode
.. autoclass:: brreg.enhetsregisteret.Naering
:members:
:exclude-members: model_config, model_fields

Expand Down
41 changes: 35 additions & 6 deletions src/brreg/enhetsregisteret/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,52 @@
"""

from brreg.enhetsregisteret._client import Client
from brreg.enhetsregisteret._types import (
from brreg.enhetsregisteret._pagination import EnhetPage, Page, UnderenhetPage
from brreg.enhetsregisteret._queries import EnhetQuery, Query, UnderenhetQuery
from brreg.enhetsregisteret._responses import (
Adresse,
Enhet,
InstitusjonellSektorkode,
Naeringskode,
InstitusjonellSektor,
Naering,
Organisasjonsform,
Underenhet,
)
from brreg.enhetsregisteret._types import (
Kommunenummer,
KommunenummerValidator,
Organisasjonsnummer,
OrganisasjonsnummerValidator,
Postnummer,
PostnummerValidator,
Sektorkode,
SektorkodeValidator,
)

__all__ = [
# From _client module:
"Client",
# From _types module:
# From _pagination module:
"EnhetPage",
"Page",
"UnderenhetPage",
# From _queries module:
"EnhetQuery",
"Query",
"UnderenhetQuery",
# From _responses module:
"Adresse",
"Enhet",
"InstitusjonellSektorkode",
"Naeringskode",
"InstitusjonellSektor",
"Naering",
"Organisasjonsform",
"Underenhet",
# From _types module:
"Kommunenummer",
"KommunenummerValidator",
"Organisasjonsnummer",
"OrganisasjonsnummerValidator",
"Postnummer",
"PostnummerValidator",
"Sektorkode",
"SektorkodeValidator",
]
63 changes: 60 additions & 3 deletions src/brreg/enhetsregisteret/_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,18 @@
import httpx

from brreg import BrregError, BrregRestError
from brreg.enhetsregisteret._types import Enhet, Underenhet
from brreg.enhetsregisteret._pagination import EnhetPage, UnderenhetPage
from brreg.enhetsregisteret._responses import Enhet, Underenhet
from brreg.enhetsregisteret._types import (
Organisasjonsnummer,
OrganisasjonsnummerValidator,
)

if TYPE_CHECKING:
from types import TracebackType

from brreg.enhetsregisteret._queries import EnhetQuery, UnderenhetQuery


class Client:
"""Client for the Enhetregisteret API.
Expand Down Expand Up @@ -61,8 +68,12 @@ def close(self) -> None:
"""
self._client.close()

def get_enhet(self, organisasjonsnummer: str) -> Optional[Enhet]:
def get_enhet(
self,
organisasjonsnummer: Organisasjonsnummer,
) -> Optional[Enhet]:
"""Get :class:`Enhet` given an organization number."""
OrganisasjonsnummerValidator.validate_python(organisasjonsnummer)
with error_handler():
res = self._client.get(
f"/enheter/{organisasjonsnummer}",
Expand All @@ -78,8 +89,12 @@ def get_enhet(self, organisasjonsnummer: str) -> Optional[Enhet]:
res.raise_for_status()
return Enhet.model_validate_json(res.content)

def get_underenhet(self, organisasjonsnummer: str) -> Optional[Underenhet]:
def get_underenhet(
self,
organisasjonsnummer: Organisasjonsnummer,
) -> Optional[Underenhet]:
"""Get :class:`Underenhet` given an organization number."""
OrganisasjonsnummerValidator.validate_python(organisasjonsnummer)
with error_handler():
res = self._client.get(
f"/underenheter/{organisasjonsnummer}",
Expand All @@ -95,6 +110,48 @@ def get_underenhet(self, organisasjonsnummer: str) -> Optional[Underenhet]:
res.raise_for_status()
return Underenhet.model_validate_json(res.content)

def search_enhet(
self,
query: EnhetQuery,
) -> EnhetPage:
"""Search for :class:`Enhet` that matches the given query.

:param query: The search query.
"""
with error_handler():
res = self._client.get(
f"/enheter?{query.as_url_query()}",
headers={
"accept": (
"application/vnd.brreg.enhetsregisteret.enhet.v2+json;"
"charset=UTF-8"
)
},
)
res.raise_for_status()
return EnhetPage.model_validate_json(res.content)

def search_underenhet(
self,
query: UnderenhetQuery,
) -> UnderenhetPage:
"""Search for :class:`Underenhet` that matches the given query.

:param query: The search query.
"""
with error_handler():
res = self._client.get(
f"/underenheter?{query.as_url_query()}",
headers={
"accept": (
"application/vnd.brreg.enhetsregisteret.underenhet.v2+json;"
"charset=UTF-8"
)
},
)
res.raise_for_status()
return UnderenhetPage.model_validate_json(res.content)


@contextmanager
def error_handler() -> Generator[None, Any, None]:
Expand Down
60 changes: 60 additions & 0 deletions src/brreg/enhetsregisteret/_pagination.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
from typing import Generic, List, TypeVar

from pydantic import (
AliasPath,
BaseModel,
Field,
)

from brreg.enhetsregisteret._responses import Enhet, Underenhet

__all__ = [
"EnhetPage",
"UnderenhetPage",
]


T = TypeVar("T", bound=BaseModel)


class Page(BaseModel, Generic[T]):
"""The fields here are available on all page objects."""

#: The items on this page.
items: List[T]

#: The number of elements on this page.
page_size: int = Field(
validation_alias=AliasPath("page", "size"),
)

#: The page number, starting at 0.
page_number: int = Field(
validation_alias=AliasPath("page", "number"),
)

#: The total number of elements available.
total_elements: int = Field(
validation_alias=AliasPath("page", "totalElements"),
)

#: The total number of pages available.
total_pages: int = Field(
validation_alias=AliasPath("page", "totalPages"),
)


class EnhetPage(Page[Enhet]):
"""Response type for enhet search."""

items: List[Enhet] = Field(
validation_alias=AliasPath("_embedded", "enheter"),
)


class UnderenhetPage(Page[Underenhet]):
"""Response type for underenhet search."""

items: List[Underenhet] = Field(
validation_alias=AliasPath("_embedded", "underenheter"),
)
Loading