fiasto-py


Namefiasto-py JSON
Version 0.1.4 PyPI version JSON
download
home_pageNone
SummaryPython bindings for fiasto - A language-agnostic modern Wilkinson's formula parser and lexer
upload_time2025-09-10 02:45:20
maintainerNone
docs_urlNone
authorNone
requires_python>=3.8
licenseMIT
keywords formula parser statistics mixed-effects wilkinson rust pyo3
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # fiasto-py

[![PyPI version](https://badge.fury.io/py/fiasto-py.svg)](https://badge.fury.io/py/fiasto-py)
[![Python versions](https://img.shields.io/pypi/pyversions/fiasto-py.svg)](https://pypi.org/project/fiasto-py/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

<h1 align="center">fiasto-py</h1>

<p align="center">
  <img src="img/mango_pixle2_py.png" alt="logo" width="240">
</p>

---

<p align="center">Pronouned like <strong>fiasco</strong>, but with a <strong>t</strong> instead of a <strong>c</strong></p>

---

<p align="center">(F)ormulas (I)n (AST) (O)ut</p>

Python bindings for [fiasto](https://github.com/alexhallam/fiasto) - A language-agnostic modern Wilkinson's formula parser and lexer.

## 🎯 Features

- **Parse Wilkinson's Formulas**: Convert formula strings into structured JSON metadata
- **Tokenize Formulas**: Break down formulas into individual tokens with detailed information
- **Python Dictionaries**: Returns native Python dictionaries for easy integration

## 🎯 Simple API

- `parse_formula()` - Takes a Wilkinson’s formula string and returns a Python dictionary
- `lex_formula()` - Tokenizes a formula string and returns a Python dictionary

## πŸš€ Quick Start

### Installation

**Install from PyPI** (recommended):
```bash
pip install fiasto-py
```

### Usage

#### Usage: Parse Formula

```python
import fiasto_py
from pprint import pprint
# Parse a formula into structured metadata
print("="*30)
print("Parse Formula")
print("="*30)
result = fiasto_py.parse_formula("y ~ x1 + x2 + (1|group)")
pprint(result, compact = True)
```

**Output:**

```bash
==============================
Parse Formula
==============================
{'all_generated_columns': ['y', 'x1', 'x2', 'group'],
 'columns': {'group': {'generated_columns': ['group'],
                       'id': 4,
                       'interactions': [],
                       'random_effects': [{'correlated': True,
                                           'grouping_variable': 'group',
                                           'has_intercept': True,
                                           'includes_interactions': [],
                                           'kind': 'grouping',
                                           'variables': []}],
                       'roles': ['GroupingVariable'],
                       'transformations': []},
             'x1': {'generated_columns': ['x1'],
                    'id': 2,
                    'interactions': [],
                    'random_effects': [],
                    'roles': ['FixedEffect'],
                    'transformations': []},
             'x2': {'generated_columns': ['x2'],
                    'id': 3,
                    'interactions': [],
                    'random_effects': [],
                    'roles': ['FixedEffect'],
                    'transformations': []},
             'y': {'generated_columns': ['y'],
                   'id': 1,
                   'interactions': [],
                   'random_effects': [],
                   'roles': ['Response'],
                   'transformations': []}},
 'formula': 'y ~ x1 + x2 + (1|group)',
 'metadata': {'family': None,
              'has_intercept': True,
              'has_uncorrelated_slopes_and_intercepts': False,
              'is_random_effects_model': True}}
```

#### Usage: Lex Formula

```python
import fiasto_py
from pprint import pprint
print("="*30)
print("Lex Formula")
print("="*30)
tokens = fiasto_py.lex_formula("y ~ x1 + x2 + (1|group)")
pprint(tokens, compact = True)
```

**Output:**

```bash
==============================
Lex Formula
==============================
[{'lexeme': 'y', 'token': 'ColumnName'},
 {'lexeme': '~', 'token': 'Tilde'},
 {'lexeme': 'x1', 'token': 'ColumnName'},
 {'lexeme': '+', 'token': 'Plus'},
 {'lexeme': 'x2', 'token': 'ColumnName'},
 {'lexeme': '+', 'token': 'Plus'},
 {'lexeme': '(', 'token': 'FunctionStart'},
 {'lexeme': '1', 'token': 'One'},
 {'lexeme': '|', 'token': 'Pipe'},
 {'lexeme': 'group', 'token': 'ColumnName'},
 {'lexeme': ')', 'token': 'FunctionEnd'}]
```

### Simple OLS Regression

```python
import fiasto_py
import polars as pl
import numpy as np
from pprint import pprint

# Load data
mtcars_path = "https://gist.githubusercontent.com/seankross/a412dfbd88b3db70b74b/raw/5f23f993cd87c283ce766e7ac6b329ee7cc2e1d1/mtcars.csv"
df = pl.read_csv(mtcars_path)

# Parse formula
formula = "mpg ~ wt + cyl"
result = fiasto_py.parse_formula(formula)

pprint(result)

# Find the response column(s)
response_cols = [
    col for col, details in result["columns"].items()
    if "Response" in details["roles"]
]

# Find non-response columns
preds = [
    col for col, details in result["columns"].items()
    if "Response" not in details["roles"]
]

# Has intercept
has_intercept = result["metadata"]["has_intercept"]

# Prepare data matrices
X = df.select(preds).to_numpy()
y = df.select(response_cols).to_numpy().ravel()

# Add intercept if metadata says so
if has_intercept:
    X_with_intercept = np.column_stack([np.ones(X.shape[0]), X])
else:
    X_with_intercept = X

# Solve normal equations: (X'X)^-1 X'y
XTX = X_with_intercept.T @ X_with_intercept
XTy = X_with_intercept.T @ y
coefficients = np.linalg.solve(XTX, XTy)

# Extract intercept and slopes
if has_intercept:
    intercept = coefficients[0]
    slopes = coefficients[1:]
else:
    intercept = 0.0
    slopes = coefficients

# Calculate R2
y_pred = X_with_intercept @ coefficients
ss_res = np.sum((y - y_pred) ** 2)
ss_tot = np.sum((y - np.mean(y)) ** 2)
r_squared = 1 - (ss_res / ss_tot)

# Prep Output
# Combine intercept and slopes into one dict
coef_dict = {"intercept": intercept} | dict(zip(preds, slopes))

# Create a tidy DataFrame
coef_df = pl.DataFrame(
    {
        "term": list(coef_dict.keys()),
        "estimate": list(coef_dict.values())
    }
)

# Print results
print(f"Formula: {formula}")
print(f"RΒ² Score: {r_squared:.3f}")
print(coef_df)
```

**Output:**

```json
{'all_generated_columns': ['mpg', 'intercept', 'wt', 'cyl'],
 'all_generated_columns_formula_order': {'1': 'mpg',
                                         '2': 'intercept',
                                         '3': 'wt',
                                         '4': 'cyl'},
 'columns': {'cyl': {'generated_columns': ['cyl'],
                     'id': 3,
                     'interactions': [],
                     'random_effects': [],
                     'roles': ['Identity'],
                     'transformations': []},
             'mpg': {'generated_columns': ['mpg'],
                     'id': 1,
                     'interactions': [],
                     'random_effects': [],
                     'roles': ['Response'],
                     'transformations': []},
             'wt': {'generated_columns': ['wt'],
                    'id': 2,
                    'interactions': [],
                    'random_effects': [],
                    'roles': ['Identity'],
                    'transformations': []}},
 'formula': 'mpg ~ wt + cyl',
 'metadata': {'family': None,
              'has_intercept': True,
              'has_uncorrelated_slopes_and_intercepts': False,
              'is_random_effects_model': False,
              'response_variable_count': 1}}
Formula: mpg ~ wt + cyl
RΒ² Score: 0.830
shape: (3, 2)
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ term      ┆ estimate  β”‚
β”‚ ---       ┆ ---       β”‚
β”‚ str       ┆ f64       β”‚
β•žβ•β•β•β•β•β•β•β•β•β•β•β•ͺ═══════════║
β”‚ intercept ┆ 39.686261 β”‚
β”‚ cyl       ┆ -1.507795 β”‚
β”‚ wt        ┆ -3.190972 β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
```


## πŸ“‹ Supported Formula Syntax

`fiasto` supports comprehensive Wilkinson's notation including:

- **Basic formulas**: `y ~ x1 + x2`
- **Interactions**: `y ~ x1 * x2`
- **Smooth terms**: `y ~ s(z)`
- **Random effects**: `y ~ x + (1|group)`
- **Complex random effects**: `y ~ x + (1+x|group)`

### Supported Formulas (Coming Soon)

- **Multivariate models**: `mvbind(y1, y2) ~ x + (1|g)`
- **Non-linear models**: `y ~ a1 - a2^x, a1 ~ 1, a2 ~ x + (x|g), nl = TRUE`

For the complete reference, see the [fiasto documentation](https://docs.rs/fiasto/latest/fiasto/).

## πŸ“¦ PyPI Package

The package is available on PyPI and can be installed with:

```bash
pip install fiasto-py
```

- **PyPI Page**: [pypi.org/project/fiasto-py](https://pypi.org/project/fiasto-py/)
- **Source Code**: [github.com/alexhallam/fiasto-py](https://github.com/alexhallam/fiasto-py)
- **Documentation**: This README and inline docstrings


## πŸ“š API Reference

### `parse_formula(formula: str) -> dict`

Parse a Wilkinson's formula string and return structured JSON metadata.

**Parameters:**
- `formula` (str): The formula string to parse

**Returns:**
- `dict`: Structured metadata describing the formula

**Raises:**
- `ValueError`: If the formula is invalid or parsing fails

### `lex_formula(formula: str) -> dict`

Tokenize a formula string and return JSON describing each token.

**Parameters:**
- `formula` (str): The formula string to tokenize

**Returns:**
- `dict`: Token information for each element in the formula

**Raises:**
- `ValueError`: If the formula is invalid or lexing fails

## 🀝 Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

## πŸ™ Acknowledgments

- [fiasto](https://github.com/alexhallam/fiasto) - The underlying Rust library
- [PyO3](https://pyo3.rs/) - Python-Rust bindings
- [maturin](https://maturin.rs/) - Build system for Python extensions
- [PyPI](https://pypi.org/) - Python Package Index for distribution

## πŸ“„ License

This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.


            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "fiasto-py",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.8",
    "maintainer_email": "Alex Hallam <alex@example.com>",
    "keywords": "formula, parser, statistics, mixed-effects, wilkinson, rust, pyo3",
    "author": null,
    "author_email": "Alex Hallam <alex@example.com>",
    "download_url": null,
    "platform": null,
    "description": "# fiasto-py\n\n[![PyPI version](https://badge.fury.io/py/fiasto-py.svg)](https://badge.fury.io/py/fiasto-py)\n[![Python versions](https://img.shields.io/pypi/pyversions/fiasto-py.svg)](https://pypi.org/project/fiasto-py/)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\n<h1 align=\"center\">fiasto-py</h1>\n\n<p align=\"center\">\n  <img src=\"img/mango_pixle2_py.png\" alt=\"logo\" width=\"240\">\n</p>\n\n---\n\n<p align=\"center\">Pronouned like <strong>fiasco</strong>, but with a <strong>t</strong> instead of a <strong>c</strong></p>\n\n---\n\n<p align=\"center\">(F)ormulas (I)n (AST) (O)ut</p>\n\nPython bindings for [fiasto](https://github.com/alexhallam/fiasto) - A language-agnostic modern Wilkinson's formula parser and lexer.\n\n## \ud83c\udfaf Features\n\n- **Parse Wilkinson's Formulas**: Convert formula strings into structured JSON metadata\n- **Tokenize Formulas**: Break down formulas into individual tokens with detailed information\n- **Python Dictionaries**: Returns native Python dictionaries for easy integration\n\n## \ud83c\udfaf Simple API\n\n- `parse_formula()` - Takes a Wilkinson\u2019s formula string and returns a Python dictionary\n- `lex_formula()` - Tokenizes a formula string and returns a Python dictionary\n\n## \ud83d\ude80 Quick Start\n\n### Installation\n\n**Install from PyPI** (recommended):\n```bash\npip install fiasto-py\n```\n\n### Usage\n\n#### Usage: Parse Formula\n\n```python\nimport fiasto_py\nfrom pprint import pprint\n# Parse a formula into structured metadata\nprint(\"=\"*30)\nprint(\"Parse Formula\")\nprint(\"=\"*30)\nresult = fiasto_py.parse_formula(\"y ~ x1 + x2 + (1|group)\")\npprint(result, compact = True)\n```\n\n**Output:**\n\n```bash\n==============================\nParse Formula\n==============================\n{'all_generated_columns': ['y', 'x1', 'x2', 'group'],\n 'columns': {'group': {'generated_columns': ['group'],\n                       'id': 4,\n                       'interactions': [],\n                       'random_effects': [{'correlated': True,\n                                           'grouping_variable': 'group',\n                                           'has_intercept': True,\n                                           'includes_interactions': [],\n                                           'kind': 'grouping',\n                                           'variables': []}],\n                       'roles': ['GroupingVariable'],\n                       'transformations': []},\n             'x1': {'generated_columns': ['x1'],\n                    'id': 2,\n                    'interactions': [],\n                    'random_effects': [],\n                    'roles': ['FixedEffect'],\n                    'transformations': []},\n             'x2': {'generated_columns': ['x2'],\n                    'id': 3,\n                    'interactions': [],\n                    'random_effects': [],\n                    'roles': ['FixedEffect'],\n                    'transformations': []},\n             'y': {'generated_columns': ['y'],\n                   'id': 1,\n                   'interactions': [],\n                   'random_effects': [],\n                   'roles': ['Response'],\n                   'transformations': []}},\n 'formula': 'y ~ x1 + x2 + (1|group)',\n 'metadata': {'family': None,\n              'has_intercept': True,\n              'has_uncorrelated_slopes_and_intercepts': False,\n              'is_random_effects_model': True}}\n```\n\n#### Usage: Lex Formula\n\n```python\nimport fiasto_py\nfrom pprint import pprint\nprint(\"=\"*30)\nprint(\"Lex Formula\")\nprint(\"=\"*30)\ntokens = fiasto_py.lex_formula(\"y ~ x1 + x2 + (1|group)\")\npprint(tokens, compact = True)\n```\n\n**Output:**\n\n```bash\n==============================\nLex Formula\n==============================\n[{'lexeme': 'y', 'token': 'ColumnName'},\n {'lexeme': '~', 'token': 'Tilde'},\n {'lexeme': 'x1', 'token': 'ColumnName'},\n {'lexeme': '+', 'token': 'Plus'},\n {'lexeme': 'x2', 'token': 'ColumnName'},\n {'lexeme': '+', 'token': 'Plus'},\n {'lexeme': '(', 'token': 'FunctionStart'},\n {'lexeme': '1', 'token': 'One'},\n {'lexeme': '|', 'token': 'Pipe'},\n {'lexeme': 'group', 'token': 'ColumnName'},\n {'lexeme': ')', 'token': 'FunctionEnd'}]\n```\n\n### Simple OLS Regression\n\n```python\nimport fiasto_py\nimport polars as pl\nimport numpy as np\nfrom pprint import pprint\n\n# Load data\nmtcars_path = \"https://gist.githubusercontent.com/seankross/a412dfbd88b3db70b74b/raw/5f23f993cd87c283ce766e7ac6b329ee7cc2e1d1/mtcars.csv\"\ndf = pl.read_csv(mtcars_path)\n\n# Parse formula\nformula = \"mpg ~ wt + cyl\"\nresult = fiasto_py.parse_formula(formula)\n\npprint(result)\n\n# Find the response column(s)\nresponse_cols = [\n    col for col, details in result[\"columns\"].items()\n    if \"Response\" in details[\"roles\"]\n]\n\n# Find non-response columns\npreds = [\n    col for col, details in result[\"columns\"].items()\n    if \"Response\" not in details[\"roles\"]\n]\n\n# Has intercept\nhas_intercept = result[\"metadata\"][\"has_intercept\"]\n\n# Prepare data matrices\nX = df.select(preds).to_numpy()\ny = df.select(response_cols).to_numpy().ravel()\n\n# Add intercept if metadata says so\nif has_intercept:\n    X_with_intercept = np.column_stack([np.ones(X.shape[0]), X])\nelse:\n    X_with_intercept = X\n\n# Solve normal equations: (X'X)^-1 X'y\nXTX = X_with_intercept.T @ X_with_intercept\nXTy = X_with_intercept.T @ y\ncoefficients = np.linalg.solve(XTX, XTy)\n\n# Extract intercept and slopes\nif has_intercept:\n    intercept = coefficients[0]\n    slopes = coefficients[1:]\nelse:\n    intercept = 0.0\n    slopes = coefficients\n\n# Calculate R2\ny_pred = X_with_intercept @ coefficients\nss_res = np.sum((y - y_pred) ** 2)\nss_tot = np.sum((y - np.mean(y)) ** 2)\nr_squared = 1 - (ss_res / ss_tot)\n\n# Prep Output\n# Combine intercept and slopes into one dict\ncoef_dict = {\"intercept\": intercept} | dict(zip(preds, slopes))\n\n# Create a tidy DataFrame\ncoef_df = pl.DataFrame(\n    {\n        \"term\": list(coef_dict.keys()),\n        \"estimate\": list(coef_dict.values())\n    }\n)\n\n# Print results\nprint(f\"Formula: {formula}\")\nprint(f\"R\u00b2 Score: {r_squared:.3f}\")\nprint(coef_df)\n```\n\n**Output:**\n\n```json\n{'all_generated_columns': ['mpg', 'intercept', 'wt', 'cyl'],\n 'all_generated_columns_formula_order': {'1': 'mpg',\n                                         '2': 'intercept',\n                                         '3': 'wt',\n                                         '4': 'cyl'},\n 'columns': {'cyl': {'generated_columns': ['cyl'],\n                     'id': 3,\n                     'interactions': [],\n                     'random_effects': [],\n                     'roles': ['Identity'],\n                     'transformations': []},\n             'mpg': {'generated_columns': ['mpg'],\n                     'id': 1,\n                     'interactions': [],\n                     'random_effects': [],\n                     'roles': ['Response'],\n                     'transformations': []},\n             'wt': {'generated_columns': ['wt'],\n                    'id': 2,\n                    'interactions': [],\n                    'random_effects': [],\n                    'roles': ['Identity'],\n                    'transformations': []}},\n 'formula': 'mpg ~ wt + cyl',\n 'metadata': {'family': None,\n              'has_intercept': True,\n              'has_uncorrelated_slopes_and_intercepts': False,\n              'is_random_effects_model': False,\n              'response_variable_count': 1}}\nFormula: mpg ~ wt + cyl\nR\u00b2 Score: 0.830\nshape: (3, 2)\n\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502 term      \u2506 estimate  \u2502\n\u2502 ---       \u2506 ---       \u2502\n\u2502 str       \u2506 f64       \u2502\n\u255e\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u256a\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2561\n\u2502 intercept \u2506 39.686261 \u2502\n\u2502 cyl       \u2506 -1.507795 \u2502\n\u2502 wt        \u2506 -3.190972 \u2502\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n```\n\n\n## \ud83d\udccb Supported Formula Syntax\n\n`fiasto` supports comprehensive Wilkinson's notation including:\n\n- **Basic formulas**: `y ~ x1 + x2`\n- **Interactions**: `y ~ x1 * x2`\n- **Smooth terms**: `y ~ s(z)`\n- **Random effects**: `y ~ x + (1|group)`\n- **Complex random effects**: `y ~ x + (1+x|group)`\n\n### Supported Formulas (Coming Soon)\n\n- **Multivariate models**: `mvbind(y1, y2) ~ x + (1|g)`\n- **Non-linear models**: `y ~ a1 - a2^x, a1 ~ 1, a2 ~ x + (x|g), nl = TRUE`\n\nFor the complete reference, see the [fiasto documentation](https://docs.rs/fiasto/latest/fiasto/).\n\n## \ud83d\udce6 PyPI Package\n\nThe package is available on PyPI and can be installed with:\n\n```bash\npip install fiasto-py\n```\n\n- **PyPI Page**: [pypi.org/project/fiasto-py](https://pypi.org/project/fiasto-py/)\n- **Source Code**: [github.com/alexhallam/fiasto-py](https://github.com/alexhallam/fiasto-py)\n- **Documentation**: This README and inline docstrings\n\n\n## \ud83d\udcda API Reference\n\n### `parse_formula(formula: str) -> dict`\n\nParse a Wilkinson's formula string and return structured JSON metadata.\n\n**Parameters:**\n- `formula` (str): The formula string to parse\n\n**Returns:**\n- `dict`: Structured metadata describing the formula\n\n**Raises:**\n- `ValueError`: If the formula is invalid or parsing fails\n\n### `lex_formula(formula: str) -> dict`\n\nTokenize a formula string and return JSON describing each token.\n\n**Parameters:**\n- `formula` (str): The formula string to tokenize\n\n**Returns:**\n- `dict`: Token information for each element in the formula\n\n**Raises:**\n- `ValueError`: If the formula is invalid or lexing fails\n\n## \ud83e\udd1d Contributing\n\nContributions are welcome! Please feel free to submit a Pull Request.\n\n## \ud83d\ude4f Acknowledgments\n\n- [fiasto](https://github.com/alexhallam/fiasto) - The underlying Rust library\n- [PyO3](https://pyo3.rs/) - Python-Rust bindings\n- [maturin](https://maturin.rs/) - Build system for Python extensions\n- [PyPI](https://pypi.org/) - Python Package Index for distribution\n\n## \ud83d\udcc4 License\n\nThis project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.\n\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "Python bindings for fiasto - A language-agnostic modern Wilkinson's formula parser and lexer",
    "version": "0.1.4",
    "project_urls": {
        "Bug Tracker": "https://github.com/alexhallam/fiasto-py/issues",
        "Changelog": "https://github.com/alexhallam/fiasto-py/blob/main/CHANGELOG.md",
        "Documentation": "https://github.com/alexhallam/fiasto-py#readme",
        "Homepage": "https://github.com/alexhallam/fiasto-py",
        "Repository": "https://github.com/alexhallam/fiasto-py"
    },
    "split_keywords": [
        "formula",
        " parser",
        " statistics",
        " mixed-effects",
        " wilkinson",
        " rust",
        " pyo3"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "43c09b6240ffdda6b12b1bbad7038a846a9a7a822a7d7de597f3237aae0abd5f",
                "md5": "f0ca0e756770db5fc3dd96f69b0ef796",
                "sha256": "079ee52330e7b3fc6f0dc8903bf0ed43e2f09e0cc042469bee20c82e62e8b294"
            },
            "downloads": -1,
            "filename": "fiasto_py-0.1.4-cp313-cp313-macosx_11_0_arm64.whl",
            "has_sig": false,
            "md5_digest": "f0ca0e756770db5fc3dd96f69b0ef796",
            "packagetype": "bdist_wheel",
            "python_version": "cp313",
            "requires_python": ">=3.8",
            "size": 292069,
            "upload_time": "2025-09-10T02:45:20",
            "upload_time_iso_8601": "2025-09-10T02:45:20.433659Z",
            "url": "https://files.pythonhosted.org/packages/43/c0/9b6240ffdda6b12b1bbad7038a846a9a7a822a7d7de597f3237aae0abd5f/fiasto_py-0.1.4-cp313-cp313-macosx_11_0_arm64.whl",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-09-10 02:45:20",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "alexhallam",
    "github_project": "fiasto-py",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": false,
    "lcname": "fiasto-py"
}
        
Elapsed time: 1.53381s