Skip to content

Commit 621991d

Browse files
committed
feat!: set up resources
1 parent aa780b2 commit 621991d

File tree

22 files changed

+3582
-123
lines changed

22 files changed

+3582
-123
lines changed

.pre-commit-config.yaml

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,15 @@ repos:
6060
hooks:
6161
- id: mdformat
6262
args: [--number, --wrap=120, --ignore-missing-references]
63-
exclude: CHANGELOG.md|.changelog.md|docs/src/cli.md|docs/src/exceptions.md
63+
exclude: |
64+
(?x)^(
65+
CHANGELOG.md|
66+
.changelog.md|
67+
docs/src/api.md|
68+
docs/src/cli.md|
69+
docs/src/exceptions.md|
70+
docs/src/resources.md
71+
)$
6472
additional_dependencies:
6573
- mdformat-mkdocs[recommended]>=v2.0.7
6674

@@ -81,6 +89,7 @@ repos:
8189
- pytest>=8.2
8290
- respx>=0.21
8391
- typer>=0.12
92+
- xsdata>=24.5
8493

8594
- repo: https://github.com/scientific-python/cookie
8695
rev: 28d1a53da26f9daff6d9a49c50260421ad6d05e0 # frozen: 2024.04.23
@@ -92,7 +101,7 @@ repos:
92101
hooks:
93102
- id: typos
94103
args: [--force-exclude]
95-
exclude: tests/conftest
104+
exclude: src/re3data/_resources/repository.py|tests/conftest.py
96105

97106
- repo: https://github.com/FHPythonUtils/LicenseCheck/
98107
rev: b2b50f4d40c95b15478279a7a00553a1dc2925ef # frozen: 2024.2

README.md

Lines changed: 18 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -18,28 +18,15 @@ metadata about research data repositories in a convenient and Pythonic way.
1818
```pycon
1919
>>> import re3data
2020
>>> response = re3data.repositories.list()
21-
>>> print(response)
22-
<?xml version="1.0" encoding="UTF-8"?>
23-
<list>
24-
<repository>
25-
<id>r3d100010468</id>
26-
<doi>https://doi.org/10.17616/R3QP53</doi>
27-
<name>Zenodo</name>
28-
<link href="https://www.re3data.org/api/beta/repository/r3d100010468" rel="self" />
29-
</repository>
21+
>>> response
22+
[RepositorySummary(id='r3d100010468', doi='https://doi.org/10.17616/R3QP53', name='Zenodo', link=Link(href='https://www.re3data.org/api/beta/repository/r3d100010468', rel='self'))]
3023
... (remaining repositories truncated)
3124
```
3225

3326
```pycon
3427
>>> response = re3data.repositories.get("r3d100010468")
35-
>>> print(response)
36-
<?xml version="1.0" encoding="utf-8"?>
37-
<!--re3data.org Schema for the Description of Research Data Repositories. Version 2.2, December 2014. doi:10.2312/re3.006-->
38-
<r3d:re3data xmlns:r3d="http://www.re3data.org/schema/2-2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.re3data.org/schema/2-2 http://schema.re3data.org/2-2/re3dataV2-2.xsd">
39-
<r3d:repository>
40-
<r3d:re3data.orgIdentifier>r3d100010468</r3d:re3data.orgIdentifier>
41-
<r3d:repositoryName language="eng">Zenodo</r3d:repositoryName>
42-
<r3d:repositoryURL>https://zenodo.org/</r3d:repositoryURL>
28+
>>> response
29+
Repository(re3data_org_identifier='r3d100010468', repository_name=RepositoryName(value='Zenodo', language=<Languages.ENG: 'eng'>), additional_name=[], repository_url='https://zenodo.org/', repository_identifier=['FAIRsharing_doi:10.25504/FAIRsharing.wy4egf', 'RRID:SCR_004129', 'RRID:nlx_158614'])
4330
... (remaining fields truncated)
4431
```
4532

