{"id":22903950,"url":"https://github.com/tracktor/tracktolib","last_synced_at":"2026-02-10T10:07:09.435Z","repository":{"id":62997710,"uuid":"564239249","full_name":"Tracktor/tracktolib","owner":"Tracktor","description":"Utility library for python","archived":false,"fork":false,"pushed_at":"2026-01-21T21:50:15.000Z","size":1849,"stargazers_count":3,"open_issues_count":2,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2026-01-21T22:16:33.047Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://tracktor.github.io/tracktolib/","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Tracktor.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2022-11-10T09:45:16.000Z","updated_at":"2026-01-21T20:56:43.000Z","dependencies_parsed_at":"2022-11-10T15:45:18.413Z","dependency_job_id":"b38b91cb-6c84-412b-b7a3-b7cebec53338","html_url":"https://github.com/Tracktor/tracktolib","commit_stats":{"total_commits":140,"total_committers":2,"mean_commits":70.0,"dds":0.4,"last_synced_commit":"91719109bbb6c453b9b02478b0440c30b9f8a68e"},"previous_names":[],"tags_count":118,"template":false,"template_full_name":null,"purl":"pkg:github/Tracktor/tracktolib","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Tracktor%2Ftracktolib","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Tracktor%2Ftracktolib/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Tracktor%2Ftracktolib/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Tracktor%2Ftracktolib/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Tracktor","download_url":"https://codeload.github.com/Tracktor/tracktolib/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Tracktor%2Ftracktolib/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28792638,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-26T21:49:50.245Z","status":"ssl_error","status_checked_at":"2026-01-26T21:48:29.455Z","response_time":59,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-12-14T02:39:34.145Z","updated_at":"2026-02-05T22:05:22.016Z","avatar_url":"https://github.com/Tracktor.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Tracktolib\n\n[![Python versions](https://img.shields.io/pypi/pyversions/tracktolib)](https://pypi.python.org/pypi/tracktolib)\n[![Latest PyPI version](https://img.shields.io/pypi/v/tracktolib?logo=pypi)](https://pypi.python.org/pypi/tracktolib)\n[![CI](https://github.com/Tracktor/tracktolib/actions/workflows/ci.yml/badge.svg)](https://github.com/Tracktor/tracktolib/actions/workflows/ci.yml)\n\nTracktor Swiss-knife Utility library.\n\n## Installation\n\n```bash\nuv add tracktolib\n```\n\nWith specific extras:\n\n```bash\nuv add tracktolib[pg,api]\n```\n\n## Modules\n\n### logs\n\nUtility functions to initialize logging formatting and streams.\n\n```python\nimport logging\nfrom tracktolib.logs import init_logging\n\nlogger = logging.getLogger()\nformatter, stream_handler = init_logging(logger, 'json', version='0.0.1')\n```\n\n### pg\n\nAsync PostgreSQL helpers using [asyncpg](https://github.com/MagicStack/asyncpg).\n\n```bash\nuv add tracktolib[pg]\n```\n\n### pg-sync\n\nSync PostgreSQL helpers using [psycopg](https://www.psycopg.org/psycopg3/) (v3).\n\n```bash\nuv add tracktolib[pg-sync]\n```\n\n```python\nfrom psycopg import connect\nfrom tracktolib.pg_sync import insert_many, fetch_one, fetch_count, fetch_all\n\nconn = connect('postgresql://user:pass@localhost/db')\n\ndata = [\n    {'foo': 'bar', 'value': 1},\n    {'foo': 'baz', 'value': 2}\n]\ninsert_many(conn, 'public.test', data)\n\nquery = 'SELECT foo from public.test order by value asc'\nvalue = fetch_one(conn, query, required=True)  # {'foo': 'bar'}, raises if not found\n\nassert fetch_count(conn, 'public.test') == 2\n\nquery = 'SELECT * from public.test order by value asc'\nassert fetch_all(conn, query) == data\n```\n\n### s3\n\nAsync S3 helpers using [aiobotocore](https://github.com/aio-libs/aiobotocore).\n\n```bash\nuv add tracktolib[s3]\n```\n\n### s3-minio\n\nS3 helpers using [minio](https://min.io/docs/minio/linux/developers/python/API.html).\n\n```bash\nuv add tracktolib[s3-minio]\n```\n\n### s3-niquests\n\nAsync S3 helpers using [niquests](https://github.com/jawah/niquests) and [botocore](https://github.com/boto/botocore) presigned URLs.\n\n```bash\nuv add tracktolib[s3-niquests]\n```\n\n```python\nfrom tracktolib.s3.niquests import S3Session\n\nasync with S3Session(\n    endpoint_url='http://localhost:9000',\n    access_key='...',\n    secret_key='...',\n    region='us-east-1',\n) as s3:\n    # Object operations\n    await s3.put_object('bucket', 'path/file.txt', b'content')\n    content = await s3.get_object('bucket', 'path/file.txt')\n    await s3.delete_object('bucket', 'path/file.txt')\n\n    # Streaming upload (multipart for large files)\n    async def data_stream():\n        yield b'chunk1'\n        yield b'chunk2'\n    await s3.file_upload('bucket', 'large-file.bin', data_stream())\n\n    # Bucket policy management\n    policy = {'Version': '2012-10-17', 'Statement': [...]}\n    await s3.put_bucket_policy('bucket', policy)\n    await s3.get_bucket_policy('bucket')\n    await s3.delete_bucket_policy('bucket')\n\n    # Empty a bucket (delete all objects)\n    deleted_count = await s3.empty_bucket('bucket')\n\n    # Sync a local directory to S3 (like aws s3 sync)\n    from pathlib import Path\n    result = await s3.sync_directory('bucket', Path('./local'), 'remote/prefix')\n    print(f\"Uploaded: {result['uploaded']}, Deleted: {result['deleted']}, Skipped: {result['skipped']}\")\n\n    # With delete flag to remove remote files not present locally\n    result = await s3.sync_directory('bucket', Path('./local'), 'remote/prefix', delete=True)\n```\n\n### http (deprecated)\n\nHTTP client helpers using [httpx](https://www.python-httpx.org/).\n\n```bash\nuv add tracktolib[http]\n```\n\n### api\n\nFastAPI utilities using [fastapi](https://fastapi.tiangolo.com/) and [pydantic](https://docs.pydantic.dev/).\n\n```bash\nuv add tracktolib[api]\n```\n\n### notion\n\nNotion API helpers using [niquests](https://github.com/jawah/niquests).\n\n```bash\nuv add tracktolib[notion]\n```\n\n```python\nimport niquests\nfrom tracktolib.notion.fetch import fetch_database, get_notion_headers\nfrom tracktolib.notion.cache import NotionCache\n\nasync with niquests.AsyncSession() as session:\n    session.headers.update(get_notion_headers())\n\n    # Without cache\n    db = await fetch_database(session, \"database-id\")\n\n    # With persistent cache (stored in ~/.cache/tracktolib/notion/cache.json)\n    cache = NotionCache()\n    db = await fetch_database(session, \"database-id\", cache=cache)\n\n    # Check cached databases\n    cache.get_databases()           # All cached databases\n    cache.get_database(\"db-id\")     # Specific database (id, title, properties, cached_at)\n```\n\n### gh\n\nGitHub API helpers using [niquests](https://github.com/jawah/niquests).\n\n```bash\nuv add tracktolib[gh]\n```\n\n```python\nfrom tracktolib.gh import GitHubClient\n\nasync with GitHubClient() as gh:  # Uses GITHUB_TOKEN env var\n    # Issue comments\n    comments = await gh.get_issue_comments(\"owner/repo\", 123)\n    await gh.create_issue_comment(\"owner/repo\", 123, \"Hello!\")\n    await gh.delete_comments_with_marker(\"owner/repo\", 123, \"\u003c!-- bot --\u003e\")\n\n    # Labels\n    labels = await gh.get_issue_labels(\"owner/repo\", 123)\n    await gh.add_labels(\"owner/repo\", 123, [\"bug\", \"priority\"])\n    await gh.remove_label(\"owner/repo\", 123, \"wontfix\")\n\n    # Deployments\n    deploys = await gh.get_deployments(\"owner/repo\", environment=\"production\")\n    await gh.mark_deployment_inactive(\"owner/repo\", \"preview-123\")\n```\n\n### cf\n\nCloudflare DNS API helpers using [niquests](https://github.com/jawah/niquests).\n\n```bash\nuv add tracktolib[cf]\n```\n\n```python\nfrom tracktolib.cf import CloudflareDNSClient\n\nasync with CloudflareDNSClient() as cf:  # Uses CLOUDFLARE_API_TOKEN and CLOUDFLARE_ZONE_ID env vars\n    # Get a DNS record\n    record = await cf.get_dns_record(\"app.example.com\", \"CNAME\")\n\n    # Create a DNS record\n    record = await cf.create_dns_record(\n        \"app.example.com\",\n        \"target.example.com\",\n        record_type=\"CNAME\",\n        ttl=60,\n        proxied=True,\n    )\n\n    # Delete by ID or name\n    await cf.delete_dns_record(record[\"id\"])\n    await cf.delete_dns_record_by_name(\"app.example.com\", \"CNAME\")\n\n    # Check existence\n    exists = await cf.dns_record_exists(\"app.example.com\")\n```\n\n### tests\n\nTesting utilities using [deepdiff](https://github.com/seperman/deepdiff).\n\n```bash\nuv add tracktolib[tests]\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftracktor%2Ftracktolib","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftracktor%2Ftracktolib","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftracktor%2Ftracktolib/lists"}