Ian OLeary
02/06/2024, 2:04 PMEdgar RamÃrez (Arch.dev)
02/06/2024, 4:42 PMIan OLeary
02/06/2024, 5:21 PMtaps\tap-mytap
, running meltano install
, and then running meltano invoke tap-mytap
Ian OLeary
02/06/2024, 6:27 PMclass MyTapAuthenticator(OAuthJWTAuthenticator):
"""Authenticator class for MyTap."""
@classmethod
def create_for_stream(
cls,
stream, # noqa: ANN001
) -> MyTapAuthenticator:
"""Instantiate an authenticator for a specific Singer stream.
Args:
stream: The Singer stream instance.
Returns:
A new authenticator.
"""
clientid = os.getenv("MYTAP_CLIENTID")
username = os.getenv("MYTAP_USERNAME")
password = os.getenv("MYTAP_PASSWORD")
api_url = f"<https://api.mytap.com/api/authenticate?clientid={clientid}&username={username}&password={password}>"
response = requests.get(api_url)
if response.status_code ==200:
auth_token = response.text
return cls(
stream=stream,
auth_token=auth_token
)
else:
raise Exception(f"Failed to authenticate with MyTap API: {response.text}")
Ian OLeary
02/06/2024, 6:27 PMIan OLeary
02/06/2024, 6:27 PMEdgar RamÃrez (Arch.dev)
02/06/2024, 6:37 PMtap.py
look like? Seems like you have required settings auth_token
and project_ids
that are missing?Ian OLeary
02/06/2024, 7:02 PMclass TapMyTap(Tap):
"""MyTap tap class."""
name = "tap-mytap"
# TODO: Update this section with the actual config values you expect:
config_jsonschema = th.PropertiesList(
th.Property(
"auth_token",
th.StringType,
required=True,
secret=True, # Flag config as protected.
description="The token to authenticate against the API service",
),
th.Property(
"project_ids",
th.ArrayType(th.StringType),
required=True,
description="Project IDs to replicate",
),
th.Property(
"start_date",
th.DateTimeType,
description="The earliest record date to sync",
),
th.Property(
"api_url",
th.StringType,
default="<https://api.mytap.com/api>",
description="The url for the API service",
),
).to_dict()
def discover_streams(self) -> list[streams.MyTapStream]:
"""Return a list of discovered streams.
Returns:
A list of discovered streams.
"""
return [
streams.NewUpdatedCandidateRecordsStream(self),
]
I haven't altered them in the tap.py yet. I've defined one stream in my streams.py (for now - for simplicity) which is shown hereEdgar RamÃrez (Arch.dev)
02/06/2024, 9:20 PMIan OLeary
02/06/2024, 10:09 PMIan OLeary
02/06/2024, 10:10 PMEdgar RamÃrez (Arch.dev)
02/07/2024, 12:54 AMso define them in the auth_token property itself?
what would that look like?rather as their own properties:
config_jsonschema = th.PropertiesList(
th.Property(
"client_id",
required=True,
...
),
th.Property(
"username",
required=True,
...
),
th.Property(
"password",
required=True,
...
),
and then in your auth class:
clientid = self.config["client_id"]
username = self.config["username"]
password = self.config["password"]
Ian OLeary
02/07/2024, 2:24 PMEdgar RamÃrez (Arch.dev)
02/07/2024, 2:32 PMIan OLeary
02/07/2024, 2:43 PMclass TapAuthenticator(OAuthJWTAuthenticator):
"""Authenticator class for Tap."""
@classmethod
def create_for_stream(
self,
cls,
stream, # noqa: ANN001
) -> TapAuthenticator:
clientid = self.config["client_id"]
username = self.config["username"]
password = self.config["password"]
api_url = f"<https://api.tap.com/api/authenticate?clientid={clientid}&username={username}&password={password}>"
response = requests.get(api_url)
if response.status_code ==200:
auth_token = response.text
return cls(
stream=stream,
auth_token=auth_token
)
else:
raise Exception(f"Failed to authenticate with Tap API: {response.text}")
So here's what I've got now, Should I also be returning self in return cls()?Ian OLeary
02/07/2024, 2:52 PM