33
44import json
55import os
6+ import warnings
67from copy import copy
78from dataclasses import dataclass
9+ from enum import Enum
810from pathlib import Path
911
1012import requests
1921_REGISTRY_ENV_VAR = "AIRBYTE_LOCAL_REGISTRY"
2022_REGISTRY_URL = "https://connectors.airbyte.com/files/registries/v0/oss_registry.json"
2123
24+ _LOWCODE_LABEL = "cdk:low-code"
25+
26+ _LOWCODE_CONNECTORS_NEEDING_PYTHON = [
27+ "source-alpha-vantage" ,
28+ "source-amplitude" ,
29+ "source-apify-dataset" ,
30+ "source-avni" ,
31+ "source-bamboo-hr" ,
32+ "source-braintree" ,
33+ "source-braze" ,
34+ "source-chargebee" ,
35+ "source-close-com" ,
36+ "source-commercetools" ,
37+ "source-facebook-pages" ,
38+ "source-fastbill" ,
39+ "source-freshdesk" ,
40+ "source-gitlab" ,
41+ "source-gnews" ,
42+ "source-greenhouse" ,
43+ "source-instatus" ,
44+ "source-intercom" ,
45+ "source-iterable" ,
46+ "source-jira" ,
47+ "source-klaviyo" ,
48+ "source-mailchimp" ,
49+ "source-mixpanel" ,
50+ "source-monday" ,
51+ "source-my-hours" ,
52+ "source-notion" ,
53+ "source-okta" ,
54+ "source-outreach" ,
55+ "source-partnerstack" ,
56+ "source-paypal-transaction" ,
57+ "source-pinterest" ,
58+ "source-pipedrive" ,
59+ "source-pocket" ,
60+ "source-posthog" ,
61+ "source-prestashop" ,
62+ "source-public-apis" ,
63+ "source-qualaroo" ,
64+ "source-quickbooks" ,
65+ "source-railz" ,
66+ "source-recharge" ,
67+ "source-retently" ,
68+ "source-rss" ,
69+ "source-slack" ,
70+ "source-surveymonkey" ,
71+ "source-the-guardian-api" ,
72+ "source-trello" ,
73+ "source-typeform" ,
74+ "source-xero" ,
75+ "source-younium" ,
76+ "source-zendesk-chat" ,
77+ "source-zendesk-sunshine" ,
78+ "source-zendesk-support" ,
79+ "source-zendesk-talk" ,
80+ "source-zenloop" ,
81+ "source-zoom" ,
82+ ]
83+ _LOWCODE_CONNECTORS_FAILING_VALIDATION = [
84+ "source-amazon-ads" ,
85+ ]
86+ _LOWCODE_CONNECTORS_404 = [
87+ "source-unleash" ,
88+ ]
89+ _LOWCODE_CONNECTORS_EXCLUDED : list [str ] = [
90+ * _LOWCODE_CONNECTORS_FAILING_VALIDATION ,
91+ * _LOWCODE_CONNECTORS_404 ,
92+ * _LOWCODE_CONNECTORS_NEEDING_PYTHON ,
93+ ]
94+
95+
96+ class InstallType (str , Enum ):
97+ YAML = "yaml"
98+ PYTHON = "python"
99+ DOCKER = "docker"
100+ JAVA = "java"
101+
102+
103+ class Language (str , Enum ):
104+ PYTHON = InstallType .PYTHON .value
105+ JAVA = InstallType .JAVA .value
106+
22107
23108@dataclass
24109class ConnectorMetadata :
@@ -33,6 +118,12 @@ class ConnectorMetadata:
33118 pypi_package_name : str | None
34119 """The name of the PyPI package for the connector, if it exists."""
35120
121+ language : Language | None
122+ """The language of the connector."""
123+
124+ install_types : set [InstallType ]
125+ """The supported install types for the connector."""
126+
36127
37128def _get_registry_url () -> str :
38129 if _REGISTRY_ENV_VAR in os .environ :
@@ -43,14 +134,36 @@ def _get_registry_url() -> str:
43134
44135def _registry_entry_to_connector_metadata (entry : dict ) -> ConnectorMetadata :
45136 name = entry ["dockerRepository" ].replace ("airbyte/" , "" )
137+ language : Language | None = None
138+ if "language" in entry and entry ["language" ] is not None :
139+ try :
140+ language = Language (entry ["language" ])
141+ except Exception :
142+ warnings .warn (
143+ message = f"Invalid language for connector { name } : { entry ['language' ]} " ,
144+ stacklevel = 2 ,
145+ )
46146 remote_registries : dict = entry .get ("remoteRegistries" , {})
47147 pypi_registry : dict = remote_registries .get ("pypi" , {})
48148 pypi_package_name : str = pypi_registry .get ("packageName" , None )
49149 pypi_enabled : bool = pypi_registry .get ("enabled" , False )
150+ install_types : set [InstallType ] = {
151+ x
152+ for x in [
153+ InstallType .DOCKER if entry .get ("dockerImageTag" ) else None ,
154+ InstallType .PYTHON if pypi_enabled else None ,
155+ InstallType .JAVA if language == Language .JAVA else None ,
156+ InstallType .YAML if _LOWCODE_LABEL in entry .get ("tags" , []) else None ,
157+ ]
158+ if x
159+ }
160+
50161 return ConnectorMetadata (
51162 name = name ,
52- latest_available_version = entry [ "dockerImageTag" ] ,
163+ latest_available_version = entry . get ( "dockerImageTag" , None ) ,
53164 pypi_package_name = pypi_package_name if pypi_enabled else None ,
165+ language = language ,
166+ install_types = install_types ,
54167 )
55168
56169
@@ -114,11 +227,45 @@ def get_connector_metadata(name: str) -> ConnectorMetadata:
114227 return cache [name ]
115228
116229
117- def get_available_connectors () -> list [str ]:
230+ def get_available_connectors (install_type : InstallType | str = InstallType . PYTHON ) -> list [str ]:
118231 """Return a list of all available connectors.
119232
120233 Connectors will be returned in alphabetical order, with the standard prefix "source-".
121234 """
122- return sorted (
123- conn .name for conn in _get_registry_cache ().values () if conn .pypi_package_name is not None
235+ if not isinstance (install_type , InstallType ):
236+ install_type = InstallType (install_type )
237+
238+ if install_type == InstallType .PYTHON :
239+ return sorted (
240+ conn .name
241+ for conn in _get_registry_cache ().values ()
242+ if conn .pypi_package_name is not None
243+ )
244+
245+ if install_type == InstallType .JAVA :
246+ warnings .warn (
247+ message = "Java connectors are not yet supported." ,
248+ stacklevel = 2 ,
249+ )
250+ return sorted (
251+ conn .name for conn in _get_registry_cache ().values () if conn .language == Language .JAVA
252+ )
253+
254+ if install_type == InstallType .DOCKER :
255+ return sorted (conn .name for conn in _get_registry_cache ().values ())
256+
257+ if install_type == InstallType .YAML :
258+ return sorted (
259+ conn .name
260+ for conn in _get_registry_cache ().values ()
261+ if InstallType .YAML in conn .install_types
262+ and conn .name not in _LOWCODE_CONNECTORS_EXCLUDED
263+ )
264+
265+ # pragma: no cover # Should never be reached.
266+ raise exc .PyAirbyteInputError (
267+ message = "Invalid install type." ,
268+ context = {
269+ "install_type" : install_type ,
270+ },
124271 )
0 commit comments