Skip to content

Commit c707b4f

Browse files
feat: add validation for profile searching & scoring in utils
1 parent 6d91cef commit c707b4f

3 files changed

Lines changed: 213 additions & 0 deletions

File tree

hrflow/utils/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
# noqa: F401
22
from .evaluation import generate_parsing_evaluation_report, parsing_evaluator
3+
from .scoring import is_valid_for_scoring
4+
from .searching import is_valid_for_searching
35
from .storing import get_all_jobs, get_all_profiles

hrflow/utils/scoring.py

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
import typing as t
2+
3+
from ..hrflow import Hrflow
4+
from ..schemas import Education, Experience, HrFlowProfile
5+
6+
7+
def is_valid_experiences_for_scoring(
8+
experience_list: t.Optional[t.List[Experience]],
9+
) -> bool:
10+
"""
11+
Check if a list of experiences is valid for scoring
12+
13+
Args:
14+
experience_list: <list>
15+
List of experiences to check
16+
Return:
17+
<bool> True if the list of experiences is valid for
18+
scoring, False otherwise
19+
"""
20+
for experience in experience_list:
21+
if experience.title:
22+
return True
23+
24+
return False
25+
26+
27+
def is_valid_educations_for_scoring(
28+
education_list: t.Optional[t.List[Education]],
29+
) -> bool:
30+
for education in education_list:
31+
if education.title or education.school:
32+
return True
33+
return False
34+
35+
36+
def is_valid_for_scoring(
37+
client: Hrflow,
38+
profile: t.Optional[t.Union[t.Dict, HrFlowProfile]] = None,
39+
source_key: t.Optional[str] = None,
40+
profile_key: t.Optional[str] = None,
41+
profile_reference: t.Optional[str] = None,
42+
) -> bool:
43+
"""
44+
Check if a profile is valid for scoring
45+
46+
Based on the following schemas https://developers.hrflow.ai/docs/profiles-scoring
47+
48+
Args:
49+
client: <Hrflow>
50+
Hrflow client
51+
profile: <dict> or <HrFlowProfile>
52+
Profile to check. Can be not provided if source_key,
53+
profile_key or profile_reference are provided
54+
source_key: <str>
55+
Source key. If provided, profile_key or
56+
profile_reference must be also provided.
57+
profile_key: <str>
58+
Profile key. If provided, profile_reference must be None
59+
profile_reference: <str>
60+
Profile reference. If provided, profile_key must be None
61+
Return:
62+
<bool> True if the profile is valid for scoring,
63+
False otherwise
64+
"""
65+
# Check parameters and fetch profile if needed
66+
if profile is None:
67+
if source_key is None:
68+
raise ValueError("profile or source_key must be provided")
69+
elif profile_key is None and profile_reference is None:
70+
raise ValueError("profile_key or profile_reference must be provided")
71+
72+
response = client.profile.storing.get(
73+
source_key=source_key, key=profile_key, reference=profile_reference
74+
)
75+
if response["code"] >= 400:
76+
message = response["message"]
77+
raise ValueError(f"Error while fetching profile: {message}")
78+
profile = response["data"]
79+
else:
80+
if (
81+
source_key is not None
82+
or profile_key is not None
83+
or profile_reference is not None
84+
):
85+
86+
raise ValueError(
87+
"If you provide a profile, you can't provide source_key, profile_key "
88+
"or profile_reference"
89+
)
90+
91+
if isinstance(profile, dict):
92+
profile = HrFlowProfile.parse_obj(profile)
93+
94+
if not isinstance(profile, HrFlowProfile):
95+
raise ValueError("profile must be a dict or a HrFlowProfile object")
96+
97+
# Check if profile is valid for scoring
98+
return (
99+
is_valid_experiences_for_scoring(profile.experiences)
100+
or is_valid_educations_for_scoring(profile.educations)
101+
or bool(profile.summary)
102+
or bool(profile.skills)
103+
or bool(profile.tasks)
104+
)

