Skip to content

Commit ece65ea

Browse files
committed
fix pylint and mypy errors and rename filter to advanced_filter in search_by_pdf()
1 parent ef2aa46 commit ece65ea

8 files changed

Lines changed: 46 additions & 28 deletions

File tree

backend/app/repositories/search_repository.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from datetime import date
22
from typing import List, Optional, Tuple, Union
33

4-
from sqlalchemy import and_, or_, select
4+
from sqlalchemy import and_, or_, select, ClauseElement
55
from sqlalchemy.ext.asyncio import AsyncSession
66

77
from app.models.paper import Paper as PaperModel
@@ -23,10 +23,10 @@ class SearchRepository:
2323

2424
@staticmethod
2525
async def search_papers_by_embeddings(
26-
db: AsyncSession,
27-
embeddings: List[List[float]],
28-
limit: int = 5,
29-
search_filter: Optional[AdvancedSearchFilter] = None,
26+
db: AsyncSession,
27+
embeddings: List[List[float]],
28+
limit: int = 5,
29+
search_filter: Optional[AdvancedSearchFilter] = None,
3030
) -> List[Tuple[PaperModel, float]]:
3131
"""
3232
Perform a vector search for papers based on a list of embeddings.
@@ -72,7 +72,7 @@ def _build_filter_clauses(search_filter: AdvancedSearchFilter) -> list:
7272
return clauses
7373

7474
@staticmethod
75-
def _build_group_clause(group: ConditionGroup):
75+
def _build_group_clause(group: ConditionGroup) -> Optional[ClauseElement]:
7676
"""Recursively build an AND/OR clause from a ConditionGroup."""
7777
if not group.children:
7878
return None
@@ -91,7 +91,7 @@ def _build_group_clause(group: ConditionGroup):
9191
return or_(*child_clauses)
9292

9393
@staticmethod
94-
def _build_node_clause(node: Union[TextCondition, ConditionGroup]):
94+
def _build_node_clause(node: Union[TextCondition, ConditionGroup]) -> Optional[ClauseElement]:
9595
"""Build a clause for a single node (condition or nested group)."""
9696
if node.type == "group":
9797
return SearchRepository._build_group_clause(node)

backend/app/routes/search_routes.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ async def search_by_pdf(
4242
default=None,
4343
description="Optional: query specifying what you want to find in relation to the paper",
4444
),
45-
filter: str | None = Form(
45+
advanced_filter: str | None = Form(
4646
default=None,
4747
description="Optional: JSON-encoded advanced search filter",
4848
),
@@ -60,9 +60,9 @@ async def search_by_pdf(
6060
)
6161

6262
search_filter = None
63-
if filter:
63+
if advanced_filter:
6464
try:
65-
search_filter = AdvancedSearchFilter.model_validate(json.loads(filter))
65+
search_filter = AdvancedSearchFilter.model_validate(json.loads(advanced_filter))
6666
except (json.JSONDecodeError, ValueError) as exc:
6767
raise HTTPException(
6868
status_code=400,

backend/app/schemas/search_dto.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,17 @@
88

99

1010
class TextCondition(BaseModel):
11+
"""Single text-based filter condition on a paper field."""
12+
1113
type: Literal["condition"]
1214
field: Literal["title", "abstract"]
1315
operator: Literal["contains", "not_contains"]
1416
value: str
1517

1618

1719
class ConditionGroup(BaseModel):
20+
"""Logical group combining multiple conditions with AND / OR."""
21+
1822
type: Literal["group"]
1923
operator: Literal["AND", "OR"]
2024
children: List[
@@ -23,6 +27,8 @@ class ConditionGroup(BaseModel):
2327

2428

2529
class AdvancedSearchFilter(BaseModel):
30+
"""Structured filter with optional year range and boolean condition tree."""
31+
2632
year_from: Optional[int] = None
2733
year_to: Optional[int] = None
2834
root: ConditionGroup

frontend/src/api/apis/search-api.ts

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,11 @@ export const SearchApiAxiosParamCreator = function (configuration?: Configuratio
3737
* @summary Search for papers using a PDF
3838
* @param {File} pdf Research paper PDF
3939
* @param {string | null} [query]
40-
* @param {string | null} [filter]
40+
* @param {string | null} [advancedFilter]
4141
* @param {*} [options] Override http request option.
4242
* @throws {RequiredError}
4343
*/
44-
searchByPdfSearchPdfPost: async (pdf: File, query?: string | null, filter?: string | null, options: RawAxiosRequestConfig = {}): Promise<RequestArgs> => {
44+
searchByPdfSearchPdfPost: async (pdf: File, query?: string | null, advancedFilter?: string | null, options: RawAxiosRequestConfig = {}): Promise<RequestArgs> => {
4545
// verify required parameter 'pdf' is not null or undefined
4646
assertParamExists('searchByPdfSearchPdfPost', 'pdf', pdf)
4747
const localVarPath = `/search/pdf`;
@@ -66,8 +66,8 @@ export const SearchApiAxiosParamCreator = function (configuration?: Configuratio
6666
localVarFormParams.append('query', query as any);
6767
}
6868

69-
if (filter !== undefined) {
70-
localVarFormParams.append('filter', filter as any);
69+
if (advancedFilter !== undefined) {
70+
localVarFormParams.append('advanced_filter', advancedFilter as any);
7171
}
7272
localVarHeaderParameter['Content-Type'] = 'multipart/form-data';
7373
localVarHeaderParameter['Accept'] = 'application/json';
@@ -131,12 +131,12 @@ export const SearchApiFp = function(configuration?: Configuration) {
131131
* @summary Search for papers using a PDF
132132
* @param {File} pdf Research paper PDF
133133
* @param {string | null} [query]
134-
* @param {string | null} [filter]
134+
* @param {string | null} [advancedFilter]
135135
* @param {*} [options] Override http request option.
136136
* @throws {RequiredError}
137137
*/
138-
async searchByPdfSearchPdfPost(pdf: File, query?: string | null, filter?: string | null, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<SearchResponse>> {
139-
const localVarAxiosArgs = await localVarAxiosParamCreator.searchByPdfSearchPdfPost(pdf, query, filter, options);
138+
async searchByPdfSearchPdfPost(pdf: File, query?: string | null, advancedFilter?: string | null, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<SearchResponse>> {
139+
const localVarAxiosArgs = await localVarAxiosParamCreator.searchByPdfSearchPdfPost(pdf, query, advancedFilter, options);
140140
const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
141141
const localVarOperationServerBasePath = operationServerMap['SearchApi.searchByPdfSearchPdfPost']?.[localVarOperationServerIndex]?.url;
142142
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
@@ -168,12 +168,12 @@ export const SearchApiFactory = function (configuration?: Configuration, basePat
168168
* @summary Search for papers using a PDF
169169
* @param {File} pdf Research paper PDF
170170
* @param {string | null} [query]
171-
* @param {string | null} [filter]
171+
* @param {string | null} [advancedFilter]
172172
* @param {*} [options] Override http request option.
173173
* @throws {RequiredError}
174174
*/
175-
searchByPdfSearchPdfPost(pdf: File, query?: string | null, filter?: string | null, options?: RawAxiosRequestConfig): AxiosPromise<SearchResponse> {
176-
return localVarFp.searchByPdfSearchPdfPost(pdf, query, filter, options).then((request) => request(axios, basePath));
175+
searchByPdfSearchPdfPost(pdf: File, query?: string | null, advancedFilter?: string | null, options?: RawAxiosRequestConfig): AxiosPromise<SearchResponse> {
176+
return localVarFp.searchByPdfSearchPdfPost(pdf, query, advancedFilter, options).then((request) => request(axios, basePath));
177177
},
178178
/**
179179
* Returns a list of papers that match the search query. Optionally accepts an advanced filter with year range and text conditions.
@@ -197,12 +197,12 @@ export class SearchApi extends BaseAPI {
197197
* @summary Search for papers using a PDF
198198
* @param {File} pdf Research paper PDF
199199
* @param {string | null} [query]
200-
* @param {string | null} [filter]
200+
* @param {string | null} [advancedFilter]
201201
* @param {*} [options] Override http request option.
202202
* @throws {RequiredError}
203203
*/
204-
public searchByPdfSearchPdfPost(pdf: File, query?: string | null, filter?: string | null, options?: RawAxiosRequestConfig) {
205-
return SearchApiFp(this.configuration).searchByPdfSearchPdfPost(pdf, query, filter, options).then((request) => request(this.axios, this.basePath));
204+
public searchByPdfSearchPdfPost(pdf: File, query?: string | null, advancedFilter?: string | null, options?: RawAxiosRequestConfig) {
205+
return SearchApiFp(this.configuration).searchByPdfSearchPdfPost(pdf, query, advancedFilter, options).then((request) => request(this.axios, this.basePath));
206206
}
207207

208208
/**

frontend/src/api/models/advanced-search-filter.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@
1717
// @ts-ignore
1818
import type { ConditionGroup } from './condition-group';
1919

20+
/**
21+
* Structured filter with optional year range and boolean condition tree.
22+
*/
2023
export interface AdvancedSearchFilter {
2124
'year_from'?: number | null;
2225
'year_to'?: number | null;

frontend/src/api/models/condition-group.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@
1717
// @ts-ignore
1818
import type { ConditionGroupChildrenInner } from './condition-group-children-inner';
1919

20+
/**
21+
* Logical group combining multiple conditions with AND / OR.
22+
*/
2023
export interface ConditionGroup {
2124
'type': ConditionGroupTypeEnum;
2225
'operator': ConditionGroupOperatorEnum;

frontend/src/api/models/text-condition.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@
1414

1515

1616

17+
/**
18+
* Single text-based filter condition on a paper field.
19+
*/
1720
export interface TextCondition {
1821
'type': TextConditionTypeEnum;
1922
'field': TextConditionFieldEnum;

openapi/openapi.json

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -753,7 +753,8 @@
753753
"required": [
754754
"root"
755755
],
756-
"title": "AdvancedSearchFilter"
756+
"title": "AdvancedSearchFilter",
757+
"description": "Structured filter with optional year range and boolean condition tree."
757758
},
758759
"Body_search_by_pdf_search_pdf_post": {
759760
"properties": {
@@ -775,7 +776,7 @@
775776
"title": "Query",
776777
"description": "Optional: query specifying what you want to find in relation to the paper"
777778
},
778-
"filter": {
779+
"advanced_filter": {
779780
"anyOf": [
780781
{
781782
"type": "string"
@@ -784,7 +785,7 @@
784785
"type": "null"
785786
}
786787
],
787-
"title": "Filter",
788+
"title": "Advanced Filter",
788789
"description": "Optional: JSON-encoded advanced search filter"
789790
}
790791
},
@@ -856,7 +857,8 @@
856857
"operator",
857858
"children"
858859
],
859-
"title": "ConditionGroup"
860+
"title": "ConditionGroup",
861+
"description": "Logical group combining multiple conditions with AND / OR."
860862
},
861863
"HTTPValidationError": {
862864
"properties": {
@@ -1281,7 +1283,8 @@
12811283
"operator",
12821284
"value"
12831285
],
1284-
"title": "TextCondition"
1286+
"title": "TextCondition",
1287+
"description": "Single text-based filter condition on a paper field."
12851288
},
12861289
"UserCreate": {
12871290
"properties": {

0 commit comments

Comments
 (0)