Working with Plugins
To connect with sources and destinations that are not currently supported natively in Tabsdata, you can use these connector plugins.
Source Plugin
The SourcePlugin class enables reading from sources which do not have built-in support in Tabsdata. Click a numbered marker (or the legend beside it) to see what each part does.
1import os2import polars as pl3import requests4import tabsdata as td51class PyPIPkgStatsSource(td.SourcePlugin):7 def __init__(self, package_name: str):8 self.package_name = package_name92 def chunk(self, working_dir: str) -> str:11 # Endpoint with the downloads information of the package12 base_endpoint = f"https://pypistats.org/api/packages/{self.package_name}"13 # Get the downloads by system14 downloads_by_system = requests.get(f"{base_endpoint}/system").json().get("data")1516 # Store the information17 destination_file = "data.parquet"18 destination_path = os.path.join(working_dir, destination_file)19 pl.DataFrame(downloads_by_system).write_parquet(destination_path)3 return destination_file2122@td.publisher(23 source=PyPIPkgStatsSource("polars"),24 tables="output",25)26def input_plugin_from_pypi(df: td.TableFrame):27 return df
Inherit from
td.SourcePluginand accept whatever configuration your source needs, which here is a PyPI package name.The one method you must implement. Fetch or generate the data, write it as a file inside
working_dir, and return that file's name. Tabsdata reads the file you return.Pass an instance of your plugin as the publisher's
source, exactly like a built-in connector.
Destination Plugin
The DestinationPlugin class enables writing to destinations which do not have built-in support in Tabsdata.
1import os2import tempfile3import polars as pl4from google.cloud import storage5import tabsdata as td61class GCPFileUpload(td.DestinationPlugin):8 def __init__(self, bucket_name: str, gcp_credentials_path: str):9 self.bucket_name = bucket_name10 self.gcp_credentials_path = gcp_credentials_path212 def stream(self, _: str, lf: pl.LazyFrame):13 # Set the GCP credentials path14 os.environ["GOOGLE_APPLICATION_CREDENTIALS"] = self.gcp_credentials_path1516 # Create a temporary file17 with tempfile.NamedTemporaryFile(suffix=".csv") as tmp_file:18 temp_file_path = tmp_file.name19 lf.sink_csv(temp_file_path)20 # Extract filename21 destination_file = os.path.basename(temp_file_path)22 # Upload the file to GCP Storage23 client = storage.Client()24 bucket = client.bucket(self.bucket_name)25 blob = bucket.blob(destination_file)3 blob.upload_from_filename(temp_file_path)2728@td.subscriber(29 tables="data",30 destination=GCPFileUpload("<gcp-bucket-name>", "<path_to_gcp_credentials.json>"),31)32def subscriber(df: pl.DataFrame):33 return df
Inherit from
td.DestinationPluginand accept whatever configuration your destination needs, which here is a GCP bucket name and a credentials path.The one method you must implement. Receives the table as a Polars
LazyFrameand is responsible for getting it to the external system. Here that means writing a temp CSV and uploading it to GCS.Pass an instance of your plugin as the subscriber's
destination, exactly like a built-in connector.
Where:
<gcp-bucket-name>is the name of your GCP bucket.<path_to_gcp_credentials.json>is the full system path (typically starting with /users/user_name) to your gcp credentials file.