From cdaa167ad58ecf6e4431604e6c4c2b112230586f Mon Sep 17 00:00:00 2001 From: Aleksandr Kroshko Date: Mon, 6 Apr 2026 10:38:59 +0300 Subject: [PATCH 1/4] DEV-22328: client to hfapi2 --- huntflow_api_client/entities/__init__.py | 2 ++ .../entities/applicant_on_vacancy.py | 2 +- huntflow_api_client/entities/applicants.py | 4 +-- huntflow_api_client/entities/dictionaries.py | 8 +++-- .../entities/multi_vacancies.py | 4 +-- .../entities/production_calendars.py | 2 +- huntflow_api_client/entities/resume.py | 2 +- huntflow_api_client/entities/tags.py | 6 ++-- huntflow_api_client/entities/token.py | 21 +++++++++++++ huntflow_api_client/entities/vacancies.py | 12 +++---- .../entities/vacancy_requests.py | 2 +- huntflow_api_client/entities/webhooks.py | 2 +- huntflow_api_client/models/consts.py | 8 ++++- huntflow_api_client/models/request/token.py | 7 +++++ .../models/response/applicant_logs.py | 19 ++++++++++++ .../models/response/applicants.py | 3 +- huntflow_api_client/models/response/token.py | 12 +++++++ huntflow_api_client/utils.py | 13 ++++++++ pyproject.toml | 2 +- tests/test_entities/test_applicants.py | 1 + .../test_entities/test_production_calendar.py | 2 +- tests/test_entities/test_tokens.py | 31 +++++++++++++++++++ 22 files changed, 141 insertions(+), 24 deletions(-) create mode 100644 huntflow_api_client/entities/token.py create mode 100644 huntflow_api_client/models/request/token.py create mode 100644 huntflow_api_client/models/response/token.py create mode 100644 huntflow_api_client/utils.py create mode 100644 tests/test_entities/test_tokens.py diff --git a/huntflow_api_client/entities/__init__.py b/huntflow_api_client/entities/__init__.py index 04b4b85..cdff254 100644 --- a/huntflow_api_client/entities/__init__.py +++ b/huntflow_api_client/entities/__init__.py @@ -25,6 +25,7 @@ from huntflow_api_client.entities.survey_type_a import SurveyTypeA from huntflow_api_client.entities.survey_type_q import SurveyTypeQ from huntflow_api_client.entities.tags import AccountTag, ApplicantTag +from huntflow_api_client.entities.token import Token from huntflow_api_client.entities.user_settings import UserSettings from huntflow_api_client.entities.users import User from huntflow_api_client.entities.users_management import UsersManagement @@ -61,6 +62,7 @@ "Resume", "SurveyTypeA", "SurveyTypeQ", + "Token", "User", "UsersManagement", "UserSettings", diff --git a/huntflow_api_client/entities/applicant_on_vacancy.py b/huntflow_api_client/entities/applicant_on_vacancy.py index e65e574..75bbf60 100644 --- a/huntflow_api_client/entities/applicant_on_vacancy.py +++ b/huntflow_api_client/entities/applicant_on_vacancy.py @@ -77,6 +77,6 @@ async def move_applicant_to_child_vacancy( response = await self._api.request( "PUT", f"/accounts/{account_id}/applicants/vacancy/{vacancy_id}/split", - json=data.jsonable_dict(exclude_none=True), + json=data.jsonable_dict(exclude_unset=True), ) return ApplicantVacancySplitResponse.model_validate(response.json()) diff --git a/huntflow_api_client/entities/applicants.py b/huntflow_api_client/entities/applicants.py index c05e218..d959cf2 100644 --- a/huntflow_api_client/entities/applicants.py +++ b/huntflow_api_client/entities/applicants.py @@ -6,7 +6,7 @@ GetEntityMixin, ListEntityMixin, ) -from huntflow_api_client.models.consts import AgreementState, ApplicantSearchField +from huntflow_api_client.models.consts import AgreementStateRequest, ApplicantSearchField from huntflow_api_client.models.request.applicants import ( ApplicantCreateRequest, ApplicantUpdateRequest, @@ -29,7 +29,7 @@ async def list( page: Optional[int] = 1, status: Optional[int] = None, vacancy_id: Optional[int] = None, - agreement_state: Optional[AgreementState] = None, + agreement_state: Optional[AgreementStateRequest] = None, ) -> ApplicantListResponse: """ API method reference https://api.huntflow.ai/v2/docs#get-/accounts/-account_id-/applicants diff --git a/huntflow_api_client/entities/dictionaries.py b/huntflow_api_client/entities/dictionaries.py index 43e3c32..ce9f0c9 100644 --- a/huntflow_api_client/entities/dictionaries.py +++ b/huntflow_api_client/entities/dictionaries.py @@ -43,7 +43,11 @@ async def create( :return: An object that contains the task ID of the delayed background update task """ path = f"/accounts/{account_id}/dictionaries" - response = await self._api.request("POST", path, json=data.jsonable_dict(exclude_none=True)) + response = await self._api.request( + "POST", + path, + json=data.jsonable_dict(exclude_unset=True), + ) return DictionaryTaskResponse.model_validate(response.json()) async def get(self, account_id: int, dict_code: str) -> DictionaryResponse: @@ -75,5 +79,5 @@ async def update( :return: An object that contains the task ID of the delayed background update task """ path = f"/accounts/{account_id}/dictionaries/{dict_code}" - response = await self._api.request("PUT", path, json=data.jsonable_dict(exclude_none=True)) + response = await self._api.request("PUT", path, json=data.jsonable_dict(exclude_unset=True)) return DictionaryTaskResponse.model_validate(response.json()) diff --git a/huntflow_api_client/entities/multi_vacancies.py b/huntflow_api_client/entities/multi_vacancies.py index 8f809b5..bc13e6e 100644 --- a/huntflow_api_client/entities/multi_vacancies.py +++ b/huntflow_api_client/entities/multi_vacancies.py @@ -26,7 +26,7 @@ async def create( response = await self._api.request( "POST", f"/accounts/{account_id}/multi-vacancies", - json=data.jsonable_dict(exclude_none=True), + json=data.jsonable_dict(exclude_unset=True), ) return MultiVacancyResponse.model_validate(response.json()) @@ -52,6 +52,6 @@ async def update( response = await self._api.request( method, f"/accounts/{account_id}/multi-vacancies/{vacancy_id}", - json=data.jsonable_dict(exclude_none=True), + json=data.jsonable_dict(exclude_unset=True), ) return MultiVacancyResponse.model_validate(response.json()) diff --git a/huntflow_api_client/entities/production_calendars.py b/huntflow_api_client/entities/production_calendars.py index c27536a..26bdbeb 100644 --- a/huntflow_api_client/entities/production_calendars.py +++ b/huntflow_api_client/entities/production_calendars.py @@ -55,7 +55,7 @@ async def get_non_working_days_in_period( calendar_id: int, deadline: datetime.date, start: Optional[datetime.date] = None, - verbose: Optional[bool] = True, + verbose: Optional[bool] = False, ) -> NonWorkingDaysResponse: """ API method reference diff --git a/huntflow_api_client/entities/resume.py b/huntflow_api_client/entities/resume.py index e664937..899ba52 100644 --- a/huntflow_api_client/entities/resume.py +++ b/huntflow_api_client/entities/resume.py @@ -83,7 +83,7 @@ async def update( response = await self._api.request( "PUT", f"/accounts/{account_id}/applicants/{applicant_id}/externals/{external_id}", - json=data.jsonable_dict(exclude_none=True), + json=data.jsonable_dict(), ) return ApplicantResumeResponse.model_validate(response.json()) diff --git a/huntflow_api_client/entities/tags.py b/huntflow_api_client/entities/tags.py index d4cc948..fa86f41 100644 --- a/huntflow_api_client/entities/tags.py +++ b/huntflow_api_client/entities/tags.py @@ -43,7 +43,7 @@ async def create( response = await self._api.request( "POST", f"/accounts/{account_id}/tags", - json=account_tag.jsonable_dict(exclude_none=True), + json=account_tag.jsonable_dict(), ) return AccountTagResponse.model_validate(response.json()) @@ -65,7 +65,7 @@ async def update( response = await self._api.request( "PUT", f"/accounts/{account_id}/tags/{account_tag_id}", - json=data.jsonable_dict(exclude_none=True), + json=data.jsonable_dict(), ) return AccountTagResponse.model_validate(response.json()) @@ -112,7 +112,7 @@ async def update( response = await self._api.request( "POST", f"/accounts/{account_id}/applicants/{applicant_id}/tags", - json=data.jsonable_dict(exclude_none=True), + json=data.jsonable_dict(), ) return ApplicantTagsListResponse.model_validate(response.json()) diff --git a/huntflow_api_client/entities/token.py b/huntflow_api_client/entities/token.py new file mode 100644 index 0000000..644005d --- /dev/null +++ b/huntflow_api_client/entities/token.py @@ -0,0 +1,21 @@ +from huntflow_api_client.entities.base import BaseEntity, UpdateEntityMixin +from huntflow_api_client.models.request.token import RefreshTokenRequest +from huntflow_api_client.models.response.token import RefreshTokenResponse + + +class Token(BaseEntity, UpdateEntityMixin): + + async def update(self, data: RefreshTokenRequest) -> RefreshTokenResponse: + """ + API method reference + https://api.huntflow.ru/latest/docs#post-/token/refresh + + :param data: token request data + :return: refreshed token data + """ + response = await self._api.request( + "POST", + "/token/refresh", + json=data.jsonable_dict(), + ) + return RefreshTokenResponse.model_validate(response.json()) diff --git a/huntflow_api_client/entities/vacancies.py b/huntflow_api_client/entities/vacancies.py index c0248de..acea6b6 100644 --- a/huntflow_api_client/entities/vacancies.py +++ b/huntflow_api_client/entities/vacancies.py @@ -96,7 +96,7 @@ async def create(self, account_id: int, data: VacancyCreateRequest) -> VacancyCr response = await self._api.request( "POST", f"/accounts/{account_id}/vacancies", - json=data.jsonable_dict(exclude_none=True), + json=data.jsonable_dict(exclude_unset=True), ) return VacancyCreateResponse.model_validate(response.json()) @@ -118,7 +118,7 @@ async def update( response = await self._api.request( "PUT", f"/accounts/{account_id}/vacancies/{vacancy_id}", - json=data.jsonable_dict(exclude_none=True), + json=data.jsonable_dict(exclude_unset=True), ) return VacancyResponse.model_validate(response.json()) @@ -150,7 +150,7 @@ async def patch( response = await self._api.request( "PATCH", f"/accounts/{account_id}/vacancies/{vacancy_id}", - json=data.jsonable_dict(exclude_none=True), + json=data.jsonable_dict(exclude_unset=True), ) return VacancyResponse.model_validate(response.json()) @@ -174,7 +174,7 @@ async def assign_coworker( response = await self._api.request( "PUT", f"/accounts/{account_id}/vacancies/{vacancy_id}/members/{account_member_id}", - json=data.jsonable_dict(exclude_none=True), + json=data.jsonable_dict(), ) return StatusResponse.model_validate(response.json()) @@ -304,7 +304,7 @@ async def close(self, account_id: int, vacancy_id: int, data: VacancyCloseReques await self._api.request( "POST", f"/accounts/{account_id}/vacancies/{vacancy_id}/state/close", - json=data.jsonable_dict(exclude_none=True), + json=data.jsonable_dict(), ) async def hold(self, account_id: int, vacancy_id: int, data: VacancyHoldRequest) -> None: @@ -319,7 +319,7 @@ async def hold(self, account_id: int, vacancy_id: int, data: VacancyHoldRequest) await self._api.request( "POST", f"/accounts/{account_id}/vacancies/{vacancy_id}/state/hold", - json=data.jsonable_dict(exclude_none=True), + json=data.jsonable_dict(), ) async def resume(self, account_id: int, vacancy_id: int) -> None: diff --git a/huntflow_api_client/entities/vacancy_requests.py b/huntflow_api_client/entities/vacancy_requests.py index b89eccb..f818946 100644 --- a/huntflow_api_client/entities/vacancy_requests.py +++ b/huntflow_api_client/entities/vacancy_requests.py @@ -76,6 +76,6 @@ async def create( response = await self._api.request( "POST", path, - json=request_data.jsonable_dict(exclude_none=True), + json=request_data.jsonable_dict(exclude_unset=True), ) return VacancyRequestResponse.model_validate(response.json()) diff --git a/huntflow_api_client/entities/webhooks.py b/huntflow_api_client/entities/webhooks.py index daa0106..a60d204 100644 --- a/huntflow_api_client/entities/webhooks.py +++ b/huntflow_api_client/entities/webhooks.py @@ -41,7 +41,7 @@ async def create(self, account_id: int, data: WebhookRequest) -> WebhookResponse :return: Information about the webhook """ path = f"/accounts/{account_id}/hooks" - response = await self._api.request("POST", path, json=data.jsonable_dict(exclude_none=True)) + response = await self._api.request("POST", path, json=data.jsonable_dict()) return WebhookResponse.model_validate(response.json()) async def delete(self, account_id: int, webhook_id: int) -> None: diff --git a/huntflow_api_client/models/consts.py b/huntflow_api_client/models/consts.py index 37bbb36..c6b57c0 100644 --- a/huntflow_api_client/models/consts.py +++ b/huntflow_api_client/models/consts.py @@ -1,5 +1,7 @@ from enum import Enum +from huntflow_api_client.utils import extend_enum + class WebhookEvent(str, Enum): APPLICANT = "APPLICANT" @@ -69,11 +71,15 @@ class FieldType(str, Enum): html = "html" -class AgreementState(str, Enum): +class AgreementStateRequest(str, Enum): not_sent = "not_sent" sent = "sent" accepted = "accepted" declined = "declined" + + +@extend_enum(AgreementStateRequest) +class AgreementStateResponse(str, Enum): send_error = "send_error" diff --git a/huntflow_api_client/models/request/token.py b/huntflow_api_client/models/request/token.py new file mode 100644 index 0000000..377c27e --- /dev/null +++ b/huntflow_api_client/models/request/token.py @@ -0,0 +1,7 @@ +from pydantic import Field + +from huntflow_api_client.models.common import JsonRequestModel + + +class RefreshTokenRequest(JsonRequestModel): + refresh_token: str = Field(..., description="Refresh token") diff --git a/huntflow_api_client/models/response/applicant_logs.py b/huntflow_api_client/models/response/applicant_logs.py index 34761eb..5cffc5a 100644 --- a/huntflow_api_client/models/response/applicant_logs.py +++ b/huntflow_api_client/models/response/applicant_logs.py @@ -20,6 +20,7 @@ Transparency, ) from huntflow_api_client.models.response.applicant_offers import ApplicantVacancyOffer +from huntflow_api_client.models.response.survey import SurveyTypeARespondent class BaseSurveySchemaType(BaseModel): @@ -35,6 +36,10 @@ class SurveySchemaTypeQLogResponse(BaseSurveySchemaType): title: Optional[str] = Field(..., description="Survey title") +class SurveySchemaTypeALogResponse(BaseSurveySchemaType): + pass + + class ApplicantLogSurveyQuestionary(BaseModel): id: int = Field(..., description="Survey questionary ID") survey: SurveySchemaTypeQLogResponse = Field(..., description="Survey schema") @@ -48,6 +53,16 @@ class ApplicantLogSurveyQuestionary(BaseModel): ) +class ApplicantLogSurveyAnswerTypeA(BaseModel): + id: int = Field(..., description="Survey questionary ID") + created: datetime = Field( + ..., + description="Date and time of creating an survey questionary of type A", + ) + respondent: SurveyTypeARespondent = Field(..., description="Who created the survey answer") + survey: SurveySchemaTypeALogResponse = Field(..., description="Survey schema") + + class EmailRecipient(BaseModel): type: Optional[EmailContactType] = Field(None, description="Type of the email contact") name: Optional[str] = Field( @@ -172,6 +187,10 @@ class ApplicantLogItem(BaseModel): None, description="Survey questionary", ) + survey_answer_of_type_a: Optional[ApplicantLogSurveyAnswerTypeA] = Field( + None, + description="Survey answer of type A object", + ) class ApplicantLogResponse(PaginatedResponse): diff --git a/huntflow_api_client/models/response/applicants.py b/huntflow_api_client/models/response/applicants.py index 5f2a8e5..9bb3e54 100644 --- a/huntflow_api_client/models/response/applicants.py +++ b/huntflow_api_client/models/response/applicants.py @@ -4,7 +4,7 @@ from pydantic import BaseModel, ConfigDict, Field, PositiveInt from huntflow_api_client.models.common import Applicant, PaginatedResponse -from huntflow_api_client.models.consts import AgreementState as AgreementStateEnum +from huntflow_api_client.models.consts import AgreementStateResponse as AgreementStateEnum class ApplicantTag(BaseModel): @@ -112,6 +112,7 @@ class ApplicantCreateResponse(Applicant): ) external: List[ApplicantResume] = Field(..., description="Applicant's resume") social: List[ApplicantSocial] = Field(..., description="List of applicant's social accounts") + reindex_job_id: str class ApplicantSearchItem(BaseModel): diff --git a/huntflow_api_client/models/response/token.py b/huntflow_api_client/models/response/token.py new file mode 100644 index 0000000..06efaec --- /dev/null +++ b/huntflow_api_client/models/response/token.py @@ -0,0 +1,12 @@ +from pydantic import BaseModel, Field + + +class RefreshTokenResponse(BaseModel): + access_token: str = Field(..., description="New access token") + token_type: str = Field(..., description="Token type") + expires_in: int = Field(..., description="Token lifetime in seconds") + refresh_token_expires_in: int = Field( + ..., + description="Refresh token lifetime in seconds", + ) + refresh_token: str = Field(..., description="New refresh token") diff --git a/huntflow_api_client/utils.py b/huntflow_api_client/utils.py new file mode 100644 index 0000000..48f685f --- /dev/null +++ b/huntflow_api_client/utils.py @@ -0,0 +1,13 @@ +from enum import Enum + + +def extend_enum(inherited_enum): + def wrapper(added_enum): + joined = {} + for item in inherited_enum: + joined[item.name] = item.value + for item in added_enum: + joined[item.name] = item.value + return Enum(added_enum.__name__, joined) + + return wrapper diff --git a/pyproject.toml b/pyproject.toml index 5d065be..f5c2ff8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,7 +1,7 @@ [project] name = "huntflow-api-client" -version = "2.13.2" +version = "2.13.3" description = "Huntflow API Client for Python" authors = [ {name = "Developers huntflow", email = "developer@huntflow.ru"}, diff --git a/tests/test_entities/test_applicants.py b/tests/test_entities/test_applicants.py index 1c46992..fbb5c1d 100644 --- a/tests/test_entities/test_applicants.py +++ b/tests/test_entities/test_applicants.py @@ -201,6 +201,7 @@ "verification_date": "2020-01-01T00:00:00+03:00", }, ], + "reindex_job_id": "12345", } APPLICANT_PATCH_REQUEST: Dict[str, Any] = {"first_name": "Newname", "social": []} APPLICANT_PATCH_RESPONSE: Dict[str, Any] = { diff --git a/tests/test_entities/test_production_calendar.py b/tests/test_entities/test_production_calendar.py index 6c1eb4f..815819e 100644 --- a/tests/test_entities/test_production_calendar.py +++ b/tests/test_entities/test_production_calendar.py @@ -110,7 +110,7 @@ async def test_get_non_working_days_in_period( ) -> None: httpx_mock.add_response( url=f"{VERSIONED_BASE_URL}/production_calendars/{CALENDAR_ID}/days/" - f"{DEADLINE_DATE.strftime('%Y-%m-%d')}?verbose=true", + f"{DEADLINE_DATE.strftime('%Y-%m-%d')}?verbose=false", json=NON_WORKING_DAYS_GET_RESPONSE, ) api_client = HuntflowAPI(BASE_URL, token_proxy=token_proxy) diff --git a/tests/test_entities/test_tokens.py b/tests/test_entities/test_tokens.py new file mode 100644 index 0000000..c0855f5 --- /dev/null +++ b/tests/test_entities/test_tokens.py @@ -0,0 +1,31 @@ +from pytest_httpx import HTTPXMock + +from huntflow_api_client import HuntflowAPI +from huntflow_api_client.entities import Token +from huntflow_api_client.models.request.token import RefreshTokenRequest +from huntflow_api_client.models.response.token import RefreshTokenResponse +from huntflow_api_client.tokens.proxy import HuntflowTokenProxy +from tests.api import BASE_URL, VERSIONED_BASE_URL + +REFRESH_TOKEN_RESPONSE = { + "access_token": "1234", + "token_type": "1234", + "expires_in": 1234, + "refresh_token_expires_in": 1234, + "refresh_token": "1234", +} + + +async def test_refresh_token( + httpx_mock: HTTPXMock, + token_proxy: HuntflowTokenProxy, +) -> None: + httpx_mock.add_response( + url=f"{VERSIONED_BASE_URL}/token/refresh", + json=REFRESH_TOKEN_RESPONSE, + ) + api_client = HuntflowAPI(BASE_URL, token_proxy=token_proxy) + tags = Token(api_client) + + response = await tags.update(data=RefreshTokenRequest(refresh_token="5678")) + assert response == RefreshTokenResponse(**REFRESH_TOKEN_RESPONSE) From ad8533396684416deda6646b8d162eb93205f05f Mon Sep 17 00:00:00 2001 From: Aleksandr Kroshko Date: Mon, 6 Apr 2026 11:05:55 +0300 Subject: [PATCH 2/4] DEV-22328: mypy fix --- huntflow_api_client/utils.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/huntflow_api_client/utils.py b/huntflow_api_client/utils.py index 48f685f..6cb6c3e 100644 --- a/huntflow_api_client/utils.py +++ b/huntflow_api_client/utils.py @@ -1,9 +1,12 @@ from enum import Enum +from typing import Any, Callable, Dict, Type, TypeVar +T = TypeVar("T", bound=Enum) -def extend_enum(inherited_enum): - def wrapper(added_enum): - joined = {} + +def extend_enum(inherited_enum: Type[T]) -> Callable: + def wrapper(added_enum: Type[T]) -> Enum: + joined: Dict[str, Any] = {} for item in inherited_enum: joined[item.name] = item.value for item in added_enum: From 6d226e7c4b28713724e89eba2cadf36129938b34 Mon Sep 17 00:00:00 2001 From: Aleksandr Kroshko Date: Mon, 6 Apr 2026 17:56:45 +0300 Subject: [PATCH 3/4] DEV-22328: fix by comments --- huntflow_api_client/entities/token.py | 4 ++-- huntflow_api_client/models/common.py | 1 + huntflow_api_client/models/response/applicant_logs.py | 11 +---------- huntflow_api_client/models/response/applicants.py | 1 - tests/test_entities/test_applicants.py | 1 - 5 files changed, 4 insertions(+), 14 deletions(-) diff --git a/huntflow_api_client/entities/token.py b/huntflow_api_client/entities/token.py index 644005d..7368782 100644 --- a/huntflow_api_client/entities/token.py +++ b/huntflow_api_client/entities/token.py @@ -10,8 +10,8 @@ async def update(self, data: RefreshTokenRequest) -> RefreshTokenResponse: API method reference https://api.huntflow.ru/latest/docs#post-/token/refresh - :param data: token request data - :return: refreshed token data + :param data: Token request data + :return: Refreshed token data """ response = await self._api.request( "POST", diff --git a/huntflow_api_client/models/common.py b/huntflow_api_client/models/common.py index 02bc7da..0a63297 100644 --- a/huntflow_api_client/models/common.py +++ b/huntflow_api_client/models/common.py @@ -170,6 +170,7 @@ class EmailRecipient(BaseModel): name: Optional[str] = Field( None, description="Name of email recipient", + alias="displayName", ) email: str = Field(..., description="Email address") diff --git a/huntflow_api_client/models/response/applicant_logs.py b/huntflow_api_client/models/response/applicant_logs.py index 5cffc5a..24c4896 100644 --- a/huntflow_api_client/models/response/applicant_logs.py +++ b/huntflow_api_client/models/response/applicant_logs.py @@ -6,6 +6,7 @@ from huntflow_api_client.models.common import ( ApplicantOffer, CalendarEventAttendeeResponse, + EmailRecipient, File, PaginatedResponse, VacancyQuotaItem, @@ -15,7 +16,6 @@ CalendarEventReminderMethod, CalendarEventStatus, CalendarEventType, - EmailContactType, SurveyType, Transparency, ) @@ -63,15 +63,6 @@ class ApplicantLogSurveyAnswerTypeA(BaseModel): survey: SurveySchemaTypeALogResponse = Field(..., description="Survey schema") -class EmailRecipient(BaseModel): - type: Optional[EmailContactType] = Field(None, description="Type of the email contact") - name: Optional[str] = Field( - None, - description="Name of email recipient", - ) - email: str = Field(..., description="Email address") - - class ApplicantLogAccountInfo(BaseModel): id: int = Field(..., description="ID of the user who created the log") name: str = Field(..., description="Name of the user who created the log") diff --git a/huntflow_api_client/models/response/applicants.py b/huntflow_api_client/models/response/applicants.py index 9bb3e54..5ae7b5e 100644 --- a/huntflow_api_client/models/response/applicants.py +++ b/huntflow_api_client/models/response/applicants.py @@ -112,7 +112,6 @@ class ApplicantCreateResponse(Applicant): ) external: List[ApplicantResume] = Field(..., description="Applicant's resume") social: List[ApplicantSocial] = Field(..., description="List of applicant's social accounts") - reindex_job_id: str class ApplicantSearchItem(BaseModel): diff --git a/tests/test_entities/test_applicants.py b/tests/test_entities/test_applicants.py index fbb5c1d..1c46992 100644 --- a/tests/test_entities/test_applicants.py +++ b/tests/test_entities/test_applicants.py @@ -201,7 +201,6 @@ "verification_date": "2020-01-01T00:00:00+03:00", }, ], - "reindex_job_id": "12345", } APPLICANT_PATCH_REQUEST: Dict[str, Any] = {"first_name": "Newname", "social": []} APPLICANT_PATCH_RESPONSE: Dict[str, Any] = { From 9d694b7b5f2e91104a873fa9c9ce3cfd1b5bb776 Mon Sep 17 00:00:00 2001 From: Aleksandr Kroshko Date: Mon, 6 Apr 2026 18:02:16 +0300 Subject: [PATCH 4/4] DEV-22328: token deleted --- huntflow_api_client/entities/__init__.py | 2 -- huntflow_api_client/entities/token.py | 21 ------------- huntflow_api_client/models/request/token.py | 7 ----- huntflow_api_client/models/response/token.py | 12 -------- tests/test_entities/test_tokens.py | 31 -------------------- 5 files changed, 73 deletions(-) delete mode 100644 huntflow_api_client/entities/token.py delete mode 100644 huntflow_api_client/models/request/token.py delete mode 100644 huntflow_api_client/models/response/token.py delete mode 100644 tests/test_entities/test_tokens.py diff --git a/huntflow_api_client/entities/__init__.py b/huntflow_api_client/entities/__init__.py index cdff254..04b4b85 100644 --- a/huntflow_api_client/entities/__init__.py +++ b/huntflow_api_client/entities/__init__.py @@ -25,7 +25,6 @@ from huntflow_api_client.entities.survey_type_a import SurveyTypeA from huntflow_api_client.entities.survey_type_q import SurveyTypeQ from huntflow_api_client.entities.tags import AccountTag, ApplicantTag -from huntflow_api_client.entities.token import Token from huntflow_api_client.entities.user_settings import UserSettings from huntflow_api_client.entities.users import User from huntflow_api_client.entities.users_management import UsersManagement @@ -62,7 +61,6 @@ "Resume", "SurveyTypeA", "SurveyTypeQ", - "Token", "User", "UsersManagement", "UserSettings", diff --git a/huntflow_api_client/entities/token.py b/huntflow_api_client/entities/token.py deleted file mode 100644 index 7368782..0000000 --- a/huntflow_api_client/entities/token.py +++ /dev/null @@ -1,21 +0,0 @@ -from huntflow_api_client.entities.base import BaseEntity, UpdateEntityMixin -from huntflow_api_client.models.request.token import RefreshTokenRequest -from huntflow_api_client.models.response.token import RefreshTokenResponse - - -class Token(BaseEntity, UpdateEntityMixin): - - async def update(self, data: RefreshTokenRequest) -> RefreshTokenResponse: - """ - API method reference - https://api.huntflow.ru/latest/docs#post-/token/refresh - - :param data: Token request data - :return: Refreshed token data - """ - response = await self._api.request( - "POST", - "/token/refresh", - json=data.jsonable_dict(), - ) - return RefreshTokenResponse.model_validate(response.json()) diff --git a/huntflow_api_client/models/request/token.py b/huntflow_api_client/models/request/token.py deleted file mode 100644 index 377c27e..0000000 --- a/huntflow_api_client/models/request/token.py +++ /dev/null @@ -1,7 +0,0 @@ -from pydantic import Field - -from huntflow_api_client.models.common import JsonRequestModel - - -class RefreshTokenRequest(JsonRequestModel): - refresh_token: str = Field(..., description="Refresh token") diff --git a/huntflow_api_client/models/response/token.py b/huntflow_api_client/models/response/token.py deleted file mode 100644 index 06efaec..0000000 --- a/huntflow_api_client/models/response/token.py +++ /dev/null @@ -1,12 +0,0 @@ -from pydantic import BaseModel, Field - - -class RefreshTokenResponse(BaseModel): - access_token: str = Field(..., description="New access token") - token_type: str = Field(..., description="Token type") - expires_in: int = Field(..., description="Token lifetime in seconds") - refresh_token_expires_in: int = Field( - ..., - description="Refresh token lifetime in seconds", - ) - refresh_token: str = Field(..., description="New refresh token") diff --git a/tests/test_entities/test_tokens.py b/tests/test_entities/test_tokens.py deleted file mode 100644 index c0855f5..0000000 --- a/tests/test_entities/test_tokens.py +++ /dev/null @@ -1,31 +0,0 @@ -from pytest_httpx import HTTPXMock - -from huntflow_api_client import HuntflowAPI -from huntflow_api_client.entities import Token -from huntflow_api_client.models.request.token import RefreshTokenRequest -from huntflow_api_client.models.response.token import RefreshTokenResponse -from huntflow_api_client.tokens.proxy import HuntflowTokenProxy -from tests.api import BASE_URL, VERSIONED_BASE_URL - -REFRESH_TOKEN_RESPONSE = { - "access_token": "1234", - "token_type": "1234", - "expires_in": 1234, - "refresh_token_expires_in": 1234, - "refresh_token": "1234", -} - - -async def test_refresh_token( - httpx_mock: HTTPXMock, - token_proxy: HuntflowTokenProxy, -) -> None: - httpx_mock.add_response( - url=f"{VERSIONED_BASE_URL}/token/refresh", - json=REFRESH_TOKEN_RESPONSE, - ) - api_client = HuntflowAPI(BASE_URL, token_proxy=token_proxy) - tags = Token(api_client) - - response = await tags.update(data=RefreshTokenRequest(refresh_token="5678")) - assert response == RefreshTokenResponse(**REFRESH_TOKEN_RESPONSE)