athena-client 1.0.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- athena_client-1.0.4/PKG-INFO +198 -0
- athena_client-1.0.4/README.md +146 -0
- athena_client-1.0.4/athena_client/__init__.py +233 -0
- athena_client-1.0.4/athena_client/async_client.py +419 -0
- athena_client-1.0.4/athena_client/auth.py +62 -0
- athena_client-1.0.4/athena_client/cli.py +357 -0
- athena_client-1.0.4/athena_client/client.py +179 -0
- athena_client-1.0.4/athena_client/exceptions.py +79 -0
- athena_client-1.0.4/athena_client/http.py +255 -0
- athena_client-1.0.4/athena_client/models/__init__.py +197 -0
- athena_client-1.0.4/athena_client/query.py +233 -0
- athena_client-1.0.4/athena_client/search_result.py +209 -0
- athena_client-1.0.4/athena_client/settings.py +40 -0
- athena_client-1.0.4/athena_client/utils/__init__.py +33 -0
- athena_client-1.0.4/athena_client.egg-info/PKG-INFO +198 -0
- athena_client-1.0.4/athena_client.egg-info/SOURCES.txt +22 -0
- athena_client-1.0.4/athena_client.egg-info/dependency_links.txt +1 -0
- athena_client-1.0.4/athena_client.egg-info/entry_points.txt +2 -0
- athena_client-1.0.4/athena_client.egg-info/requires.txt +47 -0
- athena_client-1.0.4/athena_client.egg-info/top_level.txt +1 -0
- athena_client-1.0.4/pyproject.toml +108 -0
- athena_client-1.0.4/setup.cfg +4 -0
- athena_client-1.0.4/tests/test_query.py +84 -0
- athena_client-1.0.4/tests/test_search_result.py +146 -0
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: athena-client
|
|
3
|
+
Version: 1.0.4
|
|
4
|
+
Summary: Production-ready Python SDK for the OHDSI Athena Concepts API
|
|
5
|
+
Author: Athena-Client Core Engineering Team
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/username/athena-client
|
|
8
|
+
Project-URL: Documentation, https://athena-client.readthedocs.io
|
|
9
|
+
Project-URL: Issues, https://github.com/username/athena-client/issues
|
|
10
|
+
Requires-Python: >=3.9
|
|
11
|
+
Description-Content-Type: text/markdown
|
|
12
|
+
Requires-Dist: orjson>=3.9.0
|
|
13
|
+
Requires-Dist: pydantic>=2.0.0
|
|
14
|
+
Requires-Dist: pydantic-settings
|
|
15
|
+
Provides-Extra: async
|
|
16
|
+
Requires-Dist: httpx>=0.18.0; extra == "async"
|
|
17
|
+
Provides-Extra: pandas
|
|
18
|
+
Requires-Dist: pandas>=1.3.0; extra == "pandas"
|
|
19
|
+
Provides-Extra: cli
|
|
20
|
+
Requires-Dist: click>=8.0.0; extra == "cli"
|
|
21
|
+
Requires-Dist: rich>=10.0.0; extra == "cli"
|
|
22
|
+
Provides-Extra: yaml
|
|
23
|
+
Requires-Dist: pyyaml>=6.0; extra == "yaml"
|
|
24
|
+
Provides-Extra: crypto
|
|
25
|
+
Requires-Dist: cryptography>=36.0.0; extra == "crypto"
|
|
26
|
+
Provides-Extra: all
|
|
27
|
+
Requires-Dist: httpx>=0.18.0; extra == "all"
|
|
28
|
+
Requires-Dist: pandas>=1.3.0; extra == "all"
|
|
29
|
+
Requires-Dist: click>=8.0.0; extra == "all"
|
|
30
|
+
Requires-Dist: rich>=10.0.0; extra == "all"
|
|
31
|
+
Requires-Dist: pyyaml>=6.0; extra == "all"
|
|
32
|
+
Requires-Dist: cryptography>=36.0.0; extra == "all"
|
|
33
|
+
Provides-Extra: dev
|
|
34
|
+
Requires-Dist: ruff>=0.4.0; extra == "dev"
|
|
35
|
+
Requires-Dist: cyclonedx-bom>=3.15.0; extra == "dev"
|
|
36
|
+
Requires-Dist: mypy>=1.10; extra == "dev"
|
|
37
|
+
Requires-Dist: pip-audit>=2.6; extra == "dev"
|
|
38
|
+
Requires-Dist: pytest>=8.2; extra == "dev"
|
|
39
|
+
Requires-Dist: pytest-cov>=5.0; extra == "dev"
|
|
40
|
+
Requires-Dist: pytest-asyncio[mode-auto]>=0.23; extra == "dev"
|
|
41
|
+
Requires-Dist: hypothesis>=6.103; extra == "dev"
|
|
42
|
+
Requires-Dist: vcrpy>=6.0; extra == "dev"
|
|
43
|
+
Requires-Dist: rich>=13.7; extra == "dev"
|
|
44
|
+
Requires-Dist: build>=1.2; extra == "dev"
|
|
45
|
+
Requires-Dist: twine>=5.1; extra == "dev"
|
|
46
|
+
Requires-Dist: pytest-benchmark>=4.0; extra == "dev"
|
|
47
|
+
Requires-Dist: bandit>=1.7.5; extra == "dev"
|
|
48
|
+
Requires-Dist: cyclonedx-python-lib>=5.2.0; extra == "dev"
|
|
49
|
+
Requires-Dist: types-requests; extra == "dev"
|
|
50
|
+
Requires-Dist: types-PyYAML; extra == "dev"
|
|
51
|
+
Requires-Dist: pandas-stubs; extra == "dev"
|
|
52
|
+
|
|
53
|
+
# athena-client
|
|
54
|
+
[](sbom.json)
|
|
55
|
+
|
|
56
|
+
A production-ready Python SDK for the OHDSI Athena Concepts API.
|
|
57
|
+
|
|
58
|
+
## Installation
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
pip install athena-client
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
With optional dependencies:
|
|
65
|
+
```bash
|
|
66
|
+
pip install athena-client[cli] # Command-line interface
|
|
67
|
+
pip install athena-client[async] # Async client
|
|
68
|
+
pip install athena-client[pandas] # DataFrame output support
|
|
69
|
+
pip install athena-client[yaml] # YAML output format
|
|
70
|
+
pip install athena-client[crypto] # HMAC authentication
|
|
71
|
+
pip install athena-client[all] # All optional dependencies
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Quick Start
|
|
75
|
+
|
|
76
|
+
```python
|
|
77
|
+
from athena_client import Athena
|
|
78
|
+
|
|
79
|
+
# Create a client with default settings (public Athena server)
|
|
80
|
+
athena = Athena()
|
|
81
|
+
|
|
82
|
+
# Search for concepts
|
|
83
|
+
results = athena.search("aspirin")
|
|
84
|
+
|
|
85
|
+
# Various output formats
|
|
86
|
+
concepts = results.all() # List of Pydantic models
|
|
87
|
+
top_three = results.top(3) # First three results
|
|
88
|
+
as_dict = results.to_list() # List of dictionaries
|
|
89
|
+
as_json = results.to_json() # JSON string
|
|
90
|
+
as_df = results.to_df() # pandas DataFrame
|
|
91
|
+
|
|
92
|
+
# Get details for a specific concept
|
|
93
|
+
details = athena.details(concept_id=1127433)
|
|
94
|
+
|
|
95
|
+
# Get relationships
|
|
96
|
+
rels = athena.relationships(concept_id=1127433)
|
|
97
|
+
|
|
98
|
+
# Get graph
|
|
99
|
+
graph = athena.graph(concept_id=1127433, depth=5)
|
|
100
|
+
|
|
101
|
+
# Get comprehensive summary
|
|
102
|
+
summary = athena.summary(concept_id=1127433)
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
## CLI Usage
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
# Install CLI dependencies
|
|
109
|
+
pip install "athena-client[cli]"
|
|
110
|
+
|
|
111
|
+
# Search for concepts
|
|
112
|
+
athena search "aspirin"
|
|
113
|
+
|
|
114
|
+
# Get details for a specific concept
|
|
115
|
+
athena details 1127433
|
|
116
|
+
|
|
117
|
+
# Get a summary with various output formats
|
|
118
|
+
athena summary 1127433 --output yaml
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
## Configuration
|
|
122
|
+
|
|
123
|
+
The client can be configured through:
|
|
124
|
+
1. Constructor arguments
|
|
125
|
+
2. Environment variables
|
|
126
|
+
3. A `.env` file
|
|
127
|
+
4. Default values
|
|
128
|
+
|
|
129
|
+
```python
|
|
130
|
+
# Explicit configuration
|
|
131
|
+
athena = Athena(
|
|
132
|
+
base_url="https://custom.athena.server/api/v1",
|
|
133
|
+
token="your-bearer-token",
|
|
134
|
+
timeout=15,
|
|
135
|
+
max_retries=5
|
|
136
|
+
)
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
Or use environment variables:
|
|
140
|
+
```
|
|
141
|
+
ATHENA_BASE_URL=https://custom.athena.server/api/v1
|
|
142
|
+
ATHENA_TOKEN=your-bearer-token
|
|
143
|
+
ATHENA_TIMEOUT_SECONDS=15
|
|
144
|
+
ATHENA_MAX_RETRIES=5
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
## Advanced Query DSL
|
|
148
|
+
|
|
149
|
+
For complex queries, use the Query DSL:
|
|
150
|
+
|
|
151
|
+
```python
|
|
152
|
+
from athena_client.query import Q
|
|
153
|
+
|
|
154
|
+
# Build complex queries
|
|
155
|
+
q = (Q.term("diabetes") & Q.term("type 2")) | Q.exact('"diabetic nephropathy"')
|
|
156
|
+
|
|
157
|
+
# Use with search
|
|
158
|
+
results = athena.search(q)
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
### Property-Based Tests
|
|
162
|
+
|
|
163
|
+
We use **Hypothesis** for edge-case discovery. New core utilities or parsers **must** include at least one Hypothesis scenario.
|
|
164
|
+
|
|
165
|
+
## Modern Installation & Packaging
|
|
166
|
+
|
|
167
|
+
This project uses the modern Python packaging standard with `pyproject.toml` for build and dependency management. You do not need to use `setup.py` for installation or development. Instead, use the following commands:
|
|
168
|
+
|
|
169
|
+
### Install with pip (recommended)
|
|
170
|
+
|
|
171
|
+
```bash
|
|
172
|
+
pip install .
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
Or, for development (editable install with dev dependencies):
|
|
176
|
+
|
|
177
|
+
> **Note:** For editable installs with extras, make sure you have recent versions of pip and setuptools:
|
|
178
|
+
> ```bash
|
|
179
|
+
> pip install --upgrade pip setuptools
|
|
180
|
+
> ```
|
|
181
|
+
```bash
|
|
182
|
+
pip install -e '.[dev]'
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
### Why `pyproject.toml`?
|
|
186
|
+
- All build, dependency, and metadata configuration is in `pyproject.toml`.
|
|
187
|
+
- Compatible with modern Python tooling (pip, build, poetry, etc).
|
|
188
|
+
- `setup.py` is only needed for legacy or advanced customizations.
|
|
189
|
+
|
|
190
|
+
For more details, see [Packaging Python Projects](https://packaging.python.org/en/latest/tutorials/packaging-projects/).
|
|
191
|
+
|
|
192
|
+
## Documentation
|
|
193
|
+
|
|
194
|
+
For complete documentation, visit: [https://athena-client.readthedocs.io](https://athena-client.readthedocs.io)
|
|
195
|
+
|
|
196
|
+
## License
|
|
197
|
+
|
|
198
|
+
MIT
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
# athena-client
|
|
2
|
+
[](sbom.json)
|
|
3
|
+
|
|
4
|
+
A production-ready Python SDK for the OHDSI Athena Concepts API.
|
|
5
|
+
|
|
6
|
+
## Installation
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
pip install athena-client
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
With optional dependencies:
|
|
13
|
+
```bash
|
|
14
|
+
pip install athena-client[cli] # Command-line interface
|
|
15
|
+
pip install athena-client[async] # Async client
|
|
16
|
+
pip install athena-client[pandas] # DataFrame output support
|
|
17
|
+
pip install athena-client[yaml] # YAML output format
|
|
18
|
+
pip install athena-client[crypto] # HMAC authentication
|
|
19
|
+
pip install athena-client[all] # All optional dependencies
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Quick Start
|
|
23
|
+
|
|
24
|
+
```python
|
|
25
|
+
from athena_client import Athena
|
|
26
|
+
|
|
27
|
+
# Create a client with default settings (public Athena server)
|
|
28
|
+
athena = Athena()
|
|
29
|
+
|
|
30
|
+
# Search for concepts
|
|
31
|
+
results = athena.search("aspirin")
|
|
32
|
+
|
|
33
|
+
# Various output formats
|
|
34
|
+
concepts = results.all() # List of Pydantic models
|
|
35
|
+
top_three = results.top(3) # First three results
|
|
36
|
+
as_dict = results.to_list() # List of dictionaries
|
|
37
|
+
as_json = results.to_json() # JSON string
|
|
38
|
+
as_df = results.to_df() # pandas DataFrame
|
|
39
|
+
|
|
40
|
+
# Get details for a specific concept
|
|
41
|
+
details = athena.details(concept_id=1127433)
|
|
42
|
+
|
|
43
|
+
# Get relationships
|
|
44
|
+
rels = athena.relationships(concept_id=1127433)
|
|
45
|
+
|
|
46
|
+
# Get graph
|
|
47
|
+
graph = athena.graph(concept_id=1127433, depth=5)
|
|
48
|
+
|
|
49
|
+
# Get comprehensive summary
|
|
50
|
+
summary = athena.summary(concept_id=1127433)
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## CLI Usage
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
# Install CLI dependencies
|
|
57
|
+
pip install "athena-client[cli]"
|
|
58
|
+
|
|
59
|
+
# Search for concepts
|
|
60
|
+
athena search "aspirin"
|
|
61
|
+
|
|
62
|
+
# Get details for a specific concept
|
|
63
|
+
athena details 1127433
|
|
64
|
+
|
|
65
|
+
# Get a summary with various output formats
|
|
66
|
+
athena summary 1127433 --output yaml
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Configuration
|
|
70
|
+
|
|
71
|
+
The client can be configured through:
|
|
72
|
+
1. Constructor arguments
|
|
73
|
+
2. Environment variables
|
|
74
|
+
3. A `.env` file
|
|
75
|
+
4. Default values
|
|
76
|
+
|
|
77
|
+
```python
|
|
78
|
+
# Explicit configuration
|
|
79
|
+
athena = Athena(
|
|
80
|
+
base_url="https://custom.athena.server/api/v1",
|
|
81
|
+
token="your-bearer-token",
|
|
82
|
+
timeout=15,
|
|
83
|
+
max_retries=5
|
|
84
|
+
)
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Or use environment variables:
|
|
88
|
+
```
|
|
89
|
+
ATHENA_BASE_URL=https://custom.athena.server/api/v1
|
|
90
|
+
ATHENA_TOKEN=your-bearer-token
|
|
91
|
+
ATHENA_TIMEOUT_SECONDS=15
|
|
92
|
+
ATHENA_MAX_RETRIES=5
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## Advanced Query DSL
|
|
96
|
+
|
|
97
|
+
For complex queries, use the Query DSL:
|
|
98
|
+
|
|
99
|
+
```python
|
|
100
|
+
from athena_client.query import Q
|
|
101
|
+
|
|
102
|
+
# Build complex queries
|
|
103
|
+
q = (Q.term("diabetes") & Q.term("type 2")) | Q.exact('"diabetic nephropathy"')
|
|
104
|
+
|
|
105
|
+
# Use with search
|
|
106
|
+
results = athena.search(q)
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### Property-Based Tests
|
|
110
|
+
|
|
111
|
+
We use **Hypothesis** for edge-case discovery. New core utilities or parsers **must** include at least one Hypothesis scenario.
|
|
112
|
+
|
|
113
|
+
## Modern Installation & Packaging
|
|
114
|
+
|
|
115
|
+
This project uses the modern Python packaging standard with `pyproject.toml` for build and dependency management. You do not need to use `setup.py` for installation or development. Instead, use the following commands:
|
|
116
|
+
|
|
117
|
+
### Install with pip (recommended)
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
pip install .
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
Or, for development (editable install with dev dependencies):
|
|
124
|
+
|
|
125
|
+
> **Note:** For editable installs with extras, make sure you have recent versions of pip and setuptools:
|
|
126
|
+
> ```bash
|
|
127
|
+
> pip install --upgrade pip setuptools
|
|
128
|
+
> ```
|
|
129
|
+
```bash
|
|
130
|
+
pip install -e '.[dev]'
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
### Why `pyproject.toml`?
|
|
134
|
+
- All build, dependency, and metadata configuration is in `pyproject.toml`.
|
|
135
|
+
- Compatible with modern Python tooling (pip, build, poetry, etc).
|
|
136
|
+
- `setup.py` is only needed for legacy or advanced customizations.
|
|
137
|
+
|
|
138
|
+
For more details, see [Packaging Python Projects](https://packaging.python.org/en/latest/tutorials/packaging-projects/).
|
|
139
|
+
|
|
140
|
+
## Documentation
|
|
141
|
+
|
|
142
|
+
For complete documentation, visit: [https://athena-client.readthedocs.io](https://athena-client.readthedocs.io)
|
|
143
|
+
|
|
144
|
+
## License
|
|
145
|
+
|
|
146
|
+
MIT
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
"""
|
|
2
|
+
athena-client: Production-ready Python SDK for the OHDSI Athena Concepts API
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from typing import Any, Dict, Optional
|
|
6
|
+
|
|
7
|
+
from .models import ConceptDetails, ConceptRelationsGraph, ConceptRelationship
|
|
8
|
+
|
|
9
|
+
__version__ = "1.0.4"
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class Athena:
|
|
13
|
+
"""
|
|
14
|
+
Main facade for the Athena API client.
|
|
15
|
+
|
|
16
|
+
This class provides a simplified interface to the Athena API with six
|
|
17
|
+
intuitive verbs that cover 95% of day-to-day use cases.
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
def __init__(
|
|
21
|
+
self,
|
|
22
|
+
base_url: Optional[str] = None,
|
|
23
|
+
token: Optional[str] = None,
|
|
24
|
+
client_id: Optional[str] = None,
|
|
25
|
+
private_key: Optional[str] = None,
|
|
26
|
+
timeout: Optional[int] = None,
|
|
27
|
+
max_retries: Optional[int] = None,
|
|
28
|
+
backoff_factor: Optional[float] = None,
|
|
29
|
+
) -> None:
|
|
30
|
+
"""
|
|
31
|
+
Initialize the Athena facade with optional configuration.
|
|
32
|
+
|
|
33
|
+
Args:
|
|
34
|
+
base_url: The base URL for the Athena API.
|
|
35
|
+
token: Bearer token for authentication.
|
|
36
|
+
client_id: Client ID for HMAC authentication.
|
|
37
|
+
private_key: Private key for HMAC signing.
|
|
38
|
+
timeout: HTTP timeout in seconds.
|
|
39
|
+
max_retries: Maximum number of retry attempts.
|
|
40
|
+
backoff_factor: Exponential backoff factor for retries.
|
|
41
|
+
"""
|
|
42
|
+
# Import here to avoid circular imports
|
|
43
|
+
from .client import AthenaClient # pylint: disable=import-outside-toplevel
|
|
44
|
+
|
|
45
|
+
self._client = AthenaClient(
|
|
46
|
+
base_url=base_url,
|
|
47
|
+
token=token,
|
|
48
|
+
client_id=client_id,
|
|
49
|
+
private_key=private_key,
|
|
50
|
+
timeout=timeout,
|
|
51
|
+
max_retries=max_retries,
|
|
52
|
+
backoff_factor=backoff_factor,
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
def search(
|
|
56
|
+
self,
|
|
57
|
+
query: Any, # Can be str or Q object
|
|
58
|
+
*,
|
|
59
|
+
exact: Optional[str] = None,
|
|
60
|
+
fuzzy: bool = False,
|
|
61
|
+
wildcard: Optional[str] = None,
|
|
62
|
+
boosts: Optional[Dict[str, Any]] = None,
|
|
63
|
+
debug: bool = False,
|
|
64
|
+
page_size: int = 20,
|
|
65
|
+
page: int = 0,
|
|
66
|
+
domain: Optional[str] = None,
|
|
67
|
+
vocabulary: Optional[str] = None,
|
|
68
|
+
standard_concept: Optional[str] = None,
|
|
69
|
+
) -> "SearchResult":
|
|
70
|
+
"""
|
|
71
|
+
Search for concepts in the Athena vocabulary.
|
|
72
|
+
|
|
73
|
+
Args:
|
|
74
|
+
query: The search query string
|
|
75
|
+
exact: Exact match phrase
|
|
76
|
+
fuzzy: Whether to enable fuzzy matching
|
|
77
|
+
wildcard: Wildcard pattern
|
|
78
|
+
boosts: Dictionary of field boosts
|
|
79
|
+
debug: Enable debug mode
|
|
80
|
+
page_size: Number of results per page
|
|
81
|
+
page: Page number (0-indexed)
|
|
82
|
+
domain: Filter by domain
|
|
83
|
+
vocabulary: Filter by vocabulary
|
|
84
|
+
standard_concept: Filter by standard concept status
|
|
85
|
+
|
|
86
|
+
Returns:
|
|
87
|
+
SearchResult object containing the search results
|
|
88
|
+
"""
|
|
89
|
+
from .search_result import SearchResult
|
|
90
|
+
|
|
91
|
+
# Handle Q object if provided
|
|
92
|
+
query_str = query
|
|
93
|
+
if hasattr(query, "to_boosts") and callable(query.to_boosts):
|
|
94
|
+
boosts = query.to_boosts()
|
|
95
|
+
query_str = ""
|
|
96
|
+
|
|
97
|
+
data = self._client.search_concepts(
|
|
98
|
+
query=query_str,
|
|
99
|
+
exact=exact,
|
|
100
|
+
fuzzy=fuzzy,
|
|
101
|
+
wildcard=wildcard,
|
|
102
|
+
boosts=boosts,
|
|
103
|
+
debug=debug,
|
|
104
|
+
page_size=page_size,
|
|
105
|
+
page=page,
|
|
106
|
+
domain=domain,
|
|
107
|
+
vocabulary=vocabulary,
|
|
108
|
+
standard_concept=standard_concept,
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
return SearchResult(data)
|
|
112
|
+
|
|
113
|
+
def details(self, concept_id: int) -> ConceptDetails:
|
|
114
|
+
"""
|
|
115
|
+
Get detailed information for a specific concept.
|
|
116
|
+
|
|
117
|
+
Args:
|
|
118
|
+
concept_id: The concept ID to get details for
|
|
119
|
+
|
|
120
|
+
Returns:
|
|
121
|
+
ConceptDetails object
|
|
122
|
+
"""
|
|
123
|
+
return self._client.get_concept_details(concept_id)
|
|
124
|
+
|
|
125
|
+
def relationships(
|
|
126
|
+
self,
|
|
127
|
+
concept_id: int,
|
|
128
|
+
*,
|
|
129
|
+
relationship_id: Optional[str] = None,
|
|
130
|
+
only_standard: bool = False,
|
|
131
|
+
) -> ConceptRelationship:
|
|
132
|
+
"""
|
|
133
|
+
Get relationships for a specific concept.
|
|
134
|
+
|
|
135
|
+
Args:
|
|
136
|
+
concept_id: The concept ID to get relationships for
|
|
137
|
+
relationship_id: Filter by relationship type
|
|
138
|
+
only_standard: Only include standard concepts
|
|
139
|
+
|
|
140
|
+
Returns:
|
|
141
|
+
ConceptRelationship object
|
|
142
|
+
"""
|
|
143
|
+
return self._client.get_concept_relationships(
|
|
144
|
+
concept_id=concept_id,
|
|
145
|
+
relationship_id=relationship_id,
|
|
146
|
+
only_standard=only_standard,
|
|
147
|
+
)
|
|
148
|
+
|
|
149
|
+
def graph(
|
|
150
|
+
self,
|
|
151
|
+
concept_id: int,
|
|
152
|
+
*,
|
|
153
|
+
depth: int = 10,
|
|
154
|
+
zoom_level: int = 4,
|
|
155
|
+
) -> ConceptRelationsGraph:
|
|
156
|
+
"""
|
|
157
|
+
Get relationship graph for a specific concept.
|
|
158
|
+
|
|
159
|
+
Args:
|
|
160
|
+
concept_id: The concept ID to get graph for
|
|
161
|
+
depth: Maximum depth of relationships to traverse
|
|
162
|
+
zoom_level: Zoom level for the graph
|
|
163
|
+
|
|
164
|
+
Returns:
|
|
165
|
+
ConceptRelationsGraph object
|
|
166
|
+
"""
|
|
167
|
+
return self._client.get_concept_graph(
|
|
168
|
+
concept_id=concept_id,
|
|
169
|
+
depth=depth,
|
|
170
|
+
zoom_level=zoom_level,
|
|
171
|
+
)
|
|
172
|
+
|
|
173
|
+
def summary(self, concept_id: int) -> Dict[str, Any]:
|
|
174
|
+
"""
|
|
175
|
+
Get a comprehensive summary for a concept.
|
|
176
|
+
|
|
177
|
+
This aggregates details, relationships, and graph information.
|
|
178
|
+
|
|
179
|
+
Args:
|
|
180
|
+
concept_id: The concept ID to summarize
|
|
181
|
+
|
|
182
|
+
Returns:
|
|
183
|
+
Dictionary containing details, relationships, and graph
|
|
184
|
+
"""
|
|
185
|
+
details = self.details(concept_id)
|
|
186
|
+
relationships = self.relationships(concept_id)
|
|
187
|
+
graph = self.graph(concept_id)
|
|
188
|
+
|
|
189
|
+
return {
|
|
190
|
+
"details": details,
|
|
191
|
+
"relationships": relationships,
|
|
192
|
+
"graph": graph,
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
@staticmethod
|
|
196
|
+
def capabilities() -> Dict[str, Dict[str, Any]]:
|
|
197
|
+
"""
|
|
198
|
+
Get machine-readable manifest of all supported verbs.
|
|
199
|
+
|
|
200
|
+
Returns:
|
|
201
|
+
Dictionary containing capabilities information
|
|
202
|
+
"""
|
|
203
|
+
return {
|
|
204
|
+
"search": {
|
|
205
|
+
"endpoint": "/concepts",
|
|
206
|
+
"auth": "anonymous|bearer",
|
|
207
|
+
"outputs": ["models", "list", "dataframe", "json", "yaml", "csv"],
|
|
208
|
+
},
|
|
209
|
+
"details": {
|
|
210
|
+
"endpoint": "/concepts/{id}",
|
|
211
|
+
"auth": "anonymous|bearer",
|
|
212
|
+
"outputs": ["model", "json"],
|
|
213
|
+
},
|
|
214
|
+
"relationships": {
|
|
215
|
+
"endpoint": "/concepts/{id}/relationships",
|
|
216
|
+
"auth": "anonymous|bearer",
|
|
217
|
+
"outputs": ["model", "json"],
|
|
218
|
+
},
|
|
219
|
+
"graph": {
|
|
220
|
+
"endpoint": "/concepts/{id}/relations",
|
|
221
|
+
"auth": "anonymous|bearer",
|
|
222
|
+
"outputs": ["model", "json"],
|
|
223
|
+
},
|
|
224
|
+
"summary": {
|
|
225
|
+
"composed_of": ["details", "relationships", "graph"],
|
|
226
|
+
"outputs": ["dict"],
|
|
227
|
+
},
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
# Type hint for return annotation - needed at the end to avoid circular imports
|
|
232
|
+
# This import is used for type hints only, which is why it's placed at the bottom
|
|
233
|
+
from .search_result import SearchResult # noqa: E402
|