@@ -51,15 +38,27 @@ metadata about research data repositories in a convenient and Pythonic way.
5138
`re3data.repositories.list()`.
5239
- Repository details retrieval: Get detailed information about a specific repository using
5340
`re3data.repositories.get(repository_id)`.
41+
- XML response parsers: API XML responses are parsed into Python dataclasses, providing convenient access to the
42+
elements of the [re3data.org Schema](https://www.re3data.org/schema/2-2). This makes it easy to work with the rich
43+
metadata provided by the API.
44+
- Flexible response options: The response type can be switched between:
45+
- dataclass (default): Returns a Python dataclass object, allowing convenient access to the element of the re3data
46+
schema
47+
- response: Returns a Python object representing the API response
48+
- original XML: Returns the raw XML response from the API
5449

5550
## Requirements
5651

5752
[Python](https://www.python.org/downloads/) >= 3.10
5853

5954
`python-re3data` is built with:
6055

61-
- [httpx](https://github.com/encode/httpx) for issuing HTTP requests
62-
- [typer](https://github.com/tiangolo/typer) for its CLI
56+
- **HTTP Requests**: [httpx](https://github.com/encode/httpx), a modern and efficient HTTP client library, handles all
57+
API interactions.
58+
- **XML Parsing**: [xsdata](https://github.com/tefra/xsdata), a powerful tool for generating Python dataclasses from XML
59+
schemas, simplifies processing of API responses.
60+
- **Optional CLI**: [typer](https://github.com/tiangolo/typer), a popular library for building command-line interfaces,
61+
powers the user-friendly command-line interface (CLI).
6362

6463
## Installation
6564

docs/mkdocs.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ nav:
1717
- Home: index.md
1818
- Reference:
1919
- API Reference: api.md
20+
- Resources: resources.md
2021
- Exceptions: exceptions.md
2122
- Command Line Interface: cli.md
2223
- Meta:

docs/src/api.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,17 @@
11
# API Reference
22

3+
## `BaseClient`
4+
5+
::: re3data._client.BaseClient
6+
37
## `Client`
48

59
::: re3data.Client
10+
11+
## `RepositoryManager`
12+
13+
::: re3data._client.RepositoryManager
14+
15+
## `Response`
16+
17+
::: re3data.Response

docs/src/resources.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
::: re3data._resources

pyproject.toml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ dynamic = [
4343
]
4444
dependencies = [
4545
"httpx>=0.27",
46+
"xsdata>=24.5",
4647
]
4748
optional-dependencies.cli = [
4849
"typer>=0.12",
@@ -78,8 +79,13 @@ scripts.re3data = "re3data.__main__:app"
7879
only-include = [
7980
"src/re3data",
8081
]
82+
exclude = [
83+
"src/re3data/_resources/*.md",
84+
"src/re3data/_resources/*.xml",
85+
]
8186

8287
[tool.hatch.build.targets.wheel]
88+
only-packages = true
8389
packages = [
8490
"src/re3data",
8591
]
@@ -172,6 +178,13 @@ lint.ignore = [
172178
lint.per-file-ignores."src/re3data/__about__.py" = [
173179
"D100", # undocumented-public-module
174180
]
181+
lint.per-file-ignores."src/re3data/_resources/*" = [
182+
"D101", # undocumented-public-class
183+
"D106", # undocumented-public-nested-class
184+
"D205", # blank-line-after-summary
185+
"D415", # ends-in-punctuation
186+
"TCH002", # typing-only-third-party-import
187+
]
175188
lint.per-file-ignores."tests/*" = [
176189
"D100", # undocumented-public-module
177190
"D103", # undocumented-public-function
@@ -225,6 +238,7 @@ omit = [
225238
exclude_also = [
226239
"if TYPE_CHECKING:",
227240
"@abstractmethod",
241+
"@overload",
228242
]
229243
fail_under = 90
230244
show_missing = true

requirements/docs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
# This file is autogenerated by hatch-pip-compile with Python 3.12
33
#
44
# - httpx>=0.27
5+
# - xsdata>=24.5
56
# - typer>=0.12
67
# - mike~=2.1
78
# - mkdocs-include-markdown-plugin~=6.0
@@ -536,7 +537,9 @@ typer==0.12.3 \
536537
typing-extensions==4.12.0 \
537538
--hash=sha256:8cbcdc8606ebcb0d95453ad7dc5065e6237b6aa230a31e81d0f440c30fed5fd8 \
538539
--hash=sha256:b349c66bea9016ac22978d800cfff206d5f9816951f12a7d0ec5578b0a819594
539-
# via typer
540+
# via
541+
# typer
542+
# xsdata
540543
urllib3==2.2.1 \
541544
--hash=sha256:450b20ec296a467077128bff42b73080516e71b56ff59a60a02bef2232c4fa9d \
542545
--hash=sha256:d0570876c61ab9e520d776c38acbbb5b05a776d3f9ff98a5c8fd5162a444cf19
@@ -583,6 +586,10 @@ wcmatch==8.5.2 \
583586
--hash=sha256:17d3ad3758f9d0b5b4dedc770b65420d4dac62e680229c287bf24c9db856a478 \
584587
--hash=sha256:a70222b86dea82fb382dd87b73278c10756c138bd6f8f714e2183128887b9eb2
585588
# via mkdocs-include-markdown-plugin
589+
xsdata==24.5 \
590+
--hash=sha256:4e8414a01bff603ca38a361d04d819934fcc525f9b4220f0076e040d84a4a963 \
591+
--hash=sha256:6ff12949083d9a0d9934c50401b347ccbf254bb10bf8472aef956b92662f7858
592+
# via hatch.envs.docs
586593
zipp==3.19.0 \
587594
--hash=sha256:952df858fb3164426c976d9338d3961e8e8b3758e2e059e0f754b8c4262625ee \
588595
--hash=sha256:96dc6ad62f1441bcaccef23b274ec471518daf4fbbc580341204936a5a3dddec

src/re3data/__init__.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,22 @@
55
"""python-re3data."""
66

77
from re3data.__about__ import __version__
8-
from re3data._client import Client
8+
from re3data._client import Client, ReturnType
99
from re3data._exceptions import Re3dataError, RepositoryNotFoundError
10+
from re3data._resources import Re3Data, Repository, RepositoryList, RepositorySummary
11+
from re3data._response import Response
1012

1113
__all__ = [
12-
"__version__",
1314
"Client",
15+
"Re3Data",
1416
"Re3dataError",
17+
"Repository",
18+
"RepositoryList",
1519
"RepositoryNotFoundError",
20+
"RepositorySummary",
21+
"Response",
22+
"ReturnType",
23+
"__version__",
1624
]
1725

1826
_client = Client()

src/re3data/_cli.py

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
import re3data
1414
from re3data._client import ReturnType
15+
from re3data._exceptions import RepositoryNotFoundError
1516

1617
logger = logging.getLogger(__name__)
1718

@@ -69,14 +70,18 @@ def callback(
6970

7071

7172
@repositories_app.command("list")
72-
def list_repositories(return_type: ReturnType = ReturnType.xml) -> None:
73+
def list_repositories(return_type: ReturnType = ReturnType.DATACLASS) -> None:
7374
"""List the metadata of all repositories in the re3data API."""
74-
response = re3data.repositories.list(return_type=return_type.value)
75+
response = re3data.repositories.list(return_type)
7576
console.print(response)
7677

7778

7879
@repositories_app.command("get")
79-
def get_repository(repository_id: str, return_type: ReturnType = ReturnType.xml) -> None:
80+
def get_repository(repository_id: str, return_type: ReturnType = ReturnType.DATACLASS) -> None:
8081
"""Get the metadata of a specific repository."""
81-
response = re3data.repositories.get(repository_id, return_type=return_type.value)
82-
console.print(response)
82+
try:
83+
response = re3data.repositories.get(repository_id, return_type)
84+
console.print(response)
85+
except RepositoryNotFoundError as error:
86+
print_error(str(error))
87+
raise typer.Exit(code=1) from error

0 commit comments

Comments
 (0)