minijinja


Nameminijinja JSON
Version 2.0.1 PyPI version JSON
download
home_pageNone
SummaryAn experimental Python binding of the Rust MiniJinja template engine.
upload_time2024-04-28 19:00:14
maintainerNone
docs_urlNone
authorNone
requires_python>=3.8
licenseNone
keywords jinja template-engine
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            <div align="center">
  <img src="https://github.com/mitsuhiko/minijinja/raw/main/artwork/logo.png" alt="" width=320>
  <p><strong>MiniJinja for Python: a powerful template engine for Rust and Python</strong></p>

[![Build Status](https://github.com/mitsuhiko/minijinja/workflows/Tests/badge.svg?branch=main)](https://github.com/mitsuhiko/minijinja/actions?query=workflow%3ATests)
[![License](https://img.shields.io/github/license/mitsuhiko/minijinja)](https://github.com/mitsuhiko/minijinja/blob/main/LICENSE)
[![Crates.io](https://img.shields.io/crates/d/minijinja.svg)](https://crates.io/crates/minijinja)
[![rustc 1.61.0](https://img.shields.io/badge/rust-1.61%2B-orange.svg)](https://img.shields.io/badge/rust-1.61%2B-orange.svg)
[![Documentation](https://docs.rs/minijinja/badge.svg)](https://docs.rs/minijinja)

</div>

`minijinja-py` is an experimental binding of
[MiniJinja](https://github.com/mitsuhiko/minijinja) to Python.  It has somewhat
limited functionality compared to the Rust version.  These bindings use
[maturin](https://www.maturin.rs/) and [pyo3](https://pyo3.rs/).

You might want to use MiniJinja instead of Jinja2 when the full feature set
of Jinja2 is not required and you want to have the same rendering experience
of a data set between Rust and Python.

With these bindings MiniJinja can render some Python objects and values
that are passed to templates, but there are clear limitations with regards
to what can be done.

To install MiniJinja for Python you can fetch the package [from PyPI](https://pypi.org/project/minijinja/):

```
$ pip install minijinja
```

## Basic API

The basic API is hidden behind the `Environment` object.  It behaves almost entirely
like in `minijinja` with some Python specific changes.  For instance instead of
`env.set_debug(True)` you use `env.debug = True`.  Additionally instead of using
`add_template` or attaching a `source` you either pass a dictionary of templates
directly to the environment or a `loader` function.

```python
from minijinja import Environment

env = Environment(templates={
    "template_name": "Template source"
})
```

To render a template you can use the `render_template` method:

```python
result = env.render_template('template_name', var1="value 1", var2="value 2")
print(result)
```

## Purpose

MiniJinja attempts a reasonably high level of compatibility with Jinja2, but it
does not try to achieve this at all costs.  As a result you will notice that
quite a few templates will refuse to render with MiniJinja despite the fact that
they probably look quite innocent.  It is however possible to write templates
that render to the same results for both Jinja2 and MiniJinja.  This raises the
question why you might want to use MiniJinja.

The main benefit would be to achieve the exact same results in both Rust and Python.
Additionally MiniJinja has a stronger sandbox than Jinja2 and might perform ever so
slightly better in some situations.  However you should be aware that due to the
marshalling that needs to happen in either direction there is a certain amount of
loss of information.

## Dynamic Template Loading

MiniJinja's Python bindings inherit the underlying behavior of how MiniJinja loads
templates.  Templates are loaded on first use and then cached.  The templates are
loaded via a loader.  To trigger a reload you can call `env.reload()` or
alternatively set `env.reload_before_render` to `True`.

```python
def my_loader(name):
    segments = []
    for segment in name.split("/"):
        if "\\" in segment or segment in (".", ".."):
            return None
        segments.append(segment)
    try:
        with open(os.path.join(TEMPLATES, *segments)) as f:
            return f.read()
    except (IOError, OSError):
        pass

env = Environment(loader=my_loader)
env.reload_before_render = True
print(env.render_template("index.html"))
```

Alternatively templates can manually be loaded and unloaded with `env.add_template`
and `env.remove_template`.

## Auto Escaping

The default behavior is to use auto escaping file files ending in `.html`.  You can
customize this behavior by overriding the `auto_escape_callback`:

```python
env = Environment(auto_escape_callback=lambda x: x.endswith((".html", ".foo")))
```

MiniJinja uses [markupsafe](https://github.com/pallets/markupsafe) if it's available
on the Python side.  It will honor `__html__`.

## Finalizers

Instead of custom formatters like in MiniJinja, you can define a finalizer instead
which is similar to how it works in Jinja2.  It's passed a value (or optional also
the state as first argument when `pass_state` is used) and can return a new value.
If the special `NotImplemented` value is returned, the original value is rendered
without any modification:

```
from minijinja import Environment

def finalizer(value):
    if value is None:
	return ""
    return NotImplemented

env = Environment(finalizer=finalizer)
assert env.render_str("{{ none }}") == ""
```

## State Access

Functions passed to the environment such as filters or global functions can
optionally have the template state passed by using the `pass_state` parameter.
This is similar to `pass_context` in Jinja2.  It can be used to look at the
name of the template or to look up variables in the context.

```python
from minijinja import pass_state

@pass_state
def my_filter(state, value):
    return state.lookup("a_variable") + value

env.add_filter("add_a_variable", my_filter)
```

## Runtime Behavior

MiniJinja uses it's own runtime model which is not matching the Python runtime
model.  As a result there are gaps in behavior between the two but some
limited effort is made to bridge them.  For instance you will be able to call
some methods of types, but for instance builtins such as dicts and lists do not
expose their methods on the MiniJinja side in all cases.  A natively generated
MiniJinja map (such as with the `dict` global function) will not have an `.items()`
method, whereas a Python dict passed to MiniJinja will.

Here is what this means for some basic types:

* Python dictionaries and lists (as well as other objects that behave as sequences)
  appear in the MiniJinja side very similar to how they do in Python.
* Tuples on the MiniJinja side are represented as lists, but will appear again as
  tuples if passed back to Python.
* Python objects are represented in MiniJinja similarly to dicts, but they retain all
  their meaningful Python APIs.  This means they stringify via `__str__` and they
  allow the MiniJinja code to call their non-underscored methods.  Note that there is
  no extra security layer in use at the moment so take care of what you pass there.
* MiniJinja's python binding understand what `__html__` is when it exists on a string
  subclass.  This means that a `markupsafe.Markup` object will appear as safe string in
  MiniJinja.  This information can also flow back to Python again.
* Stringification of objects uses `__str__` which is why mixed Python and MiniJinja
  objects can be a bit confusing at times.
* Where in Jinja2 there is a difference between `foo["bar"]` and `foo.bar` which can
  be used to disambiugate properties and keys, in MiniJinja there is no such difference.
  However methods are disambiugated so `foo.items()` works and will correctly call
  the method in all cases.

## Sponsor

If you like the project and find it useful you can [become a
sponsor](https://github.com/sponsors/mitsuhiko).

## License and Links

- [Documentation](https://docs.rs/minijinja/)
- [Examples](https://github.com/mitsuhiko/minijinja/tree/main/examples)
- [Issue Tracker](https://github.com/mitsuhiko/minijinja/issues)
- [MiniJinja Playground](https://mitsuhiko.github.io/minijinja-playground/)
- License: [Apache-2.0](https://github.com/mitsuhiko/minijinja/blob/main/LICENSE)


            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "minijinja",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.8",
    "maintainer_email": "Armin Ronacher <armin.ronacher@active-4.com>",
    "keywords": "jinja, template-engine",
    "author": null,
    "author_email": "Armin Ronacher <armin.ronacher@active-4.com>",
    "download_url": "https://files.pythonhosted.org/packages/e8/31/400bb74af3eb0c9826d150ba2a929f81f3d923f023017e5dd43b4d357eda/minijinja-2.0.1.tar.gz",
    "platform": null,
    "description": "<div align=\"center\">\n  <img src=\"https://github.com/mitsuhiko/minijinja/raw/main/artwork/logo.png\" alt=\"\" width=320>\n  <p><strong>MiniJinja for Python: a powerful template engine for Rust and Python</strong></p>\n\n[![Build Status](https://github.com/mitsuhiko/minijinja/workflows/Tests/badge.svg?branch=main)](https://github.com/mitsuhiko/minijinja/actions?query=workflow%3ATests)\n[![License](https://img.shields.io/github/license/mitsuhiko/minijinja)](https://github.com/mitsuhiko/minijinja/blob/main/LICENSE)\n[![Crates.io](https://img.shields.io/crates/d/minijinja.svg)](https://crates.io/crates/minijinja)\n[![rustc 1.61.0](https://img.shields.io/badge/rust-1.61%2B-orange.svg)](https://img.shields.io/badge/rust-1.61%2B-orange.svg)\n[![Documentation](https://docs.rs/minijinja/badge.svg)](https://docs.rs/minijinja)\n\n</div>\n\n`minijinja-py` is an experimental binding of\n[MiniJinja](https://github.com/mitsuhiko/minijinja) to Python.  It has somewhat\nlimited functionality compared to the Rust version.  These bindings use\n[maturin](https://www.maturin.rs/) and [pyo3](https://pyo3.rs/).\n\nYou might want to use MiniJinja instead of Jinja2 when the full feature set\nof Jinja2 is not required and you want to have the same rendering experience\nof a data set between Rust and Python.\n\nWith these bindings MiniJinja can render some Python objects and values\nthat are passed to templates, but there are clear limitations with regards\nto what can be done.\n\nTo install MiniJinja for Python you can fetch the package [from PyPI](https://pypi.org/project/minijinja/):\n\n```\n$ pip install minijinja\n```\n\n## Basic API\n\nThe basic API is hidden behind the `Environment` object.  It behaves almost entirely\nlike in `minijinja` with some Python specific changes.  For instance instead of\n`env.set_debug(True)` you use `env.debug = True`.  Additionally instead of using\n`add_template` or attaching a `source` you either pass a dictionary of templates\ndirectly to the environment or a `loader` function.\n\n```python\nfrom minijinja import Environment\n\nenv = Environment(templates={\n    \"template_name\": \"Template source\"\n})\n```\n\nTo render a template you can use the `render_template` method:\n\n```python\nresult = env.render_template('template_name', var1=\"value 1\", var2=\"value 2\")\nprint(result)\n```\n\n## Purpose\n\nMiniJinja attempts a reasonably high level of compatibility with Jinja2, but it\ndoes not try to achieve this at all costs.  As a result you will notice that\nquite a few templates will refuse to render with MiniJinja despite the fact that\nthey probably look quite innocent.  It is however possible to write templates\nthat render to the same results for both Jinja2 and MiniJinja.  This raises the\nquestion why you might want to use MiniJinja.\n\nThe main benefit would be to achieve the exact same results in both Rust and Python.\nAdditionally MiniJinja has a stronger sandbox than Jinja2 and might perform ever so\nslightly better in some situations.  However you should be aware that due to the\nmarshalling that needs to happen in either direction there is a certain amount of\nloss of information.\n\n## Dynamic Template Loading\n\nMiniJinja's Python bindings inherit the underlying behavior of how MiniJinja loads\ntemplates.  Templates are loaded on first use and then cached.  The templates are\nloaded via a loader.  To trigger a reload you can call `env.reload()` or\nalternatively set `env.reload_before_render` to `True`.\n\n```python\ndef my_loader(name):\n    segments = []\n    for segment in name.split(\"/\"):\n        if \"\\\\\" in segment or segment in (\".\", \"..\"):\n            return None\n        segments.append(segment)\n    try:\n        with open(os.path.join(TEMPLATES, *segments)) as f:\n            return f.read()\n    except (IOError, OSError):\n        pass\n\nenv = Environment(loader=my_loader)\nenv.reload_before_render = True\nprint(env.render_template(\"index.html\"))\n```\n\nAlternatively templates can manually be loaded and unloaded with `env.add_template`\nand `env.remove_template`.\n\n## Auto Escaping\n\nThe default behavior is to use auto escaping file files ending in `.html`.  You can\ncustomize this behavior by overriding the `auto_escape_callback`:\n\n```python\nenv = Environment(auto_escape_callback=lambda x: x.endswith((\".html\", \".foo\")))\n```\n\nMiniJinja uses [markupsafe](https://github.com/pallets/markupsafe) if it's available\non the Python side.  It will honor `__html__`.\n\n## Finalizers\n\nInstead of custom formatters like in MiniJinja, you can define a finalizer instead\nwhich is similar to how it works in Jinja2.  It's passed a value (or optional also\nthe state as first argument when `pass_state` is used) and can return a new value.\nIf the special `NotImplemented` value is returned, the original value is rendered\nwithout any modification:\n\n```\nfrom minijinja import Environment\n\ndef finalizer(value):\n    if value is None:\n\treturn \"\"\n    return NotImplemented\n\nenv = Environment(finalizer=finalizer)\nassert env.render_str(\"{{ none }}\") == \"\"\n```\n\n## State Access\n\nFunctions passed to the environment such as filters or global functions can\noptionally have the template state passed by using the `pass_state` parameter.\nThis is similar to `pass_context` in Jinja2.  It can be used to look at the\nname of the template or to look up variables in the context.\n\n```python\nfrom minijinja import pass_state\n\n@pass_state\ndef my_filter(state, value):\n    return state.lookup(\"a_variable\") + value\n\nenv.add_filter(\"add_a_variable\", my_filter)\n```\n\n## Runtime Behavior\n\nMiniJinja uses it's own runtime model which is not matching the Python runtime\nmodel.  As a result there are gaps in behavior between the two but some\nlimited effort is made to bridge them.  For instance you will be able to call\nsome methods of types, but for instance builtins such as dicts and lists do not\nexpose their methods on the MiniJinja side in all cases.  A natively generated\nMiniJinja map (such as with the `dict` global function) will not have an `.items()`\nmethod, whereas a Python dict passed to MiniJinja will.\n\nHere is what this means for some basic types:\n\n* Python dictionaries and lists (as well as other objects that behave as sequences)\n  appear in the MiniJinja side very similar to how they do in Python.\n* Tuples on the MiniJinja side are represented as lists, but will appear again as\n  tuples if passed back to Python.\n* Python objects are represented in MiniJinja similarly to dicts, but they retain all\n  their meaningful Python APIs.  This means they stringify via `__str__` and they\n  allow the MiniJinja code to call their non-underscored methods.  Note that there is\n  no extra security layer in use at the moment so take care of what you pass there.\n* MiniJinja's python binding understand what `__html__` is when it exists on a string\n  subclass.  This means that a `markupsafe.Markup` object will appear as safe string in\n  MiniJinja.  This information can also flow back to Python again.\n* Stringification of objects uses `__str__` which is why mixed Python and MiniJinja\n  objects can be a bit confusing at times.\n* Where in Jinja2 there is a difference between `foo[\"bar\"]` and `foo.bar` which can\n  be used to disambiugate properties and keys, in MiniJinja there is no such difference.\n  However methods are disambiugated so `foo.items()` works and will correctly call\n  the method in all cases.\n\n## Sponsor\n\nIf you like the project and find it useful you can [become a\nsponsor](https://github.com/sponsors/mitsuhiko).\n\n## License and Links\n\n- [Documentation](https://docs.rs/minijinja/)\n- [Examples](https://github.com/mitsuhiko/minijinja/tree/main/examples)\n- [Issue Tracker](https://github.com/mitsuhiko/minijinja/issues)\n- [MiniJinja Playground](https://mitsuhiko.github.io/minijinja-playground/)\n- License: [Apache-2.0](https://github.com/mitsuhiko/minijinja/blob/main/LICENSE)\n\n",
    "bugtrack_url": null,
    "license": null,
    "summary": "An experimental Python binding of the Rust MiniJinja template engine.",
    "version": "2.0.1",
    "project_urls": {
        "Donate": "https://github.com/sponsors/mitsuhiko",
        "Issue Tracker": "https://github.com/mitsuhiko/minijinja/issues",
        "Repository": "https://github.com/mitsuhiko/minijinja"
    },
    "split_keywords": [
        "jinja",
        " template-engine"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "9fa7a02ddaa88dcc1e69459dfe6b1e3a528e3815958410bda627ee8a1f23a4c7",
                "md5": "616a7ea988474ab3e2d524901a7a9e70",
                "sha256": "063b291cb31f5c33eb77bb4cb457f67f14426ca1418232b8ae9f267155d330cc"
            },
            "downloads": -1,
            "filename": "minijinja-2.0.1-cp38-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl",
            "has_sig": false,
            "md5_digest": "616a7ea988474ab3e2d524901a7a9e70",
            "packagetype": "bdist_wheel",
            "python_version": "cp38",
            "requires_python": ">=3.8",
            "size": 1584703,
            "upload_time": "2024-04-28T18:59:55",
            "upload_time_iso_8601": "2024-04-28T18:59:55.690824Z",
            "url": "https://files.pythonhosted.org/packages/9f/a7/a02ddaa88dcc1e69459dfe6b1e3a528e3815958410bda627ee8a1f23a4c7/minijinja-2.0.1-cp38-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "c1cca7742bc5dc37f39320dbc44a09baa8509acc0f6494b69bad1b401fd5a44b",
                "md5": "c5393576ea506527d6f08071a28190d1",
                "sha256": "4a4e9d639dd89ce7fef86e82147082ab3c248a36950fa3fbe793685ba322c1b7"
            },
            "downloads": -1,
            "filename": "minijinja-2.0.1-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",
            "has_sig": false,
            "md5_digest": "c5393576ea506527d6f08071a28190d1",
            "packagetype": "bdist_wheel",
            "python_version": "cp38",
            "requires_python": ">=3.8",
            "size": 818790,
            "upload_time": "2024-04-28T18:59:59",
            "upload_time_iso_8601": "2024-04-28T18:59:59.357051Z",
            "url": "https://files.pythonhosted.org/packages/c1/cc/a7742bc5dc37f39320dbc44a09baa8509acc0f6494b69bad1b401fd5a44b/minijinja-2.0.1-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "f1a9ae5b90b3c8b5b7aea31a7bd9f951bded89cdd37406f0afec53921c47eb42",
                "md5": "d251e892c05832e7a42066a7db0dfffa",
                "sha256": "a20373af4ee5430356c196c7fe5f19e3261a4fa16c944542b4de7a2349bac7a6"
            },
            "downloads": -1,
            "filename": "minijinja-2.0.1-cp38-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl",
            "has_sig": false,
            "md5_digest": "d251e892c05832e7a42066a7db0dfffa",
            "packagetype": "bdist_wheel",
            "python_version": "cp38",
            "requires_python": ">=3.8",
            "size": 810565,
            "upload_time": "2024-04-28T19:00:02",
            "upload_time_iso_8601": "2024-04-28T19:00:02.015970Z",
            "url": "https://files.pythonhosted.org/packages/f1/a9/ae5b90b3c8b5b7aea31a7bd9f951bded89cdd37406f0afec53921c47eb42/minijinja-2.0.1-cp38-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "65e62fdf8f14bbe3e7a3ad4df74eabaeb7a504e677e15c94fb9d579639075c39",
                "md5": "b0b421184695554e4ed3e0bcfa6c89e0",
                "sha256": "ade637bf4826258811a785ccc4e5d41cd2bdf4ec317b1ed3daa4dbbdd020f37d"
            },
            "downloads": -1,
            "filename": "minijinja-2.0.1-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
            "has_sig": false,
            "md5_digest": "b0b421184695554e4ed3e0bcfa6c89e0",
            "packagetype": "bdist_wheel",
            "python_version": "cp38",
            "requires_python": ">=3.8",
            "size": 853218,
            "upload_time": "2024-04-28T19:00:04",
            "upload_time_iso_8601": "2024-04-28T19:00:04.442563Z",
            "url": "https://files.pythonhosted.org/packages/65/e6/2fdf8f14bbe3e7a3ad4df74eabaeb7a504e677e15c94fb9d579639075c39/minijinja-2.0.1-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "e8df089bfa6853d9eabd176d7c833e16cc205c7042a50e40e6f533cc70315712",
                "md5": "40ce65d00b43912363621b9e140a9c91",
                "sha256": "d5ec956d777e0fee8e214af48363334c04f098e986038a9e8cb92a0564f81943"
            },
            "downloads": -1,
            "filename": "minijinja-2.0.1-cp38-abi3-manylinux_2_5_i686.manylinux1_i686.whl",
            "has_sig": false,
            "md5_digest": "40ce65d00b43912363621b9e140a9c91",
            "packagetype": "bdist_wheel",
            "python_version": "cp38",
            "requires_python": ">=3.8",
            "size": 940430,
            "upload_time": "2024-04-28T19:00:08",
            "upload_time_iso_8601": "2024-04-28T19:00:08.145042Z",
            "url": "https://files.pythonhosted.org/packages/e8/df/089bfa6853d9eabd176d7c833e16cc205c7042a50e40e6f533cc70315712/minijinja-2.0.1-cp38-abi3-manylinux_2_5_i686.manylinux1_i686.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "d5fe0069092c24ea8b80e38bcc15bda8213a9b11868c42d5bfce5b95a1b47704",
                "md5": "6b95062adbf7ac5065113c01703b2548",
                "sha256": "039f4d1a1a73f90917cff1ed7c617eb56e2b2f91bbbdc551adaa448e1673e5c2"
            },
            "downloads": -1,
            "filename": "minijinja-2.0.1-cp38-abi3-win32.whl",
            "has_sig": false,
            "md5_digest": "6b95062adbf7ac5065113c01703b2548",
            "packagetype": "bdist_wheel",
            "python_version": "cp38",
            "requires_python": ">=3.8",
            "size": 726351,
            "upload_time": "2024-04-28T19:00:11",
            "upload_time_iso_8601": "2024-04-28T19:00:11.297635Z",
            "url": "https://files.pythonhosted.org/packages/d5/fe/0069092c24ea8b80e38bcc15bda8213a9b11868c42d5bfce5b95a1b47704/minijinja-2.0.1-cp38-abi3-win32.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "7892e8b678cd7551f53d810ac7302237f38868389a9258a285058c9afaba8d3e",
                "md5": "f69b10f5dabcbe1ba569ec84a0b19bc5",
                "sha256": "dca5d7689905dce340e36e47348b505c788daf297253b85a1aff506ea63ad1b8"
            },
            "downloads": -1,
            "filename": "minijinja-2.0.1-cp38-abi3-win_amd64.whl",
            "has_sig": false,
            "md5_digest": "f69b10f5dabcbe1ba569ec84a0b19bc5",
            "packagetype": "bdist_wheel",
            "python_version": "cp38",
            "requires_python": ">=3.8",
            "size": 752827,
            "upload_time": "2024-04-28T19:00:13",
            "upload_time_iso_8601": "2024-04-28T19:00:13.429940Z",
            "url": "https://files.pythonhosted.org/packages/78/92/e8b678cd7551f53d810ac7302237f38868389a9258a285058c9afaba8d3e/minijinja-2.0.1-cp38-abi3-win_amd64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "e831400bb74af3eb0c9826d150ba2a929f81f3d923f023017e5dd43b4d357eda",
                "md5": "0da9620c43d3aad17078828bd3b3e83d",
                "sha256": "e774beffebfb8a1ad17e638ef70917cf5e94593f79acb8a8fff7d983169f3a4e"
            },
            "downloads": -1,
            "filename": "minijinja-2.0.1.tar.gz",
            "has_sig": false,
            "md5_digest": "0da9620c43d3aad17078828bd3b3e83d",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.8",
            "size": 197842,
            "upload_time": "2024-04-28T19:00:14",
            "upload_time_iso_8601": "2024-04-28T19:00:14.973344Z",
            "url": "https://files.pythonhosted.org/packages/e8/31/400bb74af3eb0c9826d150ba2a929f81f3d923f023017e5dd43b4d357eda/minijinja-2.0.1.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2024-04-28 19:00:14",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "sponsors",
    "github_project": "mitsuhiko",
    "github_not_found": true,
    "lcname": "minijinja"
}
        
Elapsed time: 0.24180s