Name | pytoma JSON |
Version |
0.1.0a6
JSON |
| download |
home_page | None |
Summary | Render a repo into one LLM-ready text file |
upload_time | 2025-08-19 16:45:39 |
maintainer | None |
docs_url | None |
author | None |
requires_python | >=3.9 |
license | Copyright 2025 Nathan Palluau
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
keywords |
llm
code-slicing
developer-tools
prompting
repo-pack
|
VCS |
 |
bugtrack_url |
|
requirements |
No requirements were recorded.
|
Travis-CI |
No Travis.
|
coveralls test coverage |
No coveralls.
|
# Pytoma — Repo text rendering
Pytoma condenses your python repo into one concise, LLM-friendly, text file.
You choose **what to show** (full code, signature + docstring, partial bodies ...) **per function, class, file, or folder**.
You can configure what will be shown via a small YAML config or CLI options, and the output is a single text file divided in fenced code blocks, ideal for prompting an LLM or sharing a focused snapshot with collaborators. You can also use it to hide sensitive code snippets to protect your innovative ideas.
Note from the author : I originally vibe-coded a basic tool for myself because ChatGPT wouldn't accept more than 10 files and the files-to-prompts lib didn't allow me to hide certain sections ... but it turned out to be very handy and useful, so I refined it and it became this project.
---
## Highlights
* **Policy-driven slicing**: `full`, `sig`, `sig+doc`, `body:levels=k`, `hide` to omit sections, `file:no-imports` to omit imports
* **Targets**:
* by **qualname** (e.g. `pkg.mod:Class.method` or `pkg.mod:*`),
* by **path glob** (e.g. `**/repo/pkg/**/*.py`),
* or via a **global default**.
* **Multiple engines**:
* Python (`.py`): granular per function/method/class.
* Markdown (`.md`): per heading or whole document (supports `full`/`hide`).
* YAML will soon be added
* A description or short extract of heavy files, ML artifacts, etc., is also to be expected
---
## Installation
**Prerequisites:** Python ≥ 3.9
```bash
pip install pytoma
```
If you can't directly call pip :
```bash
python -m pip install pytoma
```
Of course, if your pip alias is pip3, replace pip by pip3 in the command (and if your python alias is python3, replace python by python3 ...)
You can verify your installation with
```bash
pytoma --version
pytoma --help
```
During installation, if `pip` prints a **warning** like:
```
The script 'pytoma' is installed in '…' which is not on PATH
```
Then you must permanently add **that folder** to your `PATH` (in your .bashrc or .zshrc), and then reopen the terminal.
As a fallback, you may also install from source :
```bash
git clone https://github.com/nathanap2/pytoma.git
cd pytoma
python -m pip install .
```
---
## Quick Start (CLI)
```bash
# Basic: pack a repo with defaults (same behaviour as files-to-prompt)
pytoma ./path/to/repo > PACK.txt
# Now we use a YAML config to customize the render (skip sections, etc.)
pytoma ./repo --config config.yml --out PACK.txt
```
The pack looks like:
````text
### pkg/module.py
```python
def foo(a: int, b: int) -> int:
"""Adds two numbers."""
# … lines 12–37 body omitted (26 lines) …
```
### docs/guide.md
<!-- … lines 1–120 document omitted (120 lines) … -->
````
---
## Configuration (YAML)
```yaml
# config.yml
default: full # fallback policy
# optional: exclude patterns (relative to the provided roots)
excludes:
- ".venv/**"
- "**/__pycache__/**"
- "dist/**"
- "build/**"
- "site-packages/**"
- "**/*.pyi"
rules:
# Apply a file-level filter first (removes top-level imports, keeps __future__)
- match: "/abs/path/to/repo/pkg/**/*.py"
mode: "file:no-imports"
# Then apply function-level policy to the same files
- match: "/abs/path/to/repo/pkg/**/*.py"
mode: "sig+doc"
# Hide an entire module (replaced by an omission marker)
- match: "/abs/path/to/repo/legacy/big_module.py"
mode: "hide"
# Target all defs in a given module by qualname
- match: "pkg.special:*"
mode: "body:levels=1"
# Markdown supports only "full" and "hide"
- match: "/abs/path/to/repo/README.md"
mode: "hide"
````
Note : when Pytoma walks each document’s nodes, it decides a policy with this order: qualname rules > path rules > global default.
---
## Policies
* `full` — leave the node as is.
* `hide` — remove and insert an omission marker:
* On a **module**: replaces the whole file content.
* On a **class**: replaces the whole class block.
* On a **function/method**: replaces the definition or its body depending on engine mode.
* `sig` — one-line header (`def …:`), body omitted with a marker.
* `sig+doc` — header + docstring (or `"""…"""` placeholder), body omitted.
* `body:levels=k` — keep code with indentation ≤ `base + 4*k`, collapse deeper blocks with markers.
* `file:no-imports` — strip top-level `import`/`from … import …` except `from __future__ import …`.
* `file:no-legacy-strings` — remove **top-level** triple-quoted strings that are
**not** the module docstring. These are often used to “comment out” legacy code blocks.
* `file:no-path-defs` — remove or condense **top-level** path-setup assignments
(RHS matching `os.path.*`, `pathlib.Path(...)`, `__file__`, or `Path(...)` when
imported from `pathlib`). A compact marker summarizes a few removed variables.
* `file:no-sys-path` — remove `sys.path` manipulations (`append`, `insert`, `extend`),
direct assignments (`sys.path = ...`), and in-place updates (`sys.path += ...`).
* `file:tidy` — **composite** cleaner that applies `file:no-imports`,
`file:no-legacy-strings`, `file:no-path-defs`, and `file:no-sys-path`
in one pass. Recommended when you want several file-level cleaners on the
same file, since only one `file:*` rule is applied per file rule.
Markers are comment-style lines (or a light box) with line counts, e.g.:
```python
# … lines 42–97 body omitted (56 lines) …
```
---
## Applying a policy to a whole file or folder
**Three options:**
1. **Global default**
```bash
pytoma /abs/repo --default "sig+doc"
```
2. **Path glob rule** (absolute POSIX)
```yaml
rules:
- match: "/abs/repo/pkg/**/*.py"
mode: "sig+doc"
```
3. **Qualname wildcard for a module**
```yaml
rules:
- match: "pkg.module:*"
mode: "sig+doc"
```
> For file-level effects like removing imports or hiding an entire file, use `file:no-imports` or `hide` on the path glob; these apply to the module root.
---
## Excludes
By default, Pytoma skips:
```
.venv/**, **/__pycache__/**, dist/**, build/**, site-packages/**, **/*.pyi
```
You can override in `config.yml → excludes`.
---
## Pitfalls
- **Rule order can still be tricky** when several rules are about the same file. I'm looking forward to improving that soon. For the moment, prefer being as explicit as possible, and for tricky setups, you can simply ask an LLM to draft the rules for you (from your repo tree and goals).
- To name a markdown section in the config file, you still **need to give the slugified version** of the section
- **Only one `file:*` action per rule target.** If you need to combine cleaners (imports + sys.path + path vars + legacy strings), prefer `file:tidy` instead of stacking multiple `file:*` rules on the same files.
## Roadmap
* Engine for **YAML / JSON** (keys/tables granularity), **CSV** (short preview like pandas does), etc.
* Better summary of skipped lines (for instance, when skipping imports, in the examples of skipped imports, we should probably prioritize unexpected imports over classic ones such as sys, os ...)
* Propose the automatic addition of inferred rules: in particular, functions that are only called by hidden functions should probably be hidden by default.
* More markers + Let the user choose their markers, rule by rule, using the configuration
* A “custom:alternative_version” rule to simply replace a block with an alternative version of the block provided by the user.
* Heuristics to suggest rules (and possibility to condition it by a section which we want to focus on) -> may actually become another independent tool ...
* ... and even smarter module targeting via **dependency graphs , embeddings**, git edit correlations, etc.
---
## Current engines & support matrix
| Engine / Mode | full | hide | sig | sig+doc | body\:levels=k | file\:no-imports |
| ---------------- | :--: | :--: | :-: | :-----: | :------------: | :--------------: |
| Python (`.py`) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| Markdown (`.md`) | ✅ | ✅ | – | – | – | – |
---
## How it works (short)
* Each engine parses a file into a lightweight IR:
* `Document` with a flat list of `Node`s (module, class, function, etc.).
* A decision step maps nodes to `Action`s (`full`, `sig+doc`, …) using the precedence above.
* Engines render actions into concrete `Edit`s (byte spans + replacements).
* Edits are **merged**.
* The final pack concatenates per-file sections with language fences.
---
## Example: start from a **skeleton** and ask the LLM for a focused `config.yml`
Goal: produce a **skeleton** of the repo (signatures/docstrings, no bodies), then wrap that snapshot in a prompt that asks the LLM to **choose a focus area** and return a minimal Pytoma `config.yml` that “expands” that area.
First **Generate the prompt from the skeleton**
```bash
# The "skeleton" preset renders a compact snapshot (e.g., signatures only).
# The "focus_to_config" prompt asks the LLM to reply with a minimal Pytoma YAML.
pytoma . \
--config skeleton \
--prompt focus_to_config \
--prompt-arg 'focus_note=improve the collision engine' \
--out PROMPT_CFG.txt
```
`PROMPT_CFG.txt` contains a short brief + the snapshot.
Now **Paste the prompt into your LLM** and retrieve a focused `config.yml` (expected shape).
Then you can **Apply that YAML** to produce a pack “expanded” around the chosen area.
---
## License
[MIT](LICENCE)
Raw data
{
"_id": null,
"home_page": null,
"name": "pytoma",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.9",
"maintainer_email": null,
"keywords": "LLM, code-slicing, developer-tools, prompting, repo-pack",
"author": null,
"author_email": "Nathan Palluau <nathan.palluau@gmail.com>",
"download_url": "https://files.pythonhosted.org/packages/c9/1c/8d07050ad182220f5f3cd2b5d1984f36148af250003f70ccfd1b065ce4d2/pytoma-0.1.0a6.tar.gz",
"platform": null,
"description": "# Pytoma \u2014 Repo text rendering\n\nPytoma condenses your python repo into one concise, LLM-friendly, text file.\nYou choose **what to show** (full code, signature + docstring, partial bodies ...) **per function, class, file, or folder**. \n\nYou can configure what will be shown via a small YAML config or CLI options, and the output is a single text file divided in fenced code blocks, ideal for prompting an LLM or sharing a focused snapshot with collaborators. You can also use it to hide sensitive code snippets to protect your innovative ideas.\n\nNote from the author : I originally vibe-coded a basic tool for myself because ChatGPT wouldn't accept more than 10 files and the files-to-prompts lib didn't allow me to hide certain sections ... but it turned out to be very handy and useful, so I refined it and it became this project.\n\n\n---\n\n## Highlights\n\n* **Policy-driven slicing**: `full`, `sig`, `sig+doc`, `body:levels=k`, `hide` to omit sections, `file:no-imports` to omit imports\n* **Targets**:\n\n * by **qualname** (e.g. `pkg.mod:Class.method` or `pkg.mod:*`),\n * by **path glob** (e.g. `**/repo/pkg/**/*.py`),\n * or via a **global default**.\n* **Multiple engines**:\n\n * Python (`.py`): granular per function/method/class.\n * Markdown (`.md`): per heading or whole document (supports `full`/`hide`).\n * YAML will soon be added\n * A description or short extract of heavy files, ML artifacts, etc., is also to be expected\n\n---\n\n## Installation\n\n**Prerequisites:** Python \u2265 3.9\n\n```bash\npip install pytoma\n```\n\nIf you can't directly call pip : \n\n```bash\npython -m pip install pytoma\n```\n\nOf course, if your pip alias is pip3, replace pip by pip3 in the command (and if your python alias is python3, replace python by python3 ...)\n\nYou can verify your installation with\n\n```bash\npytoma --version\npytoma --help\n```\n\nDuring installation, if `pip` prints a **warning** like:\n\n```\nThe script 'pytoma' is installed in '\u2026' which is not on PATH\n```\n\nThen you must permanently add **that folder** to your `PATH` (in your .bashrc or .zshrc), and then reopen the terminal.\n\n\nAs a fallback, you may also install from source :\n\n```bash\ngit clone https://github.com/nathanap2/pytoma.git\ncd pytoma\npython -m pip install .\n```\n\n---\n\n## Quick Start (CLI)\n\n```bash\n# Basic: pack a repo with defaults (same behaviour as files-to-prompt)\npytoma ./path/to/repo > PACK.txt\n\n# Now we use a YAML config to customize the render (skip sections, etc.)\npytoma ./repo --config config.yml --out PACK.txt\n\n```\n\nThe pack looks like:\n\n````text\n### pkg/module.py\n\n```python\ndef foo(a: int, b: int) -> int:\n \"\"\"Adds two numbers.\"\"\"\n # \u2026 lines 12\u201337 body omitted (26 lines) \u2026\n```\n\n### docs/guide.md\n\n<!-- \u2026 lines 1\u2013120 document omitted (120 lines) \u2026 -->\n\n````\n\n\n---\n\n## Configuration (YAML)\n\n```yaml\n# config.yml\ndefault: full # fallback policy\n\n# optional: exclude patterns (relative to the provided roots)\nexcludes:\n - \".venv/**\"\n - \"**/__pycache__/**\"\n - \"dist/**\"\n - \"build/**\"\n - \"site-packages/**\"\n - \"**/*.pyi\"\n\nrules:\n # Apply a file-level filter first (removes top-level imports, keeps __future__)\n - match: \"/abs/path/to/repo/pkg/**/*.py\"\n mode: \"file:no-imports\"\n\n # Then apply function-level policy to the same files\n - match: \"/abs/path/to/repo/pkg/**/*.py\"\n mode: \"sig+doc\"\n\n # Hide an entire module (replaced by an omission marker)\n - match: \"/abs/path/to/repo/legacy/big_module.py\"\n mode: \"hide\"\n\n # Target all defs in a given module by qualname\n - match: \"pkg.special:*\"\n mode: \"body:levels=1\"\n\n # Markdown supports only \"full\" and \"hide\"\n - match: \"/abs/path/to/repo/README.md\"\n mode: \"hide\"\n````\n\nNote : when Pytoma walks each document\u2019s nodes, it decides a policy with this order: qualname rules > path rules > global default.\n\n---\n\n## Policies\n\n* `full` \u2014 leave the node as is.\n* `hide` \u2014 remove and insert an omission marker:\n\n * On a **module**: replaces the whole file content.\n * On a **class**: replaces the whole class block.\n * On a **function/method**: replaces the definition or its body depending on engine mode.\n* `sig` \u2014 one-line header (`def \u2026:`), body omitted with a marker.\n* `sig+doc` \u2014 header + docstring (or `\"\"\"\u2026\"\"\"` placeholder), body omitted.\n* `body:levels=k` \u2014 keep code with indentation \u2264 `base + 4*k`, collapse deeper blocks with markers.\n* `file:no-imports` \u2014 strip top-level `import`/`from \u2026 import \u2026` except `from __future__ import \u2026`.\n* `file:no-legacy-strings` \u2014 remove **top-level** triple-quoted strings that are\n **not** the module docstring. These are often used to \u201ccomment out\u201d legacy code blocks.\n* `file:no-path-defs` \u2014 remove or condense **top-level** path-setup assignments\n (RHS matching `os.path.*`, `pathlib.Path(...)`, `__file__`, or `Path(...)` when\n imported from `pathlib`). A compact marker summarizes a few removed variables.\n* `file:no-sys-path` \u2014 remove `sys.path` manipulations (`append`, `insert`, `extend`),\n direct assignments (`sys.path = ...`), and in-place updates (`sys.path += ...`).\n* `file:tidy` \u2014 **composite** cleaner that applies `file:no-imports`,\n `file:no-legacy-strings`, `file:no-path-defs`, and `file:no-sys-path`\n in one pass. Recommended when you want several file-level cleaners on the\n same file, since only one `file:*` rule is applied per file rule.\n\n\nMarkers are comment-style lines (or a light box) with line counts, e.g.:\n\n```python\n# \u2026 lines 42\u201397 body omitted (56 lines) \u2026\n```\n\n\n---\n\n## Applying a policy to a whole file or folder\n\n**Three options:**\n\n1. **Global default**\n\n```bash\npytoma /abs/repo --default \"sig+doc\"\n```\n\n2. **Path glob rule** (absolute POSIX)\n\n```yaml\nrules:\n - match: \"/abs/repo/pkg/**/*.py\"\n mode: \"sig+doc\"\n```\n\n3. **Qualname wildcard for a module**\n\n```yaml\nrules:\n - match: \"pkg.module:*\"\n mode: \"sig+doc\"\n```\n\n> For file-level effects like removing imports or hiding an entire file, use `file:no-imports` or `hide` on the path glob; these apply to the module root.\n\n---\n\n## Excludes\n\nBy default, Pytoma skips:\n\n```\n.venv/**, **/__pycache__/**, dist/**, build/**, site-packages/**, **/*.pyi\n```\n\nYou can override in `config.yml \u2192 excludes`.\n\n---\n\n## Pitfalls\n\n- **Rule order can still be tricky** when several rules are about the same file. I'm looking forward to improving that soon. For the moment, prefer being as explicit as possible, and for tricky setups, you can simply ask an LLM to draft the rules for you (from your repo tree and goals).\n- To name a markdown section in the config file, you still **need to give the slugified version** of the section\n- **Only one `file:*` action per rule target.** If you need to combine cleaners (imports + sys.path + path vars + legacy strings), prefer `file:tidy` instead of stacking multiple `file:*` rules on the same files.\n\n\n## Roadmap\n\n* Engine for **YAML / JSON** (keys/tables granularity), **CSV** (short preview like pandas does), etc.\n* Better summary of skipped lines (for instance, when skipping imports, in the examples of skipped imports, we should probably prioritize unexpected imports over classic ones such as sys, os ...)\n* Propose the automatic addition of inferred rules: in particular, functions that are only called by hidden functions should probably be hidden by default.\n* More markers + Let the user choose their markers, rule by rule, using the configuration\n* A \u201ccustom:alternative_version\u201d rule to simply replace a block with an alternative version of the block provided by the user.\n* Heuristics to suggest rules (and possibility to condition it by a section which we want to focus on) -> may actually become another independent tool ... \n* ... and even smarter module targeting via **dependency graphs , embeddings**, git edit correlations, etc.\n\n---\n\n## Current engines & support matrix\n\n| Engine / Mode | full | hide | sig | sig+doc | body\\:levels=k | file\\:no-imports |\n| ---------------- | :--: | :--: | :-: | :-----: | :------------: | :--------------: |\n| Python (`.py`) | \u2705 | \u2705 | \u2705 | \u2705 | \u2705 | \u2705 |\n| Markdown (`.md`) | \u2705 | \u2705 | \u2013 | \u2013 | \u2013 | \u2013 |\n\n---\n\n## How it works (short)\n\n* Each engine parses a file into a lightweight IR:\n\n * `Document` with a flat list of `Node`s (module, class, function, etc.).\n* A decision step maps nodes to `Action`s (`full`, `sig+doc`, \u2026) using the precedence above.\n* Engines render actions into concrete `Edit`s (byte spans + replacements).\n* Edits are **merged**.\n* The final pack concatenates per-file sections with language fences.\n\n---\n\n## Example: start from a **skeleton** and ask the LLM for a focused `config.yml`\n\nGoal: produce a **skeleton** of the repo (signatures/docstrings, no bodies), then wrap that snapshot in a prompt that asks the LLM to **choose a focus area** and return a minimal Pytoma `config.yml` that \u201cexpands\u201d that area.\n\nFirst **Generate the prompt from the skeleton**\n\n```bash\n# The \"skeleton\" preset renders a compact snapshot (e.g., signatures only).\n# The \"focus_to_config\" prompt asks the LLM to reply with a minimal Pytoma YAML.\npytoma . \\\n --config skeleton \\\n --prompt focus_to_config \\\n --prompt-arg 'focus_note=improve the collision engine' \\\n --out PROMPT_CFG.txt\n```\n\n`PROMPT_CFG.txt` contains a short brief + the snapshot.\n\nNow **Paste the prompt into your LLM** and retrieve a focused `config.yml` (expected shape).\nThen you can **Apply that YAML** to produce a pack \u201cexpanded\u201d around the chosen area.\n\n---\n\n## License\n\n[MIT](LICENCE)\n",
"bugtrack_url": null,
"license": "Copyright 2025 Nathan Palluau\n \n Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \u201cSoftware\u201d), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n \n The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n \n THE SOFTWARE IS PROVIDED \u201cAS IS\u201d, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n ",
"summary": "Render a repo into one LLM-ready text file",
"version": "0.1.0a6",
"project_urls": {
"Homepage": "https://github.com/nathanap2/pytoma"
},
"split_keywords": [
"llm",
" code-slicing",
" developer-tools",
" prompting",
" repo-pack"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "6168201e7792aa4f89a12149688afd1e8711c517aa2675368c183d7e47910d4b",
"md5": "67662f48f7fd8d6e0fbcec0cf8ccadbe",
"sha256": "f83f3bf364a74c7fbb0e93e2c9efd547fd096438e65d7a8322f3a217ffe3390c"
},
"downloads": -1,
"filename": "pytoma-0.1.0a6-py3-none-any.whl",
"has_sig": false,
"md5_digest": "67662f48f7fd8d6e0fbcec0cf8ccadbe",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.9",
"size": 49458,
"upload_time": "2025-08-19T16:45:37",
"upload_time_iso_8601": "2025-08-19T16:45:37.712381Z",
"url": "https://files.pythonhosted.org/packages/61/68/201e7792aa4f89a12149688afd1e8711c517aa2675368c183d7e47910d4b/pytoma-0.1.0a6-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "c91c8d07050ad182220f5f3cd2b5d1984f36148af250003f70ccfd1b065ce4d2",
"md5": "0bc1020377f738425112576ae25f9085",
"sha256": "1028a448be0e4532f006749c5b4b10010a7f842420d16ed62f8444a1babde5aa"
},
"downloads": -1,
"filename": "pytoma-0.1.0a6.tar.gz",
"has_sig": false,
"md5_digest": "0bc1020377f738425112576ae25f9085",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.9",
"size": 52214,
"upload_time": "2025-08-19T16:45:39",
"upload_time_iso_8601": "2025-08-19T16:45:39.946854Z",
"url": "https://files.pythonhosted.org/packages/c9/1c/8d07050ad182220f5f3cd2b5d1984f36148af250003f70ccfd1b065ce4d2/pytoma-0.1.0a6.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-08-19 16:45:39",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "nathanap2",
"github_project": "pytoma",
"travis_ci": false,
"coveralls": false,
"github_actions": false,
"lcname": "pytoma"
}