ingestr 0.14.94__tar.gz → 0.14.96__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of ingestr might be problematic. Click here for more details.
- {ingestr-0.14.94 → ingestr-0.14.96}/PKG-INFO +1 -1
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/.vitepress/config.mjs +1 -0
- ingestr-0.14.96/docs/supported-sources/socrata.md +127 -0
- ingestr-0.14.96/ingestr/src/buildinfo.py +1 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/factory.py +2 -0
- ingestr-0.14.96/ingestr/src/socrata_source/__init__.py +83 -0
- ingestr-0.14.96/ingestr/src/socrata_source/helpers.py +85 -0
- ingestr-0.14.96/ingestr/src/socrata_source/settings.py +8 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/sources.py +90 -0
- ingestr-0.14.94/ingestr/src/buildinfo.py +0 -1
- {ingestr-0.14.94 → ingestr-0.14.96}/.dlt/config.toml +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/.dockerignore +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/.githooks/pre-commit-hook.sh +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/.github/workflows/deploy-docs.yml +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/.github/workflows/release.yml +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/.github/workflows/secrets-scan.yml +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/.github/workflows/tests.yml +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/.gitignore +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/.gitleaksignore +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/.python-version +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/.vale.ini +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/Dockerfile +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/LICENSE.md +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/Makefile +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/README.md +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/.vitepress/theme/custom.css +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/.vitepress/theme/index.js +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/commands/example-uris.md +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/commands/ingest.md +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/getting-started/core-concepts.md +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/getting-started/data-masking.md +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/getting-started/incremental-loading.md +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/getting-started/quickstart.md +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/getting-started/telemetry.md +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/index.md +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/media/applovin_max.png +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/media/athena.png +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/media/clickhouse_img.png +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/media/clickup_ingestion.png +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/media/cratedb-destination.png +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/media/cratedb-source.png +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/media/freshdesk_ingestion.png +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/media/gcp_spanner_ingestion.png +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/media/github.png +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/media/google_analytics_realtime_report.png +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/media/googleanalytics.png +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/media/ingestion_elasticsearch_img.png +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/media/kinesis.bigquery.png +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/media/linear.png +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/media/linkedin_ads.png +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/media/mixpanel_ingestion.png +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/media/personio.png +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/media/personio_duckdb.png +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/media/phantombuster.png +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/media/pipedrive.png +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/media/quickbook_ingestion.png +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/media/sftp.png +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/media/stripe_postgres.png +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/media/tiktok.png +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/media/wise_ingestion.png +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/media/zoom_ingestion.png +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/public/demo.gif +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/supported-sources/adjust.md +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/supported-sources/airtable.md +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/supported-sources/allium.md +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/supported-sources/anthropic.md +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/supported-sources/applovin.md +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/supported-sources/applovin_max.md +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/supported-sources/appsflyer.md +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/supported-sources/appstore.md +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/supported-sources/asana.md +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/supported-sources/athena.md +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/supported-sources/attio.md +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/supported-sources/bigquery.md +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/supported-sources/chess.md +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/supported-sources/clickhouse.md +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/supported-sources/clickup.md +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/supported-sources/couchbase.md +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/supported-sources/cratedb.md +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/supported-sources/csv.md +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/supported-sources/custom_queries.md +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/supported-sources/databricks.md +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/supported-sources/db2.md +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/supported-sources/docebo.md +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/supported-sources/duckdb.md +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/supported-sources/dynamodb.md +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/supported-sources/elasticsearch.md +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/supported-sources/facebook-ads.md +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/supported-sources/fluxx.md +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/supported-sources/frankfurter.md +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/supported-sources/freshdesk.md +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/supported-sources/fundraiseup.md +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/supported-sources/gcs.md +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/supported-sources/github.md +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/supported-sources/google-ads.md +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/supported-sources/google_analytics.md +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/supported-sources/gorgias.md +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/supported-sources/gsheets.md +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/supported-sources/http.md +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/supported-sources/hubspot.md +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/supported-sources/influxdb.md +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/supported-sources/intercom.md +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/supported-sources/isoc-pulse.md +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/supported-sources/jira.md +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/supported-sources/kafka.md +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/supported-sources/kinesis.md +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/supported-sources/klaviyo.md +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/supported-sources/linear.md +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/supported-sources/linkedin_ads.md +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/supported-sources/mailchimp.md +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/supported-sources/mixpanel.md +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/supported-sources/monday.md +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/supported-sources/mongodb.md +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/supported-sources/motherduck.md +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/supported-sources/mssql.md +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/supported-sources/mysql.md +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/supported-sources/notion.md +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/supported-sources/oracle.md +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/supported-sources/personio.md +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/supported-sources/phantombuster.md +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/supported-sources/pinterest.md +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/supported-sources/pipedrive.md +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/supported-sources/plusvibeai.md +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/supported-sources/postgres.md +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/supported-sources/quickbooks.md +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/supported-sources/redshift.md +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/supported-sources/revenuecat.md +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/supported-sources/s3.md +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/supported-sources/salesforce.md +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/supported-sources/sap-hana.md +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/supported-sources/sftp.md +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/supported-sources/shopify.md +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/supported-sources/slack.md +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/supported-sources/smartsheets.md +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/supported-sources/snowflake.md +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/supported-sources/solidgate.md +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/supported-sources/spanner.md +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/supported-sources/sqlite.md +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/supported-sources/stripe.md +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/supported-sources/tiktok-ads.md +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/supported-sources/trino.md +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/supported-sources/trustpilot.md +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/supported-sources/wise.md +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/supported-sources/zendesk.md +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/supported-sources/zoom.md +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/tutorials/load-kinesis-bigquery.md +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/tutorials/load-personio-duckdb.md +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/docs/tutorials/load-stripe-postgres.md +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/conftest.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/main.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/.gitignore +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/adjust/__init__.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/adjust/adjust_helpers.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/airtable/__init__.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/allium/__init__.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/anthropic/__init__.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/anthropic/helpers.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/applovin/__init__.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/applovin_max/__init__.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/appsflyer/__init__.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/appsflyer/client.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/appstore/__init__.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/appstore/client.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/appstore/errors.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/appstore/models.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/appstore/resources.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/arrow/__init__.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/asana_source/__init__.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/asana_source/helpers.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/asana_source/settings.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/attio/__init__.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/attio/helpers.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/blob.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/chess/__init__.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/chess/helpers.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/chess/settings.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/clickup/__init__.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/clickup/helpers.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/collector/spinner.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/couchbase_source/__init__.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/couchbase_source/helpers.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/destinations.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/docebo/__init__.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/docebo/client.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/docebo/helpers.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/dynamodb/__init__.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/elasticsearch/__init__.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/elasticsearch/helpers.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/errors.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/facebook_ads/__init__.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/facebook_ads/exceptions.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/facebook_ads/helpers.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/facebook_ads/settings.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/facebook_ads/utils.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/filesystem/__init__.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/filesystem/helpers.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/filesystem/readers.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/filters.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/fluxx/__init__.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/fluxx/helpers.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/frankfurter/__init__.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/frankfurter/helpers.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/freshdesk/__init__.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/freshdesk/freshdesk_client.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/freshdesk/settings.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/fundraiseup/__init__.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/fundraiseup/client.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/github/__init__.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/github/helpers.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/github/queries.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/github/settings.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/google_ads/__init__.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/google_ads/field.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/google_ads/metrics.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/google_ads/predicates.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/google_ads/reports.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/google_analytics/__init__.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/google_analytics/helpers.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/google_sheets/README.md +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/google_sheets/__init__.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/google_sheets/helpers/__init__.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/google_sheets/helpers/api_calls.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/google_sheets/helpers/data_processing.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/gorgias/__init__.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/gorgias/helpers.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/http/__init__.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/http/readers.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/http_client.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/hubspot/__init__.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/hubspot/helpers.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/hubspot/settings.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/influxdb/__init__.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/influxdb/client.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/intercom/__init__.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/intercom/helpers.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/intercom/settings.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/isoc_pulse/__init__.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/jira_source/__init__.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/jira_source/helpers.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/jira_source/settings.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/kafka/__init__.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/kafka/helpers.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/kinesis/__init__.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/kinesis/helpers.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/klaviyo/__init__.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/klaviyo/client.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/klaviyo/helpers.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/linear/__init__.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/linear/helpers.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/linkedin_ads/__init__.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/linkedin_ads/dimension_time_enum.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/linkedin_ads/helpers.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/loader.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/mailchimp/__init__.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/mailchimp/helpers.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/mailchimp/settings.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/masking.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/mixpanel/__init__.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/mixpanel/client.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/monday/__init__.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/monday/helpers.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/monday/settings.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/mongodb/__init__.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/mongodb/helpers.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/notion/__init__.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/notion/helpers/__init__.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/notion/helpers/client.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/notion/helpers/database.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/notion/settings.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/partition.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/personio/__init__.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/personio/helpers.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/phantombuster/__init__.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/phantombuster/client.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/pinterest/__init__.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/pipedrive/__init__.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/pipedrive/helpers/__init__.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/pipedrive/helpers/custom_fields_munger.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/pipedrive/helpers/pages.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/pipedrive/settings.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/pipedrive/typing.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/plusvibeai/__init__.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/plusvibeai/helpers.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/plusvibeai/settings.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/quickbooks/__init__.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/resource.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/revenuecat/__init__.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/revenuecat/helpers.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/salesforce/__init__.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/salesforce/helpers.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/shopify/__init__.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/shopify/exceptions.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/shopify/helpers.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/shopify/settings.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/slack/__init__.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/slack/helpers.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/slack/settings.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/smartsheets/__init__.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/solidgate/__init__.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/solidgate/helpers.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/sql_database/__init__.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/sql_database/callbacks.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/stripe_analytics/__init__.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/stripe_analytics/helpers.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/stripe_analytics/settings.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/table_definition.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/telemetry/event.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/testdata/fakebqcredentials.json +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/tiktok_ads/__init__.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/tiktok_ads/tiktok_helpers.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/time.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/trustpilot/__init__.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/trustpilot/client.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/version.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/wise/__init__.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/wise/client.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/zendesk/__init__.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/zendesk/helpers/__init__.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/zendesk/helpers/api_helpers.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/zendesk/helpers/credentials.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/zendesk/helpers/talk_api.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/zendesk/settings.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/zoom/__init__.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/src/zoom/helpers.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/testdata/.gitignore +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/testdata/create_replace.csv +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/testdata/delete_insert_expected.csv +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/testdata/delete_insert_part1.csv +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/testdata/delete_insert_part2.csv +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/testdata/merge_expected.csv +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/testdata/merge_part1.csv +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/testdata/merge_part2.csv +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/ingestr/tests/unit/test_smartsheets.py +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/package-lock.json +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/package.json +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/pyproject.toml +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/requirements-dev.txt +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/requirements.in +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/requirements.txt +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/requirements_arm64.txt +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/resources/demo.gif +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/resources/demo.tape +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/resources/ingestr.svg +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/styles/Google/AMPM.yml +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/styles/Google/Acronyms.yml +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/styles/Google/Colons.yml +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/styles/Google/Contractions.yml +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/styles/Google/DateFormat.yml +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/styles/Google/Ellipses.yml +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/styles/Google/EmDash.yml +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/styles/Google/Exclamation.yml +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/styles/Google/FirstPerson.yml +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/styles/Google/Gender.yml +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/styles/Google/GenderBias.yml +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/styles/Google/HeadingPunctuation.yml +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/styles/Google/Headings.yml +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/styles/Google/Latin.yml +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/styles/Google/LyHyphens.yml +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/styles/Google/OptionalPlurals.yml +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/styles/Google/Ordinal.yml +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/styles/Google/OxfordComma.yml +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/styles/Google/Parens.yml +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/styles/Google/Passive.yml +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/styles/Google/Periods.yml +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/styles/Google/Quotes.yml +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/styles/Google/Ranges.yml +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/styles/Google/Semicolons.yml +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/styles/Google/Slang.yml +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/styles/Google/Spacing.yml +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/styles/Google/Spelling.yml +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/styles/Google/Units.yml +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/styles/Google/We.yml +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/styles/Google/Will.yml +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/styles/Google/WordList.yml +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/styles/Google/meta.json +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/styles/Google/vocab.txt +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/styles/bruin/Ingestr.yml +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/styles/config/vocabularies/bruin/accept.txt +0 -0
- {ingestr-0.14.94 → ingestr-0.14.96}/test.env.template +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ingestr
|
|
3
|
-
Version: 0.14.
|
|
3
|
+
Version: 0.14.96
|
|
4
4
|
Summary: ingestr is a command-line application that ingests data from various sources and stores them in any database.
|
|
5
5
|
Project-URL: Homepage, https://github.com/bruin-data/ingestr
|
|
6
6
|
Project-URL: Issues, https://github.com/bruin-data/ingestr/issues
|
|
@@ -108,6 +108,7 @@ j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
|
|
|
108
108
|
{ text: "Postgres", link: "/supported-sources/postgres.md" },
|
|
109
109
|
{ text: "SAP Hana", link: "/supported-sources/sap-hana.md" },
|
|
110
110
|
{ text: "Snowflake", link: "/supported-sources/snowflake.md" },
|
|
111
|
+
{ text: "Socrata", link: "/supported-sources/socrata.md" },
|
|
111
112
|
{ text: "SQLite", link: "/supported-sources/sqlite.md" },
|
|
112
113
|
{
|
|
113
114
|
text: "Experimental",
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
# Socrata
|
|
2
|
+
|
|
3
|
+
[Socrata](https://dev.socrata.com/) is an open data platform used by governments and organizations to publish and share public datasets. The platform powers thousands of open data portals worldwide, including data.gov and many city, state, and federal government sites.
|
|
4
|
+
|
|
5
|
+
`ingestr` allows ingesting data from any Socrata-powered open data portal using the [Socrata Open Data API (SODA)](https://dev.socrata.com/docs/endpoints.html).
|
|
6
|
+
|
|
7
|
+
## URI Format
|
|
8
|
+
|
|
9
|
+
The URI format for Socrata is as follows:
|
|
10
|
+
```
|
|
11
|
+
socrata://?domain=<domain>&dataset_id=<dataset_id>&app_token=<app_token>
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
URI Parameters:
|
|
15
|
+
* `domain`: The Socrata domain (e.g., `data.seattle.gov`, `data.cityofnewyork.us`)
|
|
16
|
+
* `dataset_id`: The dataset identifier (4x4 format like `6udu-fhnu`)
|
|
17
|
+
* `app_token`: Socrata app token for API access (required)
|
|
18
|
+
* `username` (optional): Username for authentication (required for private datasets)
|
|
19
|
+
* `password` (optional): Password for authentication (required for private datasets)
|
|
20
|
+
|
|
21
|
+
## Setting up Socrata Integration
|
|
22
|
+
|
|
23
|
+
### Finding Domain and Dataset ID
|
|
24
|
+
|
|
25
|
+
1. Navigate to any Socrata-powered open data portal
|
|
26
|
+
2. Find the dataset you want to ingest
|
|
27
|
+
3. The domain is the base URL (e.g., `data.seattle.gov`)
|
|
28
|
+
4. The dataset ID is in the URL or API endpoint (e.g., `6udu-fhnu`)
|
|
29
|
+
|
|
30
|
+
Example: For `https://data.seattle.gov/City-Business/City-of-Seattle-Wage-Data/2khk-5ukd`, the domain is `data.seattle.gov` and the dataset ID is `2khk-5ukd`.
|
|
31
|
+
|
|
32
|
+
### Generate an App Token
|
|
33
|
+
|
|
34
|
+
You need to obtain an app token to access the Socrata API.
|
|
35
|
+
|
|
36
|
+
1. Sign up for a free account at the Socrata portal you're using
|
|
37
|
+
2. Navigate to the developer settings or API documentation
|
|
38
|
+
3. Generate an app token
|
|
39
|
+
4. Use this token in the `app_token` parameter
|
|
40
|
+
|
|
41
|
+
### Example: Loading a Public Dataset
|
|
42
|
+
|
|
43
|
+
For this example, we'll load the Seattle City wage data:
|
|
44
|
+
* Domain: `data.seattle.gov`
|
|
45
|
+
* Dataset ID: `2khk-5ukd`
|
|
46
|
+
* App token: `your_app_token_here`
|
|
47
|
+
|
|
48
|
+
We will run `ingestr` to save this data to a [duckdb](https://duckdb.org/) database called `socrata.db` under the table name `public.wage_data`.
|
|
49
|
+
|
|
50
|
+
```sh
|
|
51
|
+
ingestr ingest \
|
|
52
|
+
--source-uri "socrata://?domain=data.seattle.gov&dataset_id=2khk-5ukd&app_token=your_app_token_here" \
|
|
53
|
+
--source-table "dataset" \
|
|
54
|
+
--dest-uri "duckdb:///socrata.db" \
|
|
55
|
+
--dest-table "public.wage_data"
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### Example: Incremental Loading
|
|
59
|
+
|
|
60
|
+
Socrata supports incremental loading using the `:updated_at` system field or any other date/timestamp field in your dataset that gets updated. You must specify the incremental key using the `--incremental-key` flag.
|
|
61
|
+
|
|
62
|
+
First, run an initial load for a specific time range using `:updated_at` as the incremental key:
|
|
63
|
+
|
|
64
|
+
```sh
|
|
65
|
+
ingestr ingest \
|
|
66
|
+
--source-uri "socrata://?domain=data.seattle.gov&dataset_id=2khk-5ukd&app_token=your_app_token_here" \
|
|
67
|
+
--source-table "dataset" \
|
|
68
|
+
--dest-uri "duckdb:///socrata.db" \
|
|
69
|
+
--dest-table "public.wage_data" \
|
|
70
|
+
--incremental-key ":updated_at" \
|
|
71
|
+
--interval-start "2024-01-01" \
|
|
72
|
+
--interval-end "2024-06-30" \
|
|
73
|
+
--incremental-strategy "merge"
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
Now, we will run `ingestr` again without specifying dates to load only new or updated records:
|
|
79
|
+
|
|
80
|
+
```sh
|
|
81
|
+
ingestr ingest \
|
|
82
|
+
--source-uri "socrata://?domain=data.seattle.gov&dataset_id=2khk-5ukd&app_token=your_app_token_here" \
|
|
83
|
+
--source-table "dataset" \
|
|
84
|
+
--dest-uri "duckdb:///socrata.db" \
|
|
85
|
+
--dest-table "public.wage_data" \
|
|
86
|
+
--incremental-key ":updated_at"
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
This will automatically fetch only records that were created or updated after the last ingestion.
|
|
90
|
+
|
|
91
|
+
### Example: Loading Private Datasets
|
|
92
|
+
|
|
93
|
+
For private datasets that require authentication:
|
|
94
|
+
|
|
95
|
+
```sh
|
|
96
|
+
ingestr ingest \
|
|
97
|
+
--source-uri "socrata://?domain=your.domain.com&dataset_id=xxxx-xxxx&app_token=your_token&username=your_username&password=your_password" \
|
|
98
|
+
--source-table "dataset" \
|
|
99
|
+
--dest-uri "duckdb:///socrata.db" \
|
|
100
|
+
--dest-table "public.private_data"
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
## Tables
|
|
104
|
+
|
|
105
|
+
Socrata source provides a single table called `dataset` that represents the Socrata dataset.
|
|
106
|
+
|
|
107
|
+
| Name | Merge Key | Inc Key | Inc Strategy | Details |
|
|
108
|
+
| --- | --- | --- | --- | --- |
|
|
109
|
+
| `dataset` | `:id` | user-defined | replace/merge | Loads all records from the specified Socrata dataset. Uses `replace` by default, or `merge` when `--incremental-key` is specified |
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
## Troubleshooting
|
|
116
|
+
|
|
117
|
+
### Rate Limit Errors
|
|
118
|
+
If you hit rate limits, register for an app token or reduce the frequency of requests.
|
|
119
|
+
|
|
120
|
+
### Authentication Errors
|
|
121
|
+
For private datasets, ensure username and password are correct and that you have access to the dataset.
|
|
122
|
+
|
|
123
|
+
### Invalid Dataset ID
|
|
124
|
+
Verify the dataset ID is in the correct 4x4 format (e.g., `xxxx-xxxx`) and exists on the specified domain.
|
|
125
|
+
|
|
126
|
+
### Timeout Errors
|
|
127
|
+
For very large datasets, the initial load may take time. Consider using date ranges to break up large loads.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
version = "v0.14.96"
|
|
@@ -84,6 +84,7 @@ from ingestr.src.sources import (
|
|
|
84
84
|
ShopifySource,
|
|
85
85
|
SlackSource,
|
|
86
86
|
SmartsheetSource,
|
|
87
|
+
SocrataSource,
|
|
87
88
|
SolidgateSource,
|
|
88
89
|
SqlSource,
|
|
89
90
|
StripeAnalyticsSource,
|
|
@@ -218,6 +219,7 @@ class SourceDestinationFactory:
|
|
|
218
219
|
"sftp": SFTPSource,
|
|
219
220
|
"pinterest": PinterestSource,
|
|
220
221
|
"revenuecat": RevenueCatSource,
|
|
222
|
+
"socrata": SocrataSource,
|
|
221
223
|
"zoom": ZoomSource,
|
|
222
224
|
"clickup": ClickupSource,
|
|
223
225
|
"influxdb": InfluxDBSource,
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
"""A source loading data from Socrata open data platform"""
|
|
2
|
+
|
|
3
|
+
from typing import Any, Dict, Iterator, Optional
|
|
4
|
+
|
|
5
|
+
import dlt
|
|
6
|
+
|
|
7
|
+
from .helpers import fetch_data
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@dlt.source(name="socrata", max_table_nesting=0)
|
|
11
|
+
def source(
|
|
12
|
+
domain: str,
|
|
13
|
+
dataset_id: str,
|
|
14
|
+
app_token: Optional[str] = None,
|
|
15
|
+
username: Optional[str] = None,
|
|
16
|
+
password: Optional[str] = None,
|
|
17
|
+
incremental: Optional[Any] = None,
|
|
18
|
+
primary_key: Optional[str] = None,
|
|
19
|
+
write_disposition: Optional[str] = dlt.config.value,
|
|
20
|
+
):
|
|
21
|
+
"""
|
|
22
|
+
A dlt source for the Socrata open data platform.
|
|
23
|
+
|
|
24
|
+
Supports both full refresh (replace) and incremental loading (merge).
|
|
25
|
+
|
|
26
|
+
Args:
|
|
27
|
+
domain: The Socrata domain (e.g., "evergreen.data.socrata.com")
|
|
28
|
+
dataset_id: The dataset identifier (e.g., "6udu-fhnu")
|
|
29
|
+
app_token: Socrata app token for higher rate limits (recommended)
|
|
30
|
+
username: Username for authentication (if dataset is private)
|
|
31
|
+
password: Password for authentication (if dataset is private)
|
|
32
|
+
incremental: DLT incremental object for incremental loading
|
|
33
|
+
primary_key: Primary key field for merge operations (default: ":id")
|
|
34
|
+
write_disposition: Write disposition ("replace", "append", "merge").
|
|
35
|
+
If not provided, automatically determined based on incremental setting.
|
|
36
|
+
|
|
37
|
+
Returns:
|
|
38
|
+
A dlt source with a single "dataset" resource
|
|
39
|
+
"""
|
|
40
|
+
|
|
41
|
+
@dlt.resource(
|
|
42
|
+
write_disposition=write_disposition or "replace",
|
|
43
|
+
primary_key=primary_key, # type: ignore[call-overload]
|
|
44
|
+
)
|
|
45
|
+
def dataset(
|
|
46
|
+
incremental: Optional[dlt.sources.incremental] = incremental, # type: ignore[type-arg]
|
|
47
|
+
) -> Iterator[Dict[str, Any]]:
|
|
48
|
+
"""
|
|
49
|
+
Yields records from a Socrata dataset.
|
|
50
|
+
|
|
51
|
+
Supports both full refresh (replace) and incremental loading (merge).
|
|
52
|
+
When incremental is provided, filters data using SoQL WHERE clause on the server side.
|
|
53
|
+
|
|
54
|
+
Yields:
|
|
55
|
+
Dict[str, Any]: Individual records from the dataset
|
|
56
|
+
"""
|
|
57
|
+
fetch_kwargs: Dict[str, Any] = {
|
|
58
|
+
"domain": domain,
|
|
59
|
+
"dataset_id": dataset_id,
|
|
60
|
+
"app_token": app_token,
|
|
61
|
+
"username": username,
|
|
62
|
+
"password": password,
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if incremental and incremental.cursor_path:
|
|
66
|
+
fetch_kwargs["incremental_key"] = incremental.cursor_path
|
|
67
|
+
fetch_kwargs["start_value"] = (
|
|
68
|
+
str(incremental.last_value)
|
|
69
|
+
if incremental.last_value is not None
|
|
70
|
+
else None
|
|
71
|
+
)
|
|
72
|
+
if getattr(incremental, "end_value", None) is not None:
|
|
73
|
+
ev = incremental.end_value # type: ignore[attr-defined]
|
|
74
|
+
fetch_kwargs["end_value"] = (
|
|
75
|
+
ev.isoformat() # type: ignore[union-attr]
|
|
76
|
+
if hasattr(ev, "isoformat")
|
|
77
|
+
else str(ev)
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
# Fetch and yield records
|
|
81
|
+
yield from fetch_data(**fetch_kwargs)
|
|
82
|
+
|
|
83
|
+
return (dataset,)
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
"""Socrata API helpers"""
|
|
2
|
+
|
|
3
|
+
from typing import Any, Dict, Iterator, Optional
|
|
4
|
+
|
|
5
|
+
from dlt.sources.helpers import requests
|
|
6
|
+
|
|
7
|
+
from .settings import DEFAULT_PAGE_SIZE, REQUEST_TIMEOUT
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def fetch_data(
|
|
11
|
+
domain: str,
|
|
12
|
+
dataset_id: str,
|
|
13
|
+
app_token: Optional[str] = None,
|
|
14
|
+
username: Optional[str] = None,
|
|
15
|
+
password: Optional[str] = None,
|
|
16
|
+
incremental_key: Optional[str] = None,
|
|
17
|
+
start_value: Optional[str] = None,
|
|
18
|
+
end_value: Optional[str] = None,
|
|
19
|
+
) -> Iterator[Dict[str, Any]]:
|
|
20
|
+
"""
|
|
21
|
+
Fetch records from Socrata dataset with pagination and optional filtering.
|
|
22
|
+
|
|
23
|
+
Uses offset-based pagination to get all records, not just first 50000.
|
|
24
|
+
Supports incremental loading via SoQL WHERE clause for server-side filtering.
|
|
25
|
+
|
|
26
|
+
Args:
|
|
27
|
+
domain: Socrata domain (e.g., "data.seattle.gov")
|
|
28
|
+
dataset_id: Dataset identifier (e.g., "6udu-fhnu")
|
|
29
|
+
app_token: Socrata app token for higher rate limits
|
|
30
|
+
username: Username for authentication
|
|
31
|
+
password: Password for authentication
|
|
32
|
+
start_value: Minimum value for incremental_key (inclusive)
|
|
33
|
+
end_value: Maximum value for incremental_key (exclusive)
|
|
34
|
+
|
|
35
|
+
Yields:
|
|
36
|
+
Lists of records (one list per page)
|
|
37
|
+
|
|
38
|
+
Raises:
|
|
39
|
+
requests.HTTPError: If API request fails
|
|
40
|
+
"""
|
|
41
|
+
url = f"https://{domain}/resource/{dataset_id}.json"
|
|
42
|
+
|
|
43
|
+
headers = {"Accept": "application/json"}
|
|
44
|
+
if app_token:
|
|
45
|
+
headers["X-App-Token"] = app_token
|
|
46
|
+
|
|
47
|
+
auth = (username, password) if username and password else None
|
|
48
|
+
|
|
49
|
+
limit = DEFAULT_PAGE_SIZE
|
|
50
|
+
offset = 0
|
|
51
|
+
|
|
52
|
+
while True:
|
|
53
|
+
params: Dict[str, Any] = {"$limit": limit, "$offset": offset}
|
|
54
|
+
|
|
55
|
+
if incremental_key and start_value:
|
|
56
|
+
start_value_iso = str(start_value).replace(" ", "T")
|
|
57
|
+
where_conditions = [f"{incremental_key} >= '{start_value_iso}'"]
|
|
58
|
+
|
|
59
|
+
if end_value:
|
|
60
|
+
end_value_iso = str(end_value).replace(" ", "T")
|
|
61
|
+
where_conditions.append(f"{incremental_key} < '{end_value_iso}'")
|
|
62
|
+
|
|
63
|
+
params["$where"] = " AND ".join(where_conditions)
|
|
64
|
+
params["$order"] = f"{incremental_key} ASC"
|
|
65
|
+
|
|
66
|
+
response = requests.get(
|
|
67
|
+
url,
|
|
68
|
+
headers=headers,
|
|
69
|
+
auth=auth,
|
|
70
|
+
params=params,
|
|
71
|
+
timeout=REQUEST_TIMEOUT,
|
|
72
|
+
)
|
|
73
|
+
response.raise_for_status()
|
|
74
|
+
|
|
75
|
+
data = response.json()
|
|
76
|
+
|
|
77
|
+
if not data:
|
|
78
|
+
break
|
|
79
|
+
|
|
80
|
+
yield data
|
|
81
|
+
|
|
82
|
+
if len(data) < limit:
|
|
83
|
+
break
|
|
84
|
+
|
|
85
|
+
offset += limit
|
|
@@ -4233,3 +4233,93 @@ class CouchbaseSource:
|
|
|
4233
4233
|
table_instance.max_table_nesting = 1
|
|
4234
4234
|
|
|
4235
4235
|
return table_instance
|
|
4236
|
+
|
|
4237
|
+
|
|
4238
|
+
class SocrataSource:
|
|
4239
|
+
def handles_incrementality(self) -> bool:
|
|
4240
|
+
return False
|
|
4241
|
+
|
|
4242
|
+
def dlt_source(self, uri: str, table: str, **kwargs):
|
|
4243
|
+
"""
|
|
4244
|
+
Creates a DLT source for Socrata open data platform.
|
|
4245
|
+
|
|
4246
|
+
URI format: socrata://domain?app_token=TOKEN
|
|
4247
|
+
Table: dataset_id (e.g., "6udu-fhnu")
|
|
4248
|
+
|
|
4249
|
+
Args:
|
|
4250
|
+
uri: Socrata connection URI with domain and optional auth params
|
|
4251
|
+
table: Dataset ID (e.g., "6udu-fhnu")
|
|
4252
|
+
**kwargs: Additional arguments:
|
|
4253
|
+
- incremental_key: Field to use for incremental loading (e.g., ":updated_at")
|
|
4254
|
+
- interval_start: Start date for initial load
|
|
4255
|
+
- interval_end: End date for load
|
|
4256
|
+
- primary_key: Primary key field for merge operations
|
|
4257
|
+
|
|
4258
|
+
Returns:
|
|
4259
|
+
DltResource for the Socrata dataset
|
|
4260
|
+
"""
|
|
4261
|
+
from urllib.parse import parse_qs, urlparse
|
|
4262
|
+
|
|
4263
|
+
parsed = urlparse(uri)
|
|
4264
|
+
|
|
4265
|
+
domain = parsed.netloc
|
|
4266
|
+
if not domain:
|
|
4267
|
+
raise ValueError(
|
|
4268
|
+
"Domain must be provided in the URI.\n"
|
|
4269
|
+
"Format: socrata://domain?app_token=TOKEN\n"
|
|
4270
|
+
"Example: socrata://evergreen.data.socrata.com?app_token=mytoken"
|
|
4271
|
+
)
|
|
4272
|
+
|
|
4273
|
+
query_params = parse_qs(parsed.query)
|
|
4274
|
+
|
|
4275
|
+
dataset_id = table
|
|
4276
|
+
if not dataset_id:
|
|
4277
|
+
raise ValueError(
|
|
4278
|
+
"Dataset ID must be provided as the table parameter.\n"
|
|
4279
|
+
"Example: --source-table 6udu-fhnu"
|
|
4280
|
+
)
|
|
4281
|
+
|
|
4282
|
+
app_token = query_params.get("app_token", [None])[0]
|
|
4283
|
+
username = query_params.get("username", [None])[0]
|
|
4284
|
+
password = query_params.get("password", [None])[0]
|
|
4285
|
+
|
|
4286
|
+
incremental = None
|
|
4287
|
+
if kwargs.get("incremental_key"):
|
|
4288
|
+
start_value = kwargs.get("interval_start")
|
|
4289
|
+
end_value = kwargs.get("interval_end")
|
|
4290
|
+
|
|
4291
|
+
if start_value:
|
|
4292
|
+
start_value = (
|
|
4293
|
+
start_value.isoformat()
|
|
4294
|
+
if hasattr(start_value, "isoformat")
|
|
4295
|
+
else str(start_value)
|
|
4296
|
+
)
|
|
4297
|
+
|
|
4298
|
+
if end_value:
|
|
4299
|
+
end_value = (
|
|
4300
|
+
end_value.isoformat()
|
|
4301
|
+
if hasattr(end_value, "isoformat")
|
|
4302
|
+
else str(end_value)
|
|
4303
|
+
)
|
|
4304
|
+
|
|
4305
|
+
incremental = dlt_incremental(
|
|
4306
|
+
kwargs.get("incremental_key", ""),
|
|
4307
|
+
initial_value=start_value,
|
|
4308
|
+
end_value=end_value,
|
|
4309
|
+
range_end="open",
|
|
4310
|
+
range_start="closed",
|
|
4311
|
+
)
|
|
4312
|
+
|
|
4313
|
+
primary_key = kwargs.get("primary_key")
|
|
4314
|
+
|
|
4315
|
+
from ingestr.src.socrata_source import source
|
|
4316
|
+
|
|
4317
|
+
return source(
|
|
4318
|
+
domain=domain,
|
|
4319
|
+
dataset_id=dataset_id,
|
|
4320
|
+
app_token=app_token,
|
|
4321
|
+
username=username,
|
|
4322
|
+
password=password,
|
|
4323
|
+
incremental=incremental,
|
|
4324
|
+
primary_key=primary_key,
|
|
4325
|
+
).with_resources("dataset")
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
version = "v0.14.94"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|