# Tach
[![downloads](https://static.pepy.tech/badge/tach/month)](https://pepy.tech/project/tach)
[![version](https://img.shields.io/pypi/v/tach.svg)](https://pypi.Python.org/pypi/tach)
[![license](https://img.shields.io/pypi/l/tach.svg)](https://pypi.Python.org/pypi/tach)
[![python](https://img.shields.io/pypi/pyversions/tach.svg)](https://pypi.Python.org/pypi/tach)
[![ci](https://github.com/gauge-sh/tach/actions/workflows/ci.yml/badge.svg)](https://github.com/gauge-sh/tach/actions/workflows/ci.yml)
[![pyright](https://microsoft.github.io/pyright/img/pyright_badge.svg)](https://microsoft.github.io/pyright/)
[![ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
a Python tool to enforce dependencies, written in Rust. Inspired by modular monolithic architecture.
[Docs](https://docs.gauge.sh)
[Discord](https://discord.gg/Kz2TnszerR)
<div align="center">
<img src="docs/assets/light_logo.png" alt="gauge-logo" width="30%" style="border-radius: 50%; padding-bottom: 20px"/>
</div>
Tach lets you define and enforce dependencies between Python modules within your project.
Here's an example:
![tach_demo](https://github.com/gauge-sh/tach/assets/10570340/6fc1e9b4-5a78-4330-a329-9187bd9c374d)
If a module tries to import from another module that is not listed as a dependency, Tach can prevent it.
Tach is:
- π Open source
- π Installable via pip
- π§ Able to be adopted incrementally
- β‘ Implemented with no runtime impact
- βΎοΈ Interoperable with your existing systems (cli, hooks, ci, etc.)
## Getting Started
### Installation
```bash
pip install tach
```
### Setup
Tach allows you to configure where you want to place module boundaries in your project.
You can do this interactively - run:
```bash
tach mod
# Up/Down: Navigate Enter: Mark/unmark module Right: Expand Left: Collapse Ctrl + Up: Jump to parent
# Ctrl + s: Exit and save Ctrl + c: Exit without saving Ctrl + a: Mark/unmark all
```
Mark each module boundary with 'Enter'. You can mark all of your top-level Python source packages, or just a few which you want to isolate.
If your Python code lives below your project root, or if you are working in a monorepo with multiple Python packages, mark your Python [source roots](https://docs.gauge.sh/usage/configuration#source-roots) using the 's' key.
This will create the config file for your project, `tach.toml`.
Once you've marked all the modules you want to enforce dependencies between, run:
```bash
tach sync
```
Dependencies that exist between each module you've marked will be written to `tach.toml`.
Check out what Tach has found!
```
cat tach.toml
```
Note: Your [source roots](https://docs.gauge.sh/usage/configuration#source-roots) will implicitly be treated as module boundaries, and can show up as `<root>`.
### Enforcement
Tach comes with a cli command to enforce the boundaries that you just set up! From the root of your Python project, run:
```bash
tach check
```
You will see:
```bash
β
All modules validated!
```
You can validate that Tach is working by either:
1. Commenting out an item in a `depends_on` key in `tach.toml`
2. By adding an import between modules that didn't previously import from each other.
Give both a try and run `tach check` again. This will generate an error:
```bash
β tach/check.py[L8]: Cannot import 'tach.filesystem'. Module 'tach' cannot depend on 'tach.filesystem'.
```
Each error indicates an import which violates your dependencies. If your terminal supports hyperlinks, click on the file path to go directly to the error.
When an error is detected, `tach check` will exit with a non-zero code. It can be easily integrated with CI/CD, [Pre-commit hooks](https://docs.gauge.sh/usage/commands#tach-install), and [VS Code](https://marketplace.visualstudio.com/items?itemName=Gauge.tach), and more!
### Extras
Visualize your dependency graph.
```bash
tach show [--web]
```
Tach will generate a graph of your dependencies. Here's what this looks like for Tach:
![tach show](docs/assets/tach_show.png)
Note that this graph is generated remotely with the contents of your `tach.toml` when running `tach show --web`.
If you would like to use the [GraphViz DOT format](https://graphviz.org/about/) locally, simply running `tach show` will generate `tach_module_graph.dot` in your working directory.
You can view the dependencies and usages for a given path:
```bash
tach report my_package/
# OR
tach report my_module.py
```
e.g.:
```bash
> tach report python/tach/filesystem
[Dependencies of 'python/tach/filesystem']
python/tach/filesystem/install.py[L6]: Import 'tach.hooks.build_pre_commit_hook_content'
python/tach/filesystem/project.py[L5]: Import 'tach.constants.CONFIG_FILE_NAME'
...
-------------------------------
[Usages of 'python/tach/filesystem']
python/tach/cache/access.py[L8]: Import 'tach.filesystem.find_project_config_root'
python/tach/cache/setup.py[L7]: Import 'tach.filesystem.find_project_config_root'
...
```
Tach also supports:
- [Public interfaces for modules](https://docs.gauge.sh/usage/interfaces/)
- [Deprecating individual dependencies](https://docs.gauge.sh/usage/deprecate)
- [Incremental adoption](https://docs.gauge.sh/usage/unchecked-modules)
- [Manual file configuration](https://docs.gauge.sh/usage/configuration)
- [Monorepos and namespace packages](https://docs.gauge.sh/usage/configuration#source-roots)
- [Inline exceptions](https://docs.gauge.sh/usage/tach-ignore)
- [Pre-commit hooks](https://docs.gauge.sh/usage/commands#tach-install)
More info in the [docs](https://docs.gauge.sh/). Tach logs anonymized usage statistics which can be [opted out](https://docs.gauge.sh/usage/faq/) of.
If you have any feedback, we'd love to talk!
If you have any questions or run into any issues, let us know by either reaching out on [Discord](https://discord.gg/Kz2TnszerR) or submitting a [Github Issue](https://github.com/gauge-sh/tach/issues)!
---
### Contributors
<a href="https://github.com/gauge-sh/tach/graphs/contributors">
<img src="https://contrib.rocks/image?repo=gauge-sh/tach" />
</a>
Raw data
{
"_id": null,
"home_page": null,
"name": "tach",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.7",
"maintainer_email": null,
"keywords": "python, module, package, guard, enforcement, boundary, enforcer, domain, architecture",
"author": null,
"author_email": "Caelean Barnes <caeleanb@gmail.com>, Evan Doyle <evanmdoyle@gmail.com>",
"download_url": "https://files.pythonhosted.org/packages/e6/53/580d3bfc18573e51f7a61bbfd18567774d4d647309fc944246c877b7df23/tach-0.17.0.tar.gz",
"platform": null,
"description": "# Tach\n\n[![downloads](https://static.pepy.tech/badge/tach/month)](https://pepy.tech/project/tach)\n[![version](https://img.shields.io/pypi/v/tach.svg)](https://pypi.Python.org/pypi/tach)\n[![license](https://img.shields.io/pypi/l/tach.svg)](https://pypi.Python.org/pypi/tach)\n[![python](https://img.shields.io/pypi/pyversions/tach.svg)](https://pypi.Python.org/pypi/tach)\n[![ci](https://github.com/gauge-sh/tach/actions/workflows/ci.yml/badge.svg)](https://github.com/gauge-sh/tach/actions/workflows/ci.yml)\n[![pyright](https://microsoft.github.io/pyright/img/pyright_badge.svg)](https://microsoft.github.io/pyright/)\n[![ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)\n\na Python tool to enforce dependencies, written in Rust. Inspired by modular monolithic architecture.\n\n[Docs](https://docs.gauge.sh)\n\n[Discord](https://discord.gg/Kz2TnszerR)\n\n<div align=\"center\">\n <img src=\"docs/assets/light_logo.png\" alt=\"gauge-logo\" width=\"30%\" style=\"border-radius: 50%; padding-bottom: 20px\"/>\n</div>\n\nTach lets you define and enforce dependencies between Python modules within your project.\n\nHere's an example:\n\n![tach_demo](https://github.com/gauge-sh/tach/assets/10570340/6fc1e9b4-5a78-4330-a329-9187bd9c374d)\n\nIf a module tries to import from another module that is not listed as a dependency, Tach can prevent it.\n\nTach is:\n\n- \ud83c\udf0e Open source\n- \ud83d\udc0d Installable via pip\n- \ud83d\udd27 Able to be adopted incrementally\n- \u26a1 Implemented with no runtime impact\n- \u267e\ufe0f Interoperable with your existing systems (cli, hooks, ci, etc.)\n\n## Getting Started\n\n### Installation\n\n```bash\npip install tach\n```\n\n### Setup\n\nTach allows you to configure where you want to place module boundaries in your project.\n\nYou can do this interactively - run:\n\n```bash\n tach mod\n# Up/Down: Navigate Enter: Mark/unmark module Right: Expand Left: Collapse Ctrl + Up: Jump to parent\n# Ctrl + s: Exit and save Ctrl + c: Exit without saving Ctrl + a: Mark/unmark all\n```\n\nMark each module boundary with 'Enter'. You can mark all of your top-level Python source packages, or just a few which you want to isolate.\n\nIf your Python code lives below your project root, or if you are working in a monorepo with multiple Python packages, mark your Python [source roots](https://docs.gauge.sh/usage/configuration#source-roots) using the 's' key.\n\nThis will create the config file for your project, `tach.toml`.\n\nOnce you've marked all the modules you want to enforce dependencies between, run:\n\n```bash\ntach sync\n```\n\nDependencies that exist between each module you've marked will be written to `tach.toml`.\n\nCheck out what Tach has found!\n\n```\ncat tach.toml\n```\n\nNote: Your [source roots](https://docs.gauge.sh/usage/configuration#source-roots) will implicitly be treated as module boundaries, and can show up as `<root>`.\n\n### Enforcement\n\nTach comes with a cli command to enforce the boundaries that you just set up! From the root of your Python project, run:\n\n```bash\ntach check\n```\n\nYou will see:\n\n```bash\n\u2705 All modules validated!\n```\n\nYou can validate that Tach is working by either:\n\n1. Commenting out an item in a `depends_on` key in `tach.toml`\n2. By adding an import between modules that didn't previously import from each other.\n\nGive both a try and run `tach check` again. This will generate an error:\n\n```bash\n\u274c tach/check.py[L8]: Cannot import 'tach.filesystem'. Module 'tach' cannot depend on 'tach.filesystem'.\n```\n\nEach error indicates an import which violates your dependencies. If your terminal supports hyperlinks, click on the file path to go directly to the error.\n\nWhen an error is detected, `tach check` will exit with a non-zero code. It can be easily integrated with CI/CD, [Pre-commit hooks](https://docs.gauge.sh/usage/commands#tach-install), and [VS Code](https://marketplace.visualstudio.com/items?itemName=Gauge.tach), and more!\n\n### Extras\n\nVisualize your dependency graph.\n\n```bash\ntach show [--web]\n```\n\nTach will generate a graph of your dependencies. Here's what this looks like for Tach:\n\n![tach show](docs/assets/tach_show.png)\n\nNote that this graph is generated remotely with the contents of your `tach.toml` when running `tach show --web`.\n\nIf you would like to use the [GraphViz DOT format](https://graphviz.org/about/) locally, simply running `tach show` will generate `tach_module_graph.dot` in your working directory.\n\nYou can view the dependencies and usages for a given path:\n\n```bash\ntach report my_package/\n# OR\ntach report my_module.py\n```\n\ne.g.:\n\n```bash\n> tach report python/tach/filesystem\n[Dependencies of 'python/tach/filesystem']\npython/tach/filesystem/install.py[L6]: Import 'tach.hooks.build_pre_commit_hook_content'\npython/tach/filesystem/project.py[L5]: Import 'tach.constants.CONFIG_FILE_NAME'\n...\n-------------------------------\n[Usages of 'python/tach/filesystem']\npython/tach/cache/access.py[L8]: Import 'tach.filesystem.find_project_config_root'\npython/tach/cache/setup.py[L7]: Import 'tach.filesystem.find_project_config_root'\n...\n```\n\nTach also supports:\n\n- [Public interfaces for modules](https://docs.gauge.sh/usage/interfaces/)\n- [Deprecating individual dependencies](https://docs.gauge.sh/usage/deprecate)\n- [Incremental adoption](https://docs.gauge.sh/usage/unchecked-modules)\n- [Manual file configuration](https://docs.gauge.sh/usage/configuration)\n- [Monorepos and namespace packages](https://docs.gauge.sh/usage/configuration#source-roots)\n- [Inline exceptions](https://docs.gauge.sh/usage/tach-ignore)\n- [Pre-commit hooks](https://docs.gauge.sh/usage/commands#tach-install)\n\nMore info in the [docs](https://docs.gauge.sh/). Tach logs anonymized usage statistics which can be [opted out](https://docs.gauge.sh/usage/faq/) of.\nIf you have any feedback, we'd love to talk!\n\nIf you have any questions or run into any issues, let us know by either reaching out on [Discord](https://discord.gg/Kz2TnszerR) or submitting a [Github Issue](https://github.com/gauge-sh/tach/issues)!\n\n---\n\n### Contributors\n\n<a href=\"https://github.com/gauge-sh/tach/graphs/contributors\">\n <img src=\"https://contrib.rocks/image?repo=gauge-sh/tach\" />\n</a>\n\n",
"bugtrack_url": null,
"license": null,
"summary": "A Python tool to maintain a modular package architecture.",
"version": "0.17.0",
"project_urls": {
"Homepage": "https://github.com/gauge-sh/tach",
"Issues": "https://github.com/gauge-sh/tach/issues"
},
"split_keywords": [
"python",
" module",
" package",
" guard",
" enforcement",
" boundary",
" enforcer",
" domain",
" architecture"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "28f3d4c0e26f12d7625f7e01f90e1e27813dbea54b1c727ac59c427ad8a7ea6f",
"md5": "9e0b907875d11921ef9b73a8e852ca2a",
"sha256": "6cc3d91dee8735f57ea009a82d601a5e5ec65324830182c9e46dff2fd8e128c4"
},
"downloads": -1,
"filename": "tach-0.17.0-cp37-abi3-macosx_10_12_x86_64.whl",
"has_sig": false,
"md5_digest": "9e0b907875d11921ef9b73a8e852ca2a",
"packagetype": "bdist_wheel",
"python_version": "cp37",
"requires_python": ">=3.7",
"size": 2622893,
"upload_time": "2024-12-10T01:40:48",
"upload_time_iso_8601": "2024-12-10T01:40:48.945457Z",
"url": "https://files.pythonhosted.org/packages/28/f3/d4c0e26f12d7625f7e01f90e1e27813dbea54b1c727ac59c427ad8a7ea6f/tach-0.17.0-cp37-abi3-macosx_10_12_x86_64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "5335b1f5c5db31d34b43ff2532bfc20c69ec676d0b2521a24d33d376f244a4f9",
"md5": "c84cff59c62e3d6accedaa21c681d35d",
"sha256": "b6a6f14ff44d9586798c67e09ff64a0246938eb26dab51f4af7667681faffa17"
},
"downloads": -1,
"filename": "tach-0.17.0-cp37-abi3-macosx_11_0_arm64.whl",
"has_sig": false,
"md5_digest": "c84cff59c62e3d6accedaa21c681d35d",
"packagetype": "bdist_wheel",
"python_version": "cp37",
"requires_python": ">=3.7",
"size": 2496453,
"upload_time": "2024-12-10T01:40:47",
"upload_time_iso_8601": "2024-12-10T01:40:47.546152Z",
"url": "https://files.pythonhosted.org/packages/53/35/b1f5c5db31d34b43ff2532bfc20c69ec676d0b2521a24d33d376f244a4f9/tach-0.17.0-cp37-abi3-macosx_11_0_arm64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "6337a1c03f6adc16c5aa2f7a32c170f93095a06d8f947142f511845168ba9de8",
"md5": "14c99da42610f6b8a352897a76f2aaa5",
"sha256": "dee35dfff64d1a6c1b3edccb323043f4b768e9992a323161e6b6ccdda8f3fb4e"
},
"downloads": -1,
"filename": "tach-0.17.0-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",
"has_sig": false,
"md5_digest": "14c99da42610f6b8a352897a76f2aaa5",
"packagetype": "bdist_wheel",
"python_version": "cp37",
"requires_python": ">=3.7",
"size": 2734716,
"upload_time": "2024-12-10T01:40:29",
"upload_time_iso_8601": "2024-12-10T01:40:29.290395Z",
"url": "https://files.pythonhosted.org/packages/63/37/a1c03f6adc16c5aa2f7a32c170f93095a06d8f947142f511845168ba9de8/tach-0.17.0-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "e10730cf46aee106e45c323ca23f7f81de7a14a31afcc30890b887a6e150b03c",
"md5": "86c18244815506995c58f9e68ab40027",
"sha256": "67cb622182c2e8b478db327fe5197a9e9ca9c1e4b97a48332da96908c7d7feff"
},
"downloads": -1,
"filename": "tach-0.17.0-cp37-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl",
"has_sig": false,
"md5_digest": "86c18244815506995c58f9e68ab40027",
"packagetype": "bdist_wheel",
"python_version": "cp37",
"requires_python": ">=3.7",
"size": 2708504,
"upload_time": "2024-12-10T01:40:33",
"upload_time_iso_8601": "2024-12-10T01:40:33.247952Z",
"url": "https://files.pythonhosted.org/packages/e1/07/30cf46aee106e45c323ca23f7f81de7a14a31afcc30890b887a6e150b03c/tach-0.17.0-cp37-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "8cfe2eb9b2a8aeee56c3d2f94d2c0e436c4c865d762f296278b6db69317e5896",
"md5": "abd7cb3e5c5a4751abc7373f3a51fc84",
"sha256": "d5d0eec707b9823d3d1464882db3232a72b219098d97d53c491782eea6be644d"
},
"downloads": -1,
"filename": "tach-0.17.0-cp37-abi3-manylinux_2_17_i686.manylinux2014_i686.whl",
"has_sig": false,
"md5_digest": "abd7cb3e5c5a4751abc7373f3a51fc84",
"packagetype": "bdist_wheel",
"python_version": "cp37",
"requires_python": ">=3.7",
"size": 2969174,
"upload_time": "2024-12-10T01:40:41",
"upload_time_iso_8601": "2024-12-10T01:40:41.570944Z",
"url": "https://files.pythonhosted.org/packages/8c/fe/2eb9b2a8aeee56c3d2f94d2c0e436c4c865d762f296278b6db69317e5896/tach-0.17.0-cp37-abi3-manylinux_2_17_i686.manylinux2014_i686.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "cd38e4dc75d3dee410402d630cc5abdc21ca83810fa16caf20b1b67c9f1fa933",
"md5": "64a4a122d63eb5018d711e03b8133769",
"sha256": "df952f7c434c6f3bb277e63c40219eac5fbbec695447dd5d3968411f9fa747d6"
},
"downloads": -1,
"filename": "tach-0.17.0-cp37-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl",
"has_sig": false,
"md5_digest": "64a4a122d63eb5018d711e03b8133769",
"packagetype": "bdist_wheel",
"python_version": "cp37",
"requires_python": ">=3.7",
"size": 2981733,
"upload_time": "2024-12-10T01:40:35",
"upload_time_iso_8601": "2024-12-10T01:40:35.851283Z",
"url": "https://files.pythonhosted.org/packages/cd/38/e4dc75d3dee410402d630cc5abdc21ca83810fa16caf20b1b67c9f1fa933/tach-0.17.0-cp37-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "9f17b72c5d99cbef087a8c223e82d69e644f9a6d1ae0bee91fa7548e3b09f6a0",
"md5": "3bd30e5f7bceb5eee4f3fc87a635507e",
"sha256": "d2eaa2b5b7a328b9e744fccbda216179ad3aa9e870294141958da5830051299a"
},
"downloads": -1,
"filename": "tach-0.17.0-cp37-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl",
"has_sig": false,
"md5_digest": "3bd30e5f7bceb5eee4f3fc87a635507e",
"packagetype": "bdist_wheel",
"python_version": "cp37",
"requires_python": ">=3.7",
"size": 3137383,
"upload_time": "2024-12-10T01:40:37",
"upload_time_iso_8601": "2024-12-10T01:40:37.486951Z",
"url": "https://files.pythonhosted.org/packages/9f/17/b72c5d99cbef087a8c223e82d69e644f9a6d1ae0bee91fa7548e3b09f6a0/tach-0.17.0-cp37-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "d6c2784669382b9fd78de3b34baa198ef8368c71523dbb268e57b50138940ab9",
"md5": "5de52ae0d3f282e0856bfd661c6f7ff0",
"sha256": "30fd154235df9dca944ebabb43eca7641de0a84a74bbf72365c22cb6547ab2e9"
},
"downloads": -1,
"filename": "tach-0.17.0-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
"has_sig": false,
"md5_digest": "5de52ae0d3f282e0856bfd661c6f7ff0",
"packagetype": "bdist_wheel",
"python_version": "cp37",
"requires_python": ">=3.7",
"size": 2838966,
"upload_time": "2024-12-10T01:40:44",
"upload_time_iso_8601": "2024-12-10T01:40:44.248849Z",
"url": "https://files.pythonhosted.org/packages/d6/c2/784669382b9fd78de3b34baa198ef8368c71523dbb268e57b50138940ab9/tach-0.17.0-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "bfe028221f09a4a3e2672d1b5d7dbe08d4196566ac689fc7f366bcc93b8b7271",
"md5": "728672ae449c50c97e9987ca16c0bccd",
"sha256": "525495fbf2ef7bf3352eb92a3f0c1988ff5f9444e62ba0ddd7561e3e4ad19cab"
},
"downloads": -1,
"filename": "tach-0.17.0-cp37-abi3-win32.whl",
"has_sig": false,
"md5_digest": "728672ae449c50c97e9987ca16c0bccd",
"packagetype": "bdist_wheel",
"python_version": "cp37",
"requires_python": ">=3.7",
"size": 2257785,
"upload_time": "2024-12-10T01:40:56",
"upload_time_iso_8601": "2024-12-10T01:40:56.410209Z",
"url": "https://files.pythonhosted.org/packages/bf/e0/28221f09a4a3e2672d1b5d7dbe08d4196566ac689fc7f366bcc93b8b7271/tach-0.17.0-cp37-abi3-win32.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "cd3dcfb14005e7a8eed6c6e5d29429e4904e0c147ba52e6a5310d13c814acf86",
"md5": "8f44afda3bc46c9b21c8e68ca2a8935c",
"sha256": "ed511d9f0e39c97da287aaeedbeaa980ba96bdc92b13d03d36a288b38dbd2cf2"
},
"downloads": -1,
"filename": "tach-0.17.0-cp37-abi3-win_amd64.whl",
"has_sig": false,
"md5_digest": "8f44afda3bc46c9b21c8e68ca2a8935c",
"packagetype": "bdist_wheel",
"python_version": "cp37",
"requires_python": ">=3.7",
"size": 2408883,
"upload_time": "2024-12-10T01:40:54",
"upload_time_iso_8601": "2024-12-10T01:40:54.785501Z",
"url": "https://files.pythonhosted.org/packages/cd/3d/cfb14005e7a8eed6c6e5d29429e4904e0c147ba52e6a5310d13c814acf86/tach-0.17.0-cp37-abi3-win_amd64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "e653580d3bfc18573e51f7a61bbfd18567774d4d647309fc944246c877b7df23",
"md5": "0ae6f1e81f9cb83aaf703ab43ebb2a08",
"sha256": "da251345239d144048ebbe8c98552ca6d639344c010530676e4d138d8e268846"
},
"downloads": -1,
"filename": "tach-0.17.0.tar.gz",
"has_sig": false,
"md5_digest": "0ae6f1e81f9cb83aaf703ab43ebb2a08",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.7",
"size": 729996,
"upload_time": "2024-12-10T01:40:50",
"upload_time_iso_8601": "2024-12-10T01:40:50.487362Z",
"url": "https://files.pythonhosted.org/packages/e6/53/580d3bfc18573e51f7a61bbfd18567774d4d647309fc944246c877b7df23/tach-0.17.0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-12-10 01:40:50",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "gauge-sh",
"github_project": "tach",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "tach"
}