Skip to content

Commit 2fdf976

Browse files
Merge pull request #25 from pepkit/dev
Release 0.2.0
2 parents 611d1fb + 22e0e6f commit 2fdf976

File tree

7 files changed

+120
-6
lines changed

7 files changed

+120
-6
lines changed

codecov.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ coverage:
1111
tests:
1212
paths:
1313
- "tests/"
14-
target: 100%
14+
target: 70%
1515
source:
1616
paths:
1717
- "jupytext/"

docs/changelog.md

+4
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22

33
This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html) and [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) format.
44

5+
## [0.2.0] - 2023-10-02
6+
### Added
7+
- Project search functionality
8+
59
## [0.1.1] - 2023-07-29
610
### Fixed
711
- Incorrect base url

pephubclient/__init__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from pephubclient.pephubclient import PEPHubClient
22

33
__app_name__ = "pephubclient"
4-
__version__ = "0.1.2"
4+
__version__ = "0.2.0"
55
__author__ = "Oleksandr Khoroshevskyi, Rafal Stepien"
66

77

pephubclient/constants.py

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
PEPHUB_BASE_URL = "https://pephub.databio.org/"
88
# PEPHUB_BASE_URL = "http://0.0.0.0:8000/"
99
PEPHUB_PEP_API_BASE_URL = f"{PEPHUB_BASE_URL}api/v1/projects/"
10+
PEPHUB_PEP_SEARCH_URL = f"{PEPHUB_BASE_URL}api/v1/namespaces/{{namespace}}/projects"
1011
PEPHUB_PUSH_URL = f"{PEPHUB_BASE_URL}api/v1/namespaces/{{namespace}}/projects/json"
1112

1213

pephubclient/models.py

+22-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
from typing import Optional
1+
import datetime
2+
from typing import Optional, List
23

34
import pydantic
45
from pydantic import BaseModel, Extra, Field
@@ -32,3 +33,23 @@ class ProjectUploadData(BaseModel):
3233
@pydantic.validator("tag")
3334
def tag_should_not_be_none(cls, v):
3435
return v or "default"
36+
37+
38+
class ProjectAnnotationModel(BaseModel):
39+
namespace: str
40+
name: str
41+
tag: str
42+
is_private: bool
43+
number_of_samples: int
44+
description: str
45+
last_update_date: datetime.datetime
46+
submission_date: datetime.datetime
47+
digest: str
48+
pep_schema: str
49+
50+
51+
class SearchReturnModel(BaseModel):
52+
count: int
53+
limit: int
54+
offset: int
55+
items: List[ProjectAnnotationModel]

pephubclient/pephubclient.py

+80-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import json
22
import os
3-
from typing import NoReturn, Optional
3+
from typing import NoReturn, Optional, Literal
44

55
import pandas as pd
66
import peppy
@@ -21,6 +21,7 @@
2121
PEPHUB_PUSH_URL,
2222
RegistryPath,
2323
ResponseStatusCodes,
24+
PEPHUB_PEP_SEARCH_URL,
2425
)
2526
from pephubclient.exceptions import (
2627
IncorrectQueryStringError,
@@ -29,7 +30,12 @@
2930
)
3031
from pephubclient.files_manager import FilesManager
3132
from pephubclient.helpers import MessageHandler, RequestManager
32-
from pephubclient.models import ProjectDict, ProjectUploadData
33+
from pephubclient.models import (
34+
ProjectDict,
35+
ProjectUploadData,
36+
SearchReturnModel,
37+
ProjectAnnotationModel,
38+
)
3339
from pephubclient.pephub_oauth.pephub_oauth import PEPHubAuth
3440

3541
urllib3.disable_warnings()
@@ -182,9 +188,65 @@ def upload(
182188
"User does not have permission to write to this namespace!"
183189
)
184190
else:
185-
raise ResponseError("Unexpected Response Error.")
191+
raise ResponseError(
192+
f"Unexpected Response Error. {pephub_response.status_code}"
193+
)
186194
return None
187195

