Stone IDL Compiler
Stone is an interface description language (IDL) and a suite of tools for defining APIs and generating client/server code in various languages. It is primarily used by Dropbox for its API development. The current version is 3.3.9, and it maintains an active release cadence with frequent patch updates and occasional minor feature additions.
Warnings
- gotcha Stone is an IDL compiler for *generating* client/server code, not a client library for directly making API calls. Users define an API in '.stone' files, then use Stone (typically via its CLI) to generate language-specific code (e.g., Python, Swift, TypeScript) which is then used for API interaction.
- breaking Changes in route ordering logic and `ApiRoute` hashing/sorting (e.g., in v3.3.0 and v3.3.9) were introduced to provide stable, deterministic output from code generation. However, this might lead to changes in generated file content or order if your previous build processes implicitly relied on non-deterministic ordering, potentially affecting diffs in version control or build pipelines.
- deprecated The `distutils` module, which was deprecated in Python 3.10 and removed in 3.12, was replaced by `setuptools.distutils` in `stone` v3.3.7. If you have custom build scripts or integrations that directly accessed `stone`'s internal setup process and relied on `distutils` directly, this change might affect you.
Install
-
pip install stone
Imports
- parse_stone_grammar
from stone.frontend.stone_parser import parse_stone_grammar
- Api
from stone.ir import Api
- PythonResourceBackend
from stone.backends.python_rsrc import PythonResourceBackend
Quickstart
import os
from stone.frontend.stone_parser import parse_stone_grammar
from stone.ir import Api
# 1. Define a simple Stone spec content
stone_spec_content = """
namespace example
struct User {
id String
name String
}
route greet(name: String): User
"Greets a user."
"""
# Create a temporary .stone file for parsing
temp_stone_file = "temp_spec.stone"
with open(temp_stone_file, "w") as f:
f.write(stone_spec_content)
try:
# 2. Parse the Stone spec file(s)
# parse_stone_grammar expects a list of file paths
api = parse_stone_grammar([temp_stone_file])
# 3. Access the parsed Intermediate Representation (IR)
example_namespace = api.namespaces.get('example')
if example_namespace:
print("Parsed API Namespace:", example_namespace.name)
print("Parsed API Structs:", [s.name for s in example_namespace.data_types if s.is_struct])
print("Parsed API Routes:", [r.name for r in example_namespace.routes])
else:
print("Namespace 'example' not found in parsed API.")
# For full code generation, you would then instantiate a backend
# (e.g., PythonResourceBackend) with the 'api' object and call its 'generate' method.
except Exception as e:
print(f"Error during Stone processing: {e}")
finally:
# Clean up temporary file
if os.path.exists(temp_stone_file):
os.remove(temp_stone_file)