hrflow/utils/searching.py

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
import typing as t
2+
3+
from ..hrflow import Hrflow
4+
from ..schemas import HrFlowProfile, ProfileInfo
5+
6+
7+
def is_valid_info_for_searching(info: ProfileInfo) -> bool:
8+
"""
9+
Check if the info part of a profile is valid for searching
10+
11+
Based on the following schemas https://developers.hrflow.ai/docs/profiles-searching
12+
13+
Args:
14+
info: <ProfileInfo>
15+
Info part of the profile
16+
"""
17+
if not isinstance(info, ProfileInfo):
18+
raise ValueError("info must be a ProfileInfo object")
19+
20+
first_name_score = 1 if info.first_name else 0
21+
last_name_score = 1 if info.last_name else 0
22+
phone_score = 1 if info.phone else 0
23+
date_birth_score = 1 if info.date_birth else 0
24+
gender_score = 1 if info.gender else 0
25+
summary_score = 1 if info.summary else 0
26+
urls_score = 1 if info.urls else 0
27+
location_score = 1 if info.location else 0
28+
29+
info_score = (
30+
first_name_score
31+
+ last_name_score
32+
+ phone_score
33+
+ date_birth_score
34+
+ gender_score
35+
+ summary_score
36+
+ urls_score
37+
+ location_score
38+
)
39+
info_score = info_score / 8
40+
has_person = info.first_name and info.last_name
41+
42+
return info.email or has_person or info_score >= 0.5
43+
44+
45+
def is_valid_for_searching(
46+
client: Hrflow,
47+
profile: t.Optional[t.Union[t.Dict, HrFlowProfile]] = None,
48+
source_key: t.Optional[str] = None,
49+
profile_key: t.Optional[str] = None,
50+
profile_reference: t.Optional[str] = None,
51+
) -> bool:
52+
"""
53+
Check if a profile is valid for searching
54+
55+
Based on the following schemas https://developers.hrflow.ai/docs/profiles-searching
56+
57+
Args:
58+
client: <Hrflow>
59+
Hrflow client
60+
profile: <dict> or <HrFlowProfile>
61+
Profile to check. Can be not provided if source_key,
62+
profile_key or profile_reference are provided
63+
source_key: <str>
64+
Source key. If provided, profile_key or
65+
profile_reference must be also provided.
66+
profile_key: <str>
67+
Profile key. If provided, profile_reference must be None
68+
profile_reference: <str>
69+
Profile reference. If provided, profile_key must be None
70+
Return:
71+
<bool> True if the profile is valid for searching,
72+
False otherwise
73+
"""
74+
# Check parameters and fetch profile if needed
75+
if profile is None:
76+
if source_key is None:
77+
raise ValueError("profile or source_key must be provided")
78+
elif profile_key is None and profile_reference is None:
79+
raise ValueError("profile_key or profile_reference must be provided")
80+
81+
response = client.profile.storing.get(
82+
source_key=source_key, key=profile_key, reference=profile_reference
83+
)
84+
if response["code"] >= 400:
85+
message = response["message"]
86+
raise ValueError(f"Error while fetching profile: {message}")
87+
profile = response["data"]
88+
else:
89+
if (
90+
source_key is not None
91+
or profile_key is not None
92+
or profile_reference is not None
93+
):
94+
95+
raise ValueError(
96+
"If you provide a profile, you can't provide source_key, profile_key "
97+
"or profile_reference"
98+
)
99+
100+
if isinstance(profile, dict):
101+
profile = HrFlowProfile.parse_obj(profile)
102+
103+
if not isinstance(profile, HrFlowProfile):
104+
raise ValueError("profile must be a dict or a HrFlowProfile object")
105+
106+
# Check if profile is valid for searching
107+
return is_valid_info_for_searching(profile.info) and bool(profile.text)

0 commit comments

Comments
 (0)