{"id":14974119,"url":"https://github.com/ya7010/turu-py","last_synced_at":"2026-04-19T05:02:41.182Z","repository":{"id":213319861,"uuid":"730700597","full_name":"ya7010/turu-py","owner":"ya7010","description":"Simple Database API for Typed Python","archived":false,"fork":false,"pushed_at":"2025-08-12T09:13:31.000Z","size":3551,"stargazers_count":6,"open_issues_count":8,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-08-15T09:54:56.464Z","etag":null,"topics":["async","bigquery","pep249","postgres","postgresql","postgresql-database","python","snowflake","snowflakedb","sqlite","sqlite-database","sqlite3","sqlite3-database","typed-python"],"latest_commit_sha":null,"homepage":"https://yassun7010.github.io/turu-py/","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ya7010.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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}},"created_at":"2023-12-12T13:42:33.000Z","updated_at":"2025-03-28T05:37:12.000Z","dependencies_parsed_at":"2023-12-19T21:20:25.886Z","dependency_job_id":"7922abbb-96ee-4417-a70b-236f747fac85","html_url":"https://github.com/ya7010/turu-py","commit_stats":{"total_commits":478,"total_committers":2,"mean_commits":239.0,"dds":"0.18410041841004188","last_synced_commit":"4cc2e18cbbd612fa4ca830ccb9b533204780cf6e"},"previous_names":["yassun7010/turu-py","ya7010/turu-py"],"tags_count":45,"template":false,"template_full_name":null,"purl":"pkg:github/ya7010/turu-py","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ya7010%2Fturu-py","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ya7010%2Fturu-py/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ya7010%2Fturu-py/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ya7010%2Fturu-py/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ya7010","download_url":"https://codeload.github.com/ya7010/turu-py/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ya7010%2Fturu-py/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":271628166,"owners_count":24792821,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-22T02:00:08.480Z","response_time":65,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":["async","bigquery","pep249","postgres","postgresql","postgresql-database","python","snowflake","snowflakedb","sqlite","sqlite-database","sqlite3","sqlite3-database","typed-python"],"created_at":"2024-09-24T13:49:59.151Z","updated_at":"2026-04-19T05:02:41.172Z","avatar_url":"https://github.com/ya7010.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Turu: Simple Database Client for Typed Python\n\n\u003c!-- --8\u003c-- [start:badges] --\u003e\n[![docs](https://github.com/ya7010/turu-py/actions/workflows/publish-mkdocs.yml/badge.svg)](https://ya7010.github.io/turu-py/)\n[![test](https://github.com/ya7010/turu-py/actions/workflows/test-suite.yml/badge.svg)](https://github.com/ya7010/turu-py/actions)\n[![pypi package](https://badge.fury.io/py/turu.svg)](https://pypi.org/project/turu)\n\u003c!-- --8\u003c-- [end:badges] --\u003e\n\n\u003cp align=\"center\"\u003e\n    \u003cimg alt=\"logo\" src=\"https://raw.githubusercontent.com/ya7010/turu-py/main/docs/images/logo.svg\" width=\"300\" /\u003e\n\u003c/p\u003e\n\n---\n\n**Documentation**: \u003ca href=\"https://ya7010.github.io/turu-py/\" target=\"_blank\"\u003ehttps://ya7010.github.io/turu-py/\u003c/a\u003e\n\n**Source Code**: \u003ca href=\"https://github.com/ya7010/turu-py\" target=\"_blank\"\u003ehttps://github.com/ya7010/turu-py\u003c/a\u003e\n\n---\n\n## Installation\n\n```bash\npip install \"turu[snowflake]\"\n```\n\n\u003c!-- --8\u003c-- [start:why_turu] --\u003e\n## Why Turu?\nSQL is a powerful language, but it has many dialects, and Cloud Native Databases are especially difficult to test automatically in a local environment.\n\nTuru was developed as a simple tool to assist local development.\nIt provides a simple interface according to [PEP 249 – Python Database API Specification v2.0](https://peps.python.org/pep-0249/) and allows for easy recording of query results and injection mock data.\n\u003c!-- --8\u003c-- [end:why_turu] --\u003e\n\n\u003c!-- --8\u003c-- [start:features] --\u003e\n## Features\n\n- :rocket: **Simple** - Turu is a simple database api wrapper of [PEP 249](https://peps.python.org/pep-0249/).\n- :bulb: **Type Hint**  - Full support for type hints.\n- :zap: **Async/Await** - Async/Await supports.\n- :test_tube: **Recoed and Mock** - Record and mock database queries for testing.\n\u003c!-- --8\u003c-- [end:features] --\u003e\n\n\u003c!-- --8\u003c-- [start:adapters] --\u003e\n## Supprted Database\n\n| Database   | Sync Support | Async Support | Installation                    |\n| ---------- | ------------ | ------------- | ------------------------------- |\n| SQLite3    | Yes          | Yes           | `pip install \"turu[sqlite3]\"`   |\n| MySQL      | Yes          | Yes           | `pip install \"turu[mysql]\"`     |\n| PostgreSQL | Yes          | Yes           | `pip install \"turu[postgres]\"`  |\n| Snowflake  | Yes          | Yes           | `pip install \"turu[snowflake]\"` |\n| BigQuery   | Yes          | No            | `pip install \"turu[bigquery]\"`  |\n\u003c!-- --8\u003c-- [end:adapters] --\u003e\n\n## Usage\n\n### Basic Usage\n\n```python\nfrom pydantic import BaseModel\n\n\nclass Row(BaseModel):\n    id: int\n    name: str\n\nconnection = turu.sqlite3.connect(\"test.db\")\n\nwith connection.cursor() as cursor:\n    assert cursor.execute_map(Row, \"select 1, 'a'\").fetchone() == Row(id=1, name=\"a\")\n```\n\n## Testing\n\n```python\nimport turu.sqlite3\n\nfrom pydantic import BaseModel\n\n\nclass Row(BaseModel):\n    id: int\n    name: str\n\nexpected1 = [Row(id=1, name=\"a\"), Row(id=2, name=\"b\")]\nexpected2 = [Row(id=3, name=\"c\"), Row(id=4, name=\"d\")]\nexpected3 = [Row(id=5, name=\"e\"), Row(id=6, name=\"f\")]\n\nconnection = turu.sqlite3.MockConnection()\n\n(\n    connection.chain()\n    .inject_response(Row, expected1)\n    .inject_response(Row, expected2)\n    .inject_response(Row, expected3)\n)\n\nfor expected in [expected1, expected2, expected3]:\n    with connection.cursor() as cursor:\n        assert cursor.execute_map(Row, \"select 1, 'a'\").fetchall() == expected\n```\n\n## Recording and Testing\n\nYour Production Code\n\n```python\nimport os\n\nimport turu.sqlite3\nfrom turu.core.record import record_to_csv\n\nfrom your_package.data import RECORD_DIR\nfrom your_package.schema import Row\n\n\ndef do_something(connection: turu.sqlite3.Connection):\n    with record_to_csv(\n        RECORD_DIR / \"test.csv\",\n        connection.curosr(),\n        enable=os.environ.get(\"ENABLE_RECORDING\"),\n        limit=100,\n    ) as cursor:\n        ... # Your logic\n```\n\nYour Test Code\n\n```python\nimport turu.sqlite3\n\nfrom your_package.data import RECORD_DIR\nfrom your_package.schema import Row\n\n\ndef test_do_something(connection: turu.sqlite3.MockConnection):\n    connection.inject_response_from_csv(Row, RECORD_DIR / \"test.csv\")\n\n    assert do_something(connection) is None\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fya7010%2Fturu-py","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fya7010%2Fturu-py","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fya7010%2Fturu-py/lists"}