Skip to content

Commit 424d826

Browse files
authored
Add company enrichment service (#15)
1 parent 12e2e13 commit 424d826

File tree

5 files changed

+205
-0
lines changed

5 files changed

+205
-0
lines changed

src/abstract_api/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from typing import Final
22

33
from .avatars import Avatars
4+
from .company_enrichment import CompanyEnrichment
45
from .email_validation import EmailValidation
56
from .exchange_rates import ExchangeRates
67
from .holidays import Holidays
@@ -11,6 +12,7 @@
1112

1213
__all__: Final[list[str]] = [
1314
"Avatars",
15+
"CompanyEnrichment",
1416
"EmailValidation",
1517
"ExchangeRates",
1618
"Holidays",
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
from typing import Final
2+
3+
from .company_enrichment import CompanyEnrichment
4+
from .company_enrichment_response import CompanyEnrichmentResponse
5+
6+
__all__: Final[list[str]] = [
7+
"CompanyEnrichment",
8+
"CompanyEnrichmentResponse"
9+
]
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
from typing import Iterable
2+
3+
from abstract_api.bases import BaseService
4+
from abstract_api.exceptions import ClientRequestError, ResponseParseError
5+
6+
from .company_enrichment_response import CompanyEnrichmentResponse
7+
from .response_fields import RESPONSE_FIELDS
8+
9+
10+
class CompanyEnrichment(BaseService):
11+
"""AbstractAPI company enrichment service.
12+
13+
Used to find a company's details using its domain.
14+
15+
Attributes:
16+
_subdomain: Company enrichment service subdomain.
17+
"""
18+
_subdomain: str = "companyenrichment"
19+
20+
def __init__(
21+
self,
22+
*,
23+
response_fields: Iterable[str] | None = None,
24+
**kwargs
25+
) -> None:
26+
"""Constructs a CompanyEnrichment.
27+
28+
Args:
29+
response_fields: Selected response fields.
30+
"""
31+
super().__init__(**kwargs)
32+
if response_fields is not None:
33+
self.response_fields = frozenset(response_fields)
34+
else:
35+
self.response_fields = RESPONSE_FIELDS
36+
37+
@staticmethod
38+
def _validate_response_fields(response_fields: Iterable[str]) -> None:
39+
"""Validates whether all the given fields are acceptable.
40+
41+
Args:
42+
response_fields: Selected response fields.
43+
"""
44+
for field in response_fields:
45+
if field not in RESPONSE_FIELDS:
46+
raise ClientRequestError(
47+
f"Field '{field}' is not a valid response field for "
48+
f"Company Enrichment service."
49+
)
50+
51+
@property
52+
def response_fields(self) -> frozenset[str]:
53+
"""Gets selected response fields."""
54+
if self._response_fields:
55+
return self._response_fields
56+
return RESPONSE_FIELDS
57+
58+
@response_fields.setter
59+
def response_fields(self, fields: Iterable[str]) -> None:
60+
"""Sets selected response fields."""
61+
self._validate_response_fields(fields)
62+
self._response_fields = frozenset(fields)
63+
64+
@staticmethod
65+
def _response_fields_as_param(response_fields: Iterable[str]) -> str:
66+
"""Builds 'fields' URL query parameter.
67+
68+
Builds a string that contains selected response fields to be used
69+
as a URL query parameter.
70+
71+
Args:
72+
response_fields: Selected response fields.
73+
74+
Returns:
75+
Comma-separated string with all selected response fields.
76+
"""
77+
return ",".join(response_fields)
78+
79+
def check(
80+
self,
81+
domain: str,
82+
fields: Iterable[str] | None = None
83+
) -> CompanyEnrichmentResponse:
84+
"""Finds a company's details using its domain.
85+
86+
Args:
87+
domain: The domain of the company you want to get data from.
88+
fields: Selected response fields.
89+
90+
Returns:
91+
CompanyEnrichmentResponse representing API call response.
92+
"""
93+
if fields:
94+
self._validate_response_fields(fields)
95+
response_fields = frozenset(fields)
96+
else:
97+
response_fields = self.response_fields
98+
99+
# TODO: Handle request errors.
100+
response = self._service_request(
101+
domain=domain,
102+
fields=self._response_fields_as_param(response_fields)
103+
)
104+
105+
try:
106+
company_enrichment_response = CompanyEnrichmentResponse(
107+
response=response,
108+
response_fields=response_fields
109+
)
110+
except Exception as e:
111+
raise ResponseParseError(
112+
"Failed to parse response as CompanyEnrichmentResponse"
113+
) from e
114+
115+
return company_enrichment_response
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
from typing import TYPE_CHECKING
2+
3+
import requests.models
4+
5+
from abstract_api.bases import JSONResponse
6+
7+
8+
class CompanyEnrichmentResponse(JSONResponse):
9+
"""Company enrichment service response."""
10+
11+
def __init__(
12+
self,
13+
response: requests.models.Response,
14+
response_fields: frozenset[str]
15+
) -> None:
16+
"""Initializes a new CompanyEnrichmentResponse."""
17+
super().__init__(response)
18+
self._response_fields = response_fields
19+
not_in_response = object()
20+
for field in response_fields:
21+
if TYPE_CHECKING:
22+
assert isinstance(self.meta.body_json, dict)
23+
value = self.meta.body_json.get(field, not_in_response)
24+
# Set property only if field was returned
25+
if value is not not_in_response:
26+
setattr(self, f"_{field}", value)
27+
28+
@property
29+
def name(self) -> str | None:
30+
"""The name of the company."""
31+
return self._get_response_field("name")
32+
33+
@property
34+
def domain(self) -> str | None:
35+
"""The domain the company website is hosted on."""
36+
return self._get_response_field("domain")
37+
38+
@property
39+
def year_founded(self) -> int | None:
40+
"""The year the company was founded."""
41+
return self._get_response_field("year_founded")
42+
43+
@property
44+
def industry(self) -> str | None:
45+
"""The industry the company is operating in."""
46+
return self._get_response_field("industry")
47+
48+
@property
49+
def employees_count(self) -> str | None:
50+
"""The approximate number of employees of the company."""
51+
return self._get_response_field("employees_count")
52+
53+
@property
54+
def locality(self) -> str | None:
55+
"""The city or region he company headquarter is based in."""
56+
return self._get_response_field("locality")
57+
58+
@property
59+
def country(self) -> str | None:
60+
"""The country the company is based in."""
61+
return self._get_response_field("country")
62+
63+
@property
64+
def linkedin_url(self) -> str | None:
65+
"""The LinkedIn URL of the company."""
66+
return self._get_response_field("linkedin_url")
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
"""Response fields of company enrichment service endpoint."""
2+
3+
4+
RESPONSE_FIELDS: frozenset[str] = frozenset({
5+
"name",
6+
"domain",
7+
"year_founded",
8+
"industry",
9+
"employees_count",
10+
"locality",
11+
"country",
12+
"linkedin_url"
13+
})

0 commit comments

Comments
 (0)