Metadata-Version: 2.4
Name: umls-python-client
Version: 1.1.0
Summary: Production-ready Python client for the NLM UMLS REST APIs.
Author: Palash Tiwari
License-Expression: Apache-2.0
Project-URL: Homepage, https://github.com/palasht75/umls-python-client
Project-URL: Documentation, https://palasht75.github.io/umls-python-client-homepage/
Project-URL: Issues, https://github.com/palasht75/umls-python-client/issues
Project-URL: Source, https://github.com/palasht75/umls-python-client
Keywords: umls,nlm,medical-terminology,api-client,healthcare
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Healthcare Industry
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Scientific/Engineering :: Medical Science Apps.
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: httpx<1.0,>=0.27.0
Requires-Dist: rdflib<8.0,>=7.0.0
Provides-Extra: dev
Requires-Dist: build>=1.2.0; extra == "dev"
Requires-Dist: mypy<2.0,>=1.10.0; extra == "dev"
Requires-Dist: pytest>=8.0.0; extra == "dev"
Requires-Dist: pytest-asyncio>=0.23.0; extra == "dev"
Requires-Dist: ruff>=0.6.0; extra == "dev"
Dynamic: license-file

# UMLS Python Client

Production-ready Python client for the NLM UMLS REST APIs.

The package keeps the original `UMLSClient` behavior for existing users and adds
typed sync and async clients for new applications.

## Installation

```bash
pip install umls-python-client
```

Development install:

```bash
pip install ".[dev]"
```

## Authentication

UMLS requests require an API key from NLM:
https://documentation.uts.nlm.nih.gov/rest/authentication.html

```python
import os

api_key = os.environ["UMLS_API_KEY"]
```

## Legacy Compatible Usage

`UMLSClient` preserves the existing JSON formatting defaults and camelCase
namespaces.

```python
from umls_python_client import UMLSClient

client = UMLSClient(api_key="YOUR_API_KEY")

results = client.searchAPI.search(
    search_string="diabetes",
    semantic_types="T047",
    semantic_groups="Disorders",
)
print(results)

raw_results = client.search_api.search(
    search_string="diabetes",
    return_indented=False,
)
```

## Typed Sync Usage

```python
from umls_python_client import TypedUMLSClient

with TypedUMLSClient(api_key="YOUR_API_KEY") as client:
    response = client.cui_api.get_cui_info("C0011849")
    concept = response.result
    print(concept.name)
```

Typed responses return `UMLSResponse[T]`. The original UMLS JSON is available
through `response.raw` or `response.to_dict()`, and RDF/Turtle is available with
`response.to_rdf()`.

## Async Usage

```python
from umls_python_client import AsyncUMLSClient


async def main() -> None:
    async with AsyncUMLSClient(api_key="YOUR_API_KEY") as client:
        response = await client.search_api.search("diabetes", page_size=5)
        print(response.result)
```

## API Namespaces

| Namespace | Legacy alias | Coverage |
| --- | --- | --- |
| `search_api` | `searchAPI` | `/search/{version}`, including `semanticTypes` and `semanticGroups` |
| `cui_api` | `cuiAPI` | CUI detail, atoms, preferred atom, definitions, relations |
| `source_api` | `sourceAPI` | Source concepts, atoms, preferred atom, hierarchy, attributes, relations |
| `atom_api` | none | AUI detail and hierarchy endpoints |
| `crosswalk_api` | `crosswalkAPI` | Source identifier crosswalk |
| `semantic_network_api` | `semanticNetworkAPI` | Semantic type lookup |
| `metadata_api` | none | `/metadata/{version}/sources` |

## Output Behavior

Legacy methods support:

- `format="json"` or `format="rdf"`
- `return_indented=True` for pretty JSON strings
- `return_indented=False` for raw Python payloads
- `save_to_file=True` and `file_path="output-directory"`

Typed methods raise structured exceptions on failures:

- `UMLSRequestError`
- `UMLSHTTPError`
- `UMLSDecodeError`

## Current NLM API Notes

The Search API changed on May 4, 2026. This client supports the current
`semanticTypes` and `semanticGroups` filters and does not send obsolete
`pageNumber` pagination parameters for endpoints where the current NLM docs no
longer document pagination.

Official UMLS REST documentation:
https://documentation.uts.nlm.nih.gov/rest/home.html

## Testing

```bash
ruff check .
ruff format --check .
mypy src
pytest
python -m build
```

Live integration tests are optional and must be explicitly enabled by setting
`UMLS_API_KEY`; default CI uses mocked transports only.

## Releases

This repository uses Release Please to automate versioning and publishing.
Commits merged to `main` should use Conventional Commit prefixes:

- `fix:` for patch releases
- `feat:` for minor releases
- `feat!:` or `fix!:` for major releases

After releasable commits land on `main`, Release Please opens or updates a
release PR. Merging that release PR creates the GitHub Release, builds the
package, attaches `dist/` artifacts to the release, and publishes to PyPI.

To publish the already-merged `1.1.0` modernization release, first merge the
release workflow, configure PyPI trusted publishing, and then run the `Release`
workflow manually with `tag_name` set to `v1.1.0`. The manual run creates the
tag and GitHub Release if needed, verifies the package, uploads release
artifacts, and publishes `1.1.0` to PyPI.

PyPI publishing uses trusted publishing, so no PyPI API token is required in
GitHub secrets. Configure the PyPI project with:

- Owner: `palasht75`
- Repository: `umls-python-client`
- Workflow: `release-please.yml`
- Environment: `pypi`

## License

Apache-2.0. See `LICENSE`.
