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_classesglobal_vars
Features
- Safe execution without using Python's
execoreval - 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 executemax_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 availableallowed_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
execoreval - 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)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| tiny_python-0.2.2.tar.gz | 19.7 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| 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.