The supported subset¶
A script body is Python that Python never runs, so only the part of the language with a faithful Lua meaning is accepted.
Supported:
- Statements: assignment, including unpacking (
a, b = b, a) and annotated assignment (text: str = redis.get(key)), whose annotation tells the compiler the value's type; augmented assignment;if/elif/else;while;break;continue;return. - Errors:
trywith oneexcept(bare orException),elseandfinally;raise SomeError("message"), and a bareraiseinsideexcept;assert. - Loops:
for ... inover a table,range(),enumerate(), or a dict's.items(),.keys()and.values(), binding a name or a tuple of names. - Helper functions defined with
defat the top level of the body, andlambdawherever an expression can go. They can call each other and themselves, and be passed to a helper that calls them. - Expressions: comparisons, chained ones such as
0 < n <= limitincluded; arithmetic;inandnot in;and/or, anda if c else b, both as values; list and dict literals. - Subscripts: indices, dict keys of any type, negative literal indices on a name, and slices of lists and strings, with a step or without.
- Strings: f-strings with format specs;
%formatting;+and*on a string;str.join,upper,lower,strip,lstrip,rstrip,startswith,endswith,find,split,partitionandreplace;isdigit,isalpha,isalnumandisspace, which test ASCII as they do on bytes;encode()anddecode()in UTF-8, which leave the bytes as they are. - Builtins and methods:
len(),int(), which truncates toward zero,float(),str(),min(),max(),abs(),ord(),chr(),.append(),.insert(),.pop()anddict.get();isinstance()againststr,bytes,int,float,bool,dictandlist. - The
mathmodule:floor,ceil,sqrt,fabs,fmod,exp,log,log10andpow, imported either way. - Calls: into
redisandcjson, with*xsallowed as the last argument, andcjson.nullfor a JSON null. - Parameters:
list[Key]andlist[...], for a variable number of keys and arguments. - Module-level constants.
Everything else raises
UnsupportedSyntax when the module is imported,
with a caret under the line at fault:
math.log() with a base is not supported
File "/srv/app/limits.py", line 12
buckets = math.log(n, 2)
^
hint: Lua 5.1's math.log takes no base; divide by math.log(base) instead.
Failing at import, loudly, is deliberate. A body that looks like Python but is never run by Python is exactly where a quiet mistranslation would cost the most.
The gaps that a supported construct still carries — truthiness, 1-based indexing, block scope — are covered in Where Lua differs from Python.