Skip to main content

tiny-python (pre-release)

WARNING: This library is still under development and needs to be thoroughly tested for security. Use at your own risk.

LLMs are very good at writing python code!

tiny-python allows you to take advantage of this without your web app getting hacked.

It is very simple: use tiny_exec(unsafe_llm_code) on code generated by an LLM, and a python-like language will be run instead of dangerously running real python.

Why?

  • More powerful structured outputs: OpenAI supports structured outputs, but you must define the schema rigorously beforehand, and it is really only designed to handle small numbers of classes. What if you are having the AI create a complicated nested and polymorphic structure like video game level? What if you want the AI to be able to use mathematical functions to lay out positions of where things are? What if you are trying to represent a graph structure with cycles instead of a tree structure?

Solution: Have the LLM generate python and evaluate it safely using tiny-python. You can control the number of iterations of execution the code is allowed.

Does tiny-python guarantee security?

No:

tiny-python allows you to pass your own functions and dataclasses into the execution environment! You must use this feature responsibly. If you want to see a toy example of insecure usage of tiny-python:

# BAD: Suppose we define an insecure dataclass
@dataclass
class MyInsecureClass:
  code: str
  def __post_init__(self):
    exec(self.code)  # exec is bad.

# BAD: Then we run on an LLM output
tiny_exec(llm_output, allowed_classes=[MyInsecureClass])

To use this library properly, you should avoid providing it access to dataclasses with insecure side effects, or that are used in an insecure way. Care must be taken when you pass any of the following extra arguments to the tiny_exec (see more docs on these below):

  • allowed_classes
  • global_vars

Features

  • Safe execution without using Python's exec or eval
  • Support for math operations, string operations, and dataclass instantiation
  • Control flow structures (if, for, while)
  • Configurable execution limits (iterations, recursion depth)

Installation

pip install tiny-python

Quick Start

from tiny_python import tiny_exec, tiny_eval_last
from dataclasses import dataclass
from typing import List, Optional

# Define dataclasses that model an organization
# Note: These can have circular references to each other
@dataclass
class Person:
    name: str
    role: str
    team: Optional['Team'] = None

@dataclass
class Team:
    name: str
    description: str
    leader: Optional[Person] = None
    members: List[Person] = None

    def __post_init__(self):
        if self.members is None:
            self.members = []

@dataclass
class Project:
    title: str
    team: Team
    budget: float
    priority: int

# Use tiny_exec to safely execute LLM-generated code that builds complex structures
code = """
# Create team members
alice = Person("Alice", "Engineer")
bob = Person("Bob", "Designer")
charlie = Person("Charlie", "Manager")

# Create a team with a leader
dev_team = Team("Development Team", "Builds awesome products", charlie)
dev_team.members = [alice, bob, charlie]

# Set team references (creating cycles)
alice.team = dev_team
bob.team = dev_team
charlie.team = dev_team

# Create a project for this team
project = Project("New Website", dev_team, 50000.0, 1)

# Calculate some metrics
team_size = len(dev_team.members)
budget_per_person = project.budget / team_size
high_priority = project.priority == 1

# Store results in a summary
summary = {
    "project_name": project.title,
    "team_leader": dev_team.leader.name,
    "team_size": team_size,
    "budget_per_person": budget_per_person,
    "is_high_priority": high_priority
}
"""

# Execute the code safely with the allowed dataclasses
result = tiny_exec(code, allowed_classes=[Person, Team, Project])

# Access the created objects and computed values from the returned locals
print(result["summary"])
# {'project_name': 'New Website', 'team_leader': 'Charlie', 'team_size': 3,
#  'budget_per_person': 16666.666666666668, 'is_high_priority': True}

print(f"Team leader: {result['dev_team'].leader.name}")  # Charlie
print(f"First team member's team: {result['alice'].team.name}")  # Development Team

# Or use tiny_eval_last to get just the last expression value
last_value = tiny_eval_last("2 + 3 * 4")
print(last_value)  # 14

You can imagine that the code given in the string above is generated by an LLM that was given a description of the team and its members and projects.

API

tiny_exec(code, **kwargs)

Execute tiny-python code safely and return the local variables.

Parameters:

  • code: String containing the code to execute
  • max_iterations: Maximum number of total operations allowed (default: 1000)
  • max_iterations_per_loop: Maximum iterations for any single loop (default: 100)
  • allowed_classes: List of classes that can be instantiated (must be dataclasses)
  • global_vars: Dictionary of global variables to make available
  • allowed_functions: List of functions that may be called

Returns a dictionary containing all local variables created during execution. The executor instance is stored in the returned dictionary under the key "__executor__", which provides access to executor.last_result for the value of the last expression.

Supported Operations

  • Arithmetic: +, -, *, /, //, %, **
  • Comparison: ==, !=, <, <=, >, >=, in, not in, is, is not
  • Boolean: and, or, not
  • Built-in functions: len, range, int, float, str, bool, list, dict, tuple, set, abs, min, max, sum, round, sorted, reversed, enumerate, zip, all, any, isinstance, type
  • String methods: upper, lower, strip, lstrip, rstrip, split, join, replace, startswith, endswith, find, rfind, format, capitalize, title, isdigit, isalpha, isalnum, isspace, and many more string methods
  • Control flow: if, elif, else, for, while, break, continue, return, pass
  • Variable assignment: =, +=, -=, *=, /=, //=, %=, **=
  • Tuple unpacking in assignments and for loops
  • Dataclass instantiation and attribute access (with allowed_classes)
  • Custom functions (with allowed_functions)
  • Dictionary and list indexing/slicing

Security

This package is designed to provide a safe execution environment by:

  • Using AST parsing instead of exec or eval
  • Whitelisting allowed operations
  • Limiting iteration
  • Restricting module imports and file operations
  • At this early stage, feel free to open an issue if you find a security vulnerability
  • The interpreter disallows access to dangerous python built-ins

License

MIT

Metadata

Release files for tiny-python 0.2.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for tiny-python 0.2.2
File Size Uploaded Provenance
tiny_python-0.2.2.tar.gz 19.7 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for tiny-python 0.2.2
File Interpreter ABI Platform
tiny_python-0.2.2-py3-none-any.whl Python 3 none any Details

Total release size: 32.5 kB

Release files / tiny_python-0.2.2.tar.gz

Download URL tiny_python-0.2.2.tar.gz
Size 19.7 kB
Tags Source
SHA-256 checksum
How to use checksums
c77d3ac2f1adb3fb187f3dbf23309b1fc4721fa54a5a5f439c48d94c74eb7a43
BLAKE2b-256 checksum
How to use checksums
cce0401ce310f930688fb5899d3d23c3bdcdf5b38a278878f9e0232d1133d575
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.11.13

Release files / tiny_python-0.2.2-py3-none-any.whl

Download URL tiny_python-0.2.2-py3-none-any.whl
Size 12.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
99b92b3d7fde3929278ce40547ed80aad12cddaa7706320ed546f910adf2e3d3
BLAKE2b-256 checksum
How to use checksums
f8bd406df787ce1a9da3a1172fa9fcbf28198c0f4b942b21f48b5e7c3205d127
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.11.13

Security for tiny-python 0.2.2

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Release history Release notifications | RSS feed

This release

0.2.2 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page