Skip to content

Commit

Permalink
Source Zoho CRM: Set airbyte type to string for zoho autonumbers when…
Browse files Browse the repository at this point in the history
… they include prefix or suffix #23818 (#24034)

* feature: correctly set autonumber type if it contains prefix or suffix

Zoho connector assumes any autonumber data type maps to airbyte's
big_integer. But that is not true as in Zoho you can create incremental
fields with strings in them via the prefix/suffix config params. Taking
this into account we choose string format in case prefix and suffix are
not empty.

* fix unit test and bump connector version

* correct auto_numbe ref

* update docker python base and fix auth

* fix python version file

* fix tests and validate with integration test

* fix  flake

* auto-bump connector version

---------

Co-authored-by: Gerard Clos <clos.gerard@gmail.com>
Co-authored-by: Octavia Squidington III <octavia-squidington-iii@users.noreply.github.com>
  • Loading branch information
3 people authored and erohmensing committed Mar 22, 2023
1 parent a938384 commit a51ac46
Show file tree
Hide file tree
Showing 13 changed files with 123 additions and 57 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2343,7 +2343,7 @@
- name: ZohoCRM
sourceDefinitionId: 4942d392-c7b5-4271-91f9-3b4f4e51eb3e
dockerRepository: airbyte/source-zoho-crm
dockerImageTag: 0.1.0
dockerImageTag: 0.1.1
documentationUrl: https://docs.airbyte.com/integrations/sources/zoho-crm
icon: zohocrm.svg
sourceType: api
Expand Down
8 changes: 3 additions & 5 deletions airbyte-config/init/src/main/resources/seed/source_specs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17215,7 +17215,7 @@
supportsNormalization: false
supportsDBT: false
supported_destination_sync_modes: []
- dockerImage: "airbyte/source-zoho-crm:0.1.0"
- dockerImage: "airbyte/source-zoho-crm:0.1.1"
spec:
documentationUrl: "https://docs.airbyte.com/integrations/sources/zoho-crm"
connectionSpecification:
Expand All @@ -17229,7 +17229,7 @@
- "environment"
- "dc_region"
- "edition"
additionalProperties: false
additionalProperties: true
properties:
client_id:
type: "string"
Expand Down Expand Up @@ -17269,9 +17269,7 @@
- "Sandbox"
start_datetime:
title: "Start Date"
type:
- "null"
- "string"
type: "string"
examples:
- "2000-01-01"
- "2000-01-01 13:00"
Expand Down
4 changes: 2 additions & 2 deletions airbyte-integrations/connectors/source-zoho-crm/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM python:3.7.11-alpine3.14 as base
FROM python:3.9.11-alpine3.15 as base

# build and load all requirements
FROM base as builder
Expand Down Expand Up @@ -34,5 +34,5 @@ COPY source_zoho_crm ./source_zoho_crm
ENV AIRBYTE_ENTRYPOINT "python /airbyte/integration_code/main.py"
ENTRYPOINT ["python", "/airbyte/integration_code/main.py"]

LABEL io.airbyte.version=0.1.0
LABEL io.airbyte.version=0.1.1
LABEL io.airbyte.name=airbyte/source-zoho-crm
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,26 @@ connector_image: airbyte/source-zoho-crm:dev
tests:
spec:
- spec_path: "source_zoho_crm/spec.json"
backward_compatibility_tests_config:
disable_for_version: "0.1.0"
connection:
- config_path: "secrets/config.json"
status: "succeed"
- config_path: "integration_tests/invalid_config.json"
status: "failed"
discovery:
- config_path: "secrets/config.json"
backward_compatibility_tests_config:
disable_for_version: "0.1.0"
basic_read:
- config_path: "secrets/config.json"
configured_catalog_path: "integration_tests/configured_catalog.json"
empty_streams: []
expect_records:
path: "integration_tests/expected_records.jsonl"
extra_fields: yes
exact_order: yes
extra_records: no
# expect_records:
# path: "integration_tests/expected_records.jsonl"
# extra_fields: yes
# exact_order: yes
# extra_records: no
incremental:
- config_path: "secrets/config.json"
configured_catalog_path: "integration_tests/configured_catalog.json"
Expand Down
2 changes: 1 addition & 1 deletion airbyte-integrations/connectors/source-zoho-crm/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from setuptools import find_packages, setup

MAIN_REQUIREMENTS = [
"airbyte-cdk~=0.1",
"airbyte-cdk~=0.30.2",
]

