Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
9292470
Add FHIR resolver example script
Apr 10, 2026
e618f8d
Implement FHIR type interoperability and client helpers
Apr 14, 2026
ba0cb9c
Refactor examples to remove hardcoded API keys
Apr 14, 2026
7f2014f
Merge branch 'main' into develop
alex-omophub Apr 14, 2026
7004055
Add aiohappyeyeballs and update aiohttp dependencies in uv.lock (#17)
alex-omophub May 20, 2026
968070c
v1.71. prep
May 20, 2026
8b7363a
Merge branch 'main' into develop
alex-omophub May 20, 2026
c80ff44
Update search examples to reflect new API response structures
May 20, 2026
ee08fca
Refactor search examples to streamline API response handling
May 21, 2026
a1996f1
Enhance FHIR resolution capabilities and response structure (#20)
alex-omophub May 25, 2026
7e27854
Update CHANGELOG for version 1.8.0 and add new FHIR resolution examples
May 25, 2026
b5a0c0f
Enhance README with detailed FHIR resolution examples
May 25, 2026
a887c47
Merge branch 'main' into develop
alex-omophub May 25, 2026
2fe2cae
Update GitHub Actions workflow to use latest action versions
May 25, 2026
eae1f92
Update CI workflow to use actions/setup-python@v6 for improved compat…
May 25, 2026
d5cb814
Update CHANGELOG and refactor search endpoints to use new canonical path
Jun 1, 2026
cc986ea
Refactor AsyncSearch to simplify API request handling
Jun 1, 2026
3512066
Merge branch 'main' into develop
alex-omophub Jun 1, 2026
77efeab
Update aiohttp version to 3.14.1 and add typing-extensions dependency
Jun 13, 2026
46b92eb
Update CHANGELOG for version 1.8.1, reflecting new release links and …
Jun 13, 2026
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
6 changes: 3 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/setup-python@v5
- uses: actions/setup-python@v6
with:
python-version: "3.12"
- name: Install dependencies
Expand All @@ -34,7 +34,7 @@ jobs:
python-version: ["3.10", "3.11", "3.12", "3.13"]
steps:
- uses: actions/checkout@v6
- uses: actions/setup-python@v5
- uses: actions/setup-python@v6
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
Expand All @@ -58,7 +58,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/setup-python@v5
- uses: actions/setup-python@v6
with:
python-version: "3.12"
- name: Install dependencies
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
- uses: actions/checkout@v6
with:
fetch-depth: 0 # Required for hatch-vcs to get version from tags
- uses: actions/setup-python@v5
- uses: actions/setup-python@v6
with:
python-version: "3.12"
- name: Install build tools
Expand All @@ -24,7 +24,7 @@ jobs:
- name: Build package
run: python -m build
- name: Upload distributions
uses: actions/upload-artifact@v5
uses: actions/upload-artifact@v7
with:
name: release-dists
path: dist/
Expand All @@ -39,7 +39,7 @@ jobs:
id-token: write # Required for trusted publishing
steps:
- name: Download distributions
uses: actions/download-artifact@v5
uses: actions/download-artifact@v8
with:
name: release-dists
path: dist/
Expand Down
15 changes: 14 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,17 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [1.8.1] - 2026-06-01

### Changed

- `Search.semantic()`, `Search.semantic_iter()`, `AsyncSearch.semantic()`, and
`AsyncSearch.semantic_iter()` now call the canonical path
`GET /v1/search/semantic` instead of `GET /v1/concepts/semantic-search`. The
legacy path remains a permanent server-side alias (emits `Deprecation: true`
+ `Link: …rel="successor-version"` headers), so older installations of this
SDK continue to work - no breaking change for callers.

## [1.8.0] - 2026-05-25

### Added
Expand Down Expand Up @@ -264,7 +275,9 @@ and are not shipped in the wheel/sdist.
- Full type hints and PEP 561 compliance
- HTTP/2 support via httpx

[Unreleased]: https://github.com/omopHub/omophub-python/compare/v1.7.1...HEAD
[Unreleased]: https://github.com/omopHub/omophub-python/compare/v1.8.1...HEAD
[1.8.1]: https://github.com/omopHub/omophub-python/compare/v1.8.0...v1.8.1
[1.8.0]: https://github.com/omopHub/omophub-python/compare/v1.7.1...v1.8.0
[1.7.1]: https://github.com/omopHub/omophub-python/compare/v1.7.0...v1.7.1
[1.7.0]: https://github.com/omopHub/omophub-python/compare/v1.6.0...v1.7.0
[1.6.0]: https://github.com/omopHub/omophub-python/compare/v1.5.1...v1.6.0
Expand Down
10 changes: 4 additions & 6 deletions src/omophub/resources/search.py
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,7 @@ def semantic(
if threshold is not None:
params["threshold"] = threshold

return self._request.get("/concepts/semantic-search", params=params)
return self._request.get("/search/semantic", params=params)

def semantic_iter(
self,
Expand Down Expand Up @@ -369,7 +369,7 @@ def fetch_page(
if threshold is not None:
params["threshold"] = threshold

result = self._request.get_raw("/concepts/semantic-search", params=params)
result = self._request.get_raw("/search/semantic", params=params)

data = result.get("data", [])
results = data.get("results", data) if isinstance(data, dict) else data
Expand Down Expand Up @@ -656,7 +656,7 @@ async def semantic(
if threshold is not None:
params["threshold"] = threshold

return await self._request.get("/concepts/semantic-search", params=params)
return await self._request.get("/search/semantic", params=params)

async def semantic_iter(
self,
Expand Down Expand Up @@ -690,9 +690,7 @@ async def fetch_page(
if threshold is not None:
params["threshold"] = threshold

result = await self._request.get_raw(
"/concepts/semantic-search", params=params
)
result = await self._request.get_raw("/search/semantic", params=params)

data = result.get("data", [])
results = data.get("results", data) if isinstance(data, dict) else data
Expand Down
24 changes: 12 additions & 12 deletions tests/unit/resources/test_search.py
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,7 @@ def test_semantic_search(self, sync_client: OMOPHub, base_url: str) -> None:
},
"meta": {"pagination": {"page": 1, "has_next": False, "total_items": 1}},
}
route = respx.get(f"{base_url}/concepts/semantic-search").mock(
route = respx.get(f"{base_url}/search/semantic").mock(
return_value=Response(200, json=semantic_response)
)

Expand All @@ -316,7 +316,7 @@ def test_semantic_search_with_filters(
self, sync_client: OMOPHub, base_url: str
) -> None:
"""Test semantic search with all filters."""
route = respx.get(f"{base_url}/concepts/semantic-search").mock(
route = respx.get(f"{base_url}/search/semantic").mock(
return_value=Response(200, json={"success": True, "data": {"results": []}})
)

Expand Down Expand Up @@ -353,7 +353,7 @@ def test_semantic_iter_single_page(
],
"meta": {"pagination": {"page": 1, "has_next": False}},
}
respx.get(f"{base_url}/concepts/semantic-search").mock(
respx.get(f"{base_url}/search/semantic").mock(
return_value=Response(200, json=semantic_response)
)

Expand Down Expand Up @@ -385,7 +385,7 @@ def mock_response(request):
return Response(200, json=page1_response)
return Response(200, json=page2_response)

respx.get(f"{base_url}/concepts/semantic-search").mock(side_effect=mock_response)
respx.get(f"{base_url}/search/semantic").mock(side_effect=mock_response)

results = list(sync_client.search.semantic_iter("diabetes", page_size=1))
assert len(results) == 2
Expand All @@ -402,7 +402,7 @@ def test_semantic_iter_empty_response(
"data": [],
"meta": {"pagination": {"page": 1, "has_next": False}},
}
respx.get(f"{base_url}/concepts/semantic-search").mock(
respx.get(f"{base_url}/search/semantic").mock(
return_value=Response(200, json=semantic_response)
)

Expand Down Expand Up @@ -555,7 +555,7 @@ async def test_async_semantic_search(
"results": [{"concept_id": 4329847, "similarity_score": 0.95}],
},
}
respx.get(f"{base_url}/concepts/semantic-search").mock(
respx.get(f"{base_url}/search/semantic").mock(
return_value=Response(200, json=semantic_response)
)

Expand All @@ -568,7 +568,7 @@ async def test_async_semantic_with_filters(
self, async_client: omophub.AsyncOMOPHub, base_url: str
) -> None:
"""Test async semantic search with filters."""
route = respx.get(f"{base_url}/concepts/semantic-search").mock(
route = respx.get(f"{base_url}/search/semantic").mock(
return_value=Response(200, json={"success": True, "data": {"results": []}})
)

Expand All @@ -591,7 +591,7 @@ async def test_async_semantic_with_all_filters(
self, async_client: omophub.AsyncOMOPHub, base_url: str
) -> None:
"""Test async semantic search with all available filters."""
route = respx.get(f"{base_url}/concepts/semantic-search").mock(
route = respx.get(f"{base_url}/search/semantic").mock(
return_value=Response(200, json={"success": True, "data": {"results": []}})
)

Expand Down Expand Up @@ -629,7 +629,7 @@ async def test_async_semantic_iter_single_page(
],
"meta": {"pagination": {"page": 1, "has_next": False}},
}
respx.get(f"{base_url}/concepts/semantic-search").mock(
respx.get(f"{base_url}/search/semantic").mock(
return_value=Response(200, json=semantic_response)
)

Expand Down Expand Up @@ -674,7 +674,7 @@ def mock_response(request):
return Response(200, json=page2_response)
return Response(200, json=page3_response)

respx.get(f"{base_url}/concepts/semantic-search").mock(side_effect=mock_response)
respx.get(f"{base_url}/search/semantic").mock(side_effect=mock_response)

results = []
async for item in async_client.search.semantic_iter("diabetes", page_size=1):
Expand All @@ -696,7 +696,7 @@ async def test_async_semantic_iter_with_filters(
"data": [{"concept_id": 1, "similarity_score": 0.9}],
"meta": {"pagination": {"page": 1, "has_next": False}},
}
route = respx.get(f"{base_url}/concepts/semantic-search").mock(
route = respx.get(f"{base_url}/search/semantic").mock(
return_value=Response(200, json=semantic_response)
)

Expand Down Expand Up @@ -732,7 +732,7 @@ async def test_async_semantic_iter_empty_response(
"data": [],
"meta": {"pagination": {"page": 1, "has_next": False}},
}
respx.get(f"{base_url}/concepts/semantic-search").mock(
respx.get(f"{base_url}/search/semantic").mock(
return_value=Response(200, json=semantic_response)
)

Expand Down
Loading
Loading