diff --git a/hrflow/core/validation.py b/hrflow/core/validation.py index 0c68472..3f6e3b6 100644 --- a/hrflow/core/validation.py +++ b/hrflow/core/validation.py @@ -91,6 +91,14 @@ def validate_limit(value): return value +def validate_score(value): + if not isinstance(value, (int, float)): + raise TypeError("score must be a number, not {}".format(type(value).__name__)) + if value <= 0 or value >= 1: + raise ValueError("score must be between 0 and 1 (exclusive)") + return value + + def validate_provider_keys(value): if not value or not all(isinstance(elt, str) for elt in value): raise TypeError("provider_ids must contain list of strings") diff --git a/hrflow/hrflow.py b/hrflow/hrflow.py index 723a3b9..5def4e3 100755 --- a/hrflow/hrflow.py +++ b/hrflow/hrflow.py @@ -11,6 +11,7 @@ from .text import Text from .tracking import Tracking from .webhook import Webhook +from .workflow import Workflow CLIENT_API_URL = "https://api.hrflow.ai/v1/" @@ -57,6 +58,7 @@ def __init__( self.board = Board(self) self.tracking = Tracking(self) self.rating = Rating(self) + self.workflow = Workflow(self) def _create_request_url(self, resource_url): return "{api_endpoint}{resource_url}".format( diff --git a/hrflow/job/__init__.py b/hrflow/job/__init__.py index 75f792f..9f1c20c 100644 --- a/hrflow/job/__init__.py +++ b/hrflow/job/__init__.py @@ -1,17 +1,20 @@ from .asking import JobAsking from .embedding import JobEmbedding +from .grading import JobGrading from .matching import JobMatching from .parsing import JobParsing from .reasoning import JobReasoning from .scoring import JobScoring from .searching import JobSearching from .storing import JobStoring +from .upskilling import JobUpskilling class Job: def __init__(self, client): self.client = client self.asking = JobAsking(self.client) + self.grading = JobGrading(self.client) self.parsing = JobParsing(self.client) self.embedding = JobEmbedding(self.client) self.searching = JobSearching(self.client) @@ -19,3 +22,4 @@ def __init__(self, client): self.reasoning = JobReasoning(self.client) self.storing = JobStoring(self.client) self.matching = JobMatching(self.client) + self.upskilling = JobUpskilling(self.client) diff --git a/hrflow/job/grading.py b/hrflow/job/grading.py new file mode 100644 index 0000000..d2faa30 --- /dev/null +++ b/hrflow/job/grading.py @@ -0,0 +1,62 @@ +import typing as t + +from ..core.rate_limit import rate_limiter +from ..core.validation import ( + KEY_REGEX, + validate_key, + validate_reference, + validate_response, +) + + +class JobGrading: + def __init__(self, api): + """Initialize the JobGrading class with the provided API client.""" + self.client = api + + @rate_limiter + def get( + self, + algorithm_key: str, + board_key: str, + source_key: str, + job_key: t.Optional[str] = None, + job_reference: t.Optional[str] = None, + profile_key: t.Optional[str] = None, + profile_reference: t.Optional[str] = None, + ): + """ + Grade Jobs indexed in a Board for a Profile + (https://api.hrflow.ai/v1/job/grading). + + Args: + algorithm_key: + The key of the grading algorithm to use. + board_key: + The key of the Board where the job is indexed. + source_key: + The key of the Source where the profile is indexed. + job_key: + (Optional) The Job unique identifier. + job_reference: + (Optional) The Job reference chosen by the customer. + profile_key: + (Optional) The Profile unique identifier. + profile_reference: + (Optional) The Profile reference chosen by the customer. + + Returns: + The grading information for the job, based on the specified profile. + """ + query_params = { + "algorithm_key": algorithm_key, + "board_key": validate_key("Board", board_key, regex=KEY_REGEX), + "job_key": validate_key("Key", job_key, regex=KEY_REGEX), + "job_reference": validate_reference(job_reference), + "source_key": validate_key("Source", source_key, regex=KEY_REGEX), + "profile_key": validate_key("Key", profile_key, regex=KEY_REGEX), + "profile_reference": validate_reference(profile_reference), + } + + response = self.client.get("job/grading", query_params) + return validate_response(response) diff --git a/hrflow/job/upskilling.py b/hrflow/job/upskilling.py new file mode 100644 index 0000000..f39ebab --- /dev/null +++ b/hrflow/job/upskilling.py @@ -0,0 +1,64 @@ +import typing as t + +from ..core.rate_limit import rate_limiter +from ..core.validation import ( + KEY_REGEX, + validate_key, + validate_reference, + validate_response, + validate_score, +) + + +class JobUpskilling: + def __init__(self, api): + """Initialize the JobUpskilling class with the provided API client.""" + self.client = api + + @rate_limiter + def get( + self, + board_key: str, + source_key: str, + score: float, + job_key: t.Optional[str] = None, + job_reference: t.Optional[str] = None, + profile_key: t.Optional[str] = None, + profile_reference: t.Optional[str] = None, + ) -> t.Dict[str, t.Any]: + """ + Explain a Job recommendation for a Profile + (https://api.hrflow.ai/v1/job/upskilling). + + Args: + board_key: + The key of the Board where the job is indexed. + source_key: + The key of the Source where the profile is indexed. + score: + The recommendation score. Must be between 0 and 1 + (exclusive). + job_key: + (Optional) The Job unique identifier. + job_reference: + (Optional) The Job reference chosen by the customer. + profile_key: + (Optional) The Profile unique identifier. + profile_reference: + (Optional) The Profile reference chosen by the customer. + + Returns: + Explanation of why the job is recommended for the profile. + """ + query_params = { + "board_key": validate_key("Board", board_key, regex=KEY_REGEX), + "source_key": validate_key("Source", source_key, regex=KEY_REGEX), + "score": validate_score(score), + "job_key": validate_key("Key", job_key, regex=KEY_REGEX), + "job_reference": validate_reference(job_reference), + "profile_key": validate_key("Key", profile_key, regex=KEY_REGEX), + "profile_reference": validate_reference(profile_reference), + } + + response = self.client.get("job/upskilling", query_params) + return validate_response(response) diff --git a/hrflow/profile/__init__.py b/hrflow/profile/__init__.py index 1f5016b..efb1aaf 100644 --- a/hrflow/profile/__init__.py +++ b/hrflow/profile/__init__.py @@ -12,6 +12,7 @@ from .searching import ProfileSearching from .storing import ProfileStoring from .unfolding import ProfileUnfolding +from .upskilling import ProfileUpskilling class Profile(object): @@ -39,3 +40,4 @@ def __init__(self, client): self.unfolding = ProfileUnfolding(self.client) self.matching = ProfileMatching(self.client) self.grading = ProfileGrading(self.client) + self.upskilling = ProfileUpskilling(self.client) diff --git a/hrflow/profile/upskilling.py b/hrflow/profile/upskilling.py new file mode 100644 index 0000000..b5cd051 --- /dev/null +++ b/hrflow/profile/upskilling.py @@ -0,0 +1,64 @@ +import typing as t + +from ..core.rate_limit import rate_limiter +from ..core.validation import ( + KEY_REGEX, + validate_key, + validate_reference, + validate_response, + validate_score, +) + + +class ProfileUpskilling: + def __init__(self, api): + """Initialize the ProfileUpskilling class with the provided API client.""" + self.client = api + + @rate_limiter + def get( + self, + source_key: str, + board_key: str, + score: float, + profile_key: t.Optional[str] = None, + profile_reference: t.Optional[str] = None, + job_key: t.Optional[str] = None, + job_reference: t.Optional[str] = None, + ) -> t.Dict[str, t.Any]: + """ + Explain a Profile recommendation for a Job + (https://api.hrflow.ai/v1/profile/upskilling). + + Args: + source_key: + The key of the Source where the profile is indexed. + board_key: + The key of the Board where the job is indexed. + score: + The recommendation score. Must be between 0 and 1 + (exclusive). + profile_key: + (Optional) The Profile unique identifier. + profile_reference: + (Optional) The Profile reference chosen by the customer. + job_key: + (Optional) The Job unique identifier. + job_reference: + (Optional) The Job reference chosen by the customer. + + Returns: + Explanation of why the profile is recommended for the job. + """ + query_params = { + "source_key": validate_key("Source", source_key, regex=KEY_REGEX), + "board_key": validate_key("Board", board_key, regex=KEY_REGEX), + "score": validate_score(score), + "profile_key": validate_key("Key", profile_key, regex=KEY_REGEX), + "profile_reference": validate_reference(profile_reference), + "job_key": validate_key("Key", job_key, regex=KEY_REGEX), + "job_reference": validate_reference(job_reference), + } + + response = self.client.get("profile/upskilling", query_params) + return validate_response(response) diff --git a/hrflow/text/__init__.py b/hrflow/text/__init__.py index 2e242bd..a9e7843 100644 --- a/hrflow/text/__init__.py +++ b/hrflow/text/__init__.py @@ -1,6 +1,7 @@ """Profile related calls.""" from .embedding import TextEmbedding +from .geocoding import TextGeocoding from .imaging import TextImaging from .linking import TextLinking from .ocr import TextOCR @@ -29,3 +30,4 @@ def __init__(self, client): self.tagging = TextTagging(self.client) self.ocr = TextOCR(self.client) self.imaging = TextImaging(self.client) + self.geocoding = TextGeocoding(self.client) diff --git a/hrflow/text/geocoding.py b/hrflow/text/geocoding.py new file mode 100644 index 0000000..7677944 --- /dev/null +++ b/hrflow/text/geocoding.py @@ -0,0 +1,30 @@ +import typing as t + +from ..core.rate_limit import rate_limiter +from ..core.validation import validate_response + + +class TextGeocoding: + """Manage text geocoding calls.""" + + def __init__(self, api): + """Init.""" + self.client = api + + @rate_limiter + def post(self, text: str) -> t.Dict[str, t.Any]: + """ + Geocode a location text. Retrieve geojson data for a textual location + input. + (https://api.hrflow.ai/v1/text/geocoding). + + Args: + text: + The location text to geocode. + + Returns: + Geojson data for the given location text. + """ + payload = {"text": text} + response = self.client.post("text/geocoding", json=payload) + return validate_response(response) diff --git a/hrflow/workflow/__init__.py b/hrflow/workflow/__init__.py new file mode 100644 index 0000000..37a1433 --- /dev/null +++ b/hrflow/workflow/__init__.py @@ -0,0 +1,47 @@ +from ..core.rate_limit import rate_limiter +from ..core.validation import ( + ORDER_BY_VALUES, + validate_limit, + validate_page, + validate_response, + validate_value, +) + + +class Workflow(object): + def __init__(self, client): + self.client = client + + @rate_limiter + def list(self, name=None, environment=None, page=1, limit=30, order_by="desc"): + """ + Find Workflows in a Workspace. + (https://api.hrflow.ai/v1/workflows). + + Args: + name: + (Optional) The Workflow name. If empty, the API + will return all possible values. + environment: + (Optional) The deployment context (production, + staging, test). Returns all values if omitted. + page: (default to 1) + API page offset. + limit: (default to 30) + Number of entities per page. + order_by: (default to "desc") + Order results by creation date: "asc" or "desc". + + Returns: + List of workflows matching the given filters. + """ + query_params = {} + if name: + query_params["name"] = name + if environment: + query_params["environment"] = environment + query_params["page"] = validate_page(page) + query_params["limit"] = validate_limit(limit) + query_params["order_by"] = validate_value(order_by, ORDER_BY_VALUES, "order by") + response = self.client.get("workflows", query_params) + return validate_response(response)