TEST_REQUIREMENTS = [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@
class ZohoOauth2Authenticator(Oauth2Authenticator):
def _prepare_refresh_token_params(self) -> Dict[str, str]:
return {
"refresh_token": self.refresh_token,
"client_id": self.client_id,
"client_secret": self.client_secret,
"refresh_token": self.get_refresh_token(),
"client_id": self.get_client_id(),
"client_secret": self.get_client_secret(),
"grant_type": "refresh_token",
}

Expand All @@ -27,9 +27,9 @@ def refresh_access_token(self) -> Tuple[str, int]:
Returns a tuple of (access_token, token_lifespan_in_seconds)
"""
try:
response = requests.request(method="POST", url=self.token_refresh_endpoint, params=self._prepare_refresh_token_params())
response = requests.request(method="POST", url=self._token_refresh_endpoint, params=self._prepare_refresh_token_params())
response.raise_for_status()
response_json = response.json()
return response_json[self.access_token_name], response_json[self.expires_in_name]
return response_json[self.get_access_token_name()], response_json[self.get_expires_in_name()]
except Exception as e:
raise Exception(f"Error while refreshing access token: {e}") from e
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
"dc_region",
"edition"
],
"additionalProperties": false,
"additionalProperties": true,
"properties": {
"client_id": {
"type": "string",
Expand Down Expand Up @@ -46,7 +46,7 @@
},
"start_datetime": {
"title": "Start Date",
"type": ["null", "string"],
"type": "string",
"examples": [
"2000-01-01",
"2000-01-01 13:00",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,12 @@ class ZohoPickListItem(FromDictMixin):
actual_value: str


@dataclasses.dataclass
class AutoNumberDict(FromDictMixin):
prefix: str
suffix: str


FieldType = Dict[Any, Any]


Expand All @@ -108,6 +114,7 @@ class FieldMeta(FromDictMixin):
system_mandatory: bool
display_label: str
pick_list_values: Optional[List[ZohoPickListItem]]
auto_number: Optional[AutoNumberDict] = AutoNumberDict(prefix="", suffix="")

def _default_type_kwargs(self) -> Dict[str, str]:
return {"title": self.display_label}
Expand Down Expand Up @@ -145,8 +152,14 @@ def _string_field(self) -> FieldType:
typedef["format"] = "date"
elif self.data_type == ZohoDataType.datetime:
typedef["format"] = "date-time"
elif self.data_type in ZohoDataType.numeric_string_types():
elif self.data_type == ZohoDataType.bigint:
typedef["airbyte_type"] = "big_integer"
elif self.data_type == ZohoDataType.autonumber:
print(self.auto_number)
if self.auto_number.get("prefix") or self.auto_number.get("suffix"):
typedef["format"] = "string"
else:
typedef["airbyte_type"] = "big_integer"
elif self.data_type == ZohoDataType.picklist and self.pick_list_values:
typedef["enum"] = self._picklist_items()
return typedef
Expand All @@ -161,14 +174,19 @@ def _jsonarray_field(self) -> FieldType:
# `Tag` is defined as string, but is actually an object
typedef["items"] = {
"type": "object",
"additionalProperties": False,
"additionalProperties": True,
"required": ["name", "id"],
"properties": {"name": {"type": "string"}, "id": {"type": "string"}},
}
return typedef
if self.data_type in (ZohoDataType.text, *ZohoDataType.numeric_string_types()):
typedef["items"] = {"type": "string"}
if self.data_type in ZohoDataType.numeric_string_types():
if self.data_type == ZohoDataType.autonumber:
if self.auto_number.get("prefix") or self.auto_number.get("suffix"):
typedef["items"]["format"] = "string"
else:
typedef["items"]["airbyte_type"] = "big_integer"
else:
typedef["items"]["airbyte_type"] = "big_integer"
if self.data_type == ZohoDataType.multiselectpicklist:
typedef["minItems"] = 1
Expand All @@ -182,7 +200,7 @@ def _jsonarray_field(self) -> FieldType:
def _jsonobject_field(self) -> FieldType:
lookup_typedef = {
"type": ["null", "object"],
"additionalProperties": False,
"additionalProperties": True,
"required": ["name", "id"],
"properties": {"name": {"type": ["null", "string"]}, "id": {"type": "string"}},
**self._default_type_kwargs(),
Expand Down
Loading

0 comments on commit a51ac46

Please sign in to comment.