196+
def find_project(
197+
self,
198+
namespace: str,
199+
query_string: str = "",
200+
limit: int = 100,
201+
offset: int = 0,
202+
filter_by: Literal["submission_date", "last_update_date"] = None,
203+
start_date: str = None,
204+
end_date: str = None,
205+
) -> SearchReturnModel:
206+
"""
207+
Find project in specific namespace and return list of PEP annotation
208+
209+
:param namespace: Namespace where to search for projects
210+
:param query_string: Search query
211+
:param limit: Return limit
212+
:param offset: Return offset
213+
:param filter_by: Use filter date. Option: [submission_date, last_update_date]
214+
:param start_date: filter beginning date
215+
:param end_date: filter end date (if none today's date is used)
216+
:return:
217+
"""
218+
jwt_data = FilesManager.load_jwt_data_from_file(self.PATH_TO_FILE_WITH_JWT)
219+
220+
query_param = {
221+
"q": query_string,
222+
"limit": limit,
223+
"offset": offset,
224+
}
225+
if filter_by in ["submission_date", "last_update_date"]:
226+
query_param["filter_by"] = filter_by
227+
query_param["filter_start_date"] = start_date
228+
if end_date:
229+
query_param["filter_end_date"] = end_date
230+
231+
url = self._build_project_search_url(
232+
namespace=namespace,
233+
query_param=query_param,
234+
)
235+
236+
pephub_response = self.send_request(
237+
method="GET",
238+
url=url,
239+
headers=self._get_header(jwt_data),
240+
json=None,
241+
cookies=None,
242+
)
243+
if pephub_response.status_code == ResponseStatusCodes.OK:
244+
decoded_response = self._handle_pephub_response(pephub_response)
245+
project_list = []
246+
for project_found in json.loads(decoded_response)["items"]:
247+
project_list.append(ProjectAnnotationModel(**project_found))
248+
return SearchReturnModel(**json.loads(decoded_response))
249+
188250
@staticmethod
189251
def _save_raw_pep(
190252
reg_path: str,
@@ -334,6 +396,21 @@ def _build_pull_request_url(self, query_param: dict = None) -> str:
334396

335397
return PEPHUB_PEP_API_BASE_URL + endpoint
336398

399+
def _build_project_search_url(
400+
self, namespace: str, query_param: dict = None
401+
) -> str:
402+
"""
403+
Build request for searching projects form pephub
404+
405+
:param query_param: dict of parameters used in query string
406+
:return: url string
407+
"""
408+
409+
variables_string = PEPHubClient._parse_query_param(query_param)
410+
endpoint = variables_string
411+
412+
return PEPHUB_PEP_SEARCH_URL.format(namespace=namespace) + endpoint
413+
337414
@staticmethod
338415
def _build_push_request_url(namespace: str) -> str:
339416
"""

tests/test_pephubclient.py

+11
Original file line numberDiff line numberDiff line change
@@ -147,3 +147,14 @@ def test_push_with_pephub_error_response(
147147
namespace="s_name",
148148
name="name",
149149
)
150+
151+
def test_search_prj(self, mocker):
152+
return_value = b'{"count":1,"limit":100,"offset":0,"items":[{"namespace":"namespace1","name":"basic","tag":"default","is_private":false,"number_of_samples":2,"description":"None","last_update_date":"2023-08-27 19:07:31.552861+00:00","submission_date":"2023-08-27 19:07:31.552858+00:00","digest":"08cbcdbf4974fc84bee824c562b324b5","pep_schema":"random_schema_name"}],"session_info":null,"can_edit":false}'
153+
requests_mock = mocker.patch(
154+
"requests.request",
155+
return_value=Mock(content=return_value, status_code=200),
156+
)
157+
158+
return_value = PEPHubClient().find_project(namespace="namespace1")
159+
assert return_value.count == 1
160+
assert len(return_value.items) == 1

0 commit comments

Comments
 (0)