Viper is a simple, easy to understand language with easy integration capabilities.
python -m pip install viper-lang
The dev version can be installed via
python -m pip install -U git+https://github.com/IAmTomahawkx/viper-lang
And can be imported into your project
import viper
To use Viper in your application, make use of the two eval methods, viper.eval and viper.eval_file functions. These functions are asynchronous, and must be run using asyncio, whether that be through the await keyword, or something such as asyncio.run. The asyncio docs can be found here.
import viper
import asyncio
code = 'myvar = "hi"'
asyncio.run(viper.eval(code))
or
import asyncio
import viper
asyncio.run(viper.eval_file("myfile.vp"))
you can pass defaults to be injected into the namespace, as such
import asyncio
import viper
asyncio.run(viper.eval("say(myvar)", injected={"myvar": "blue"}))
for more control over the creation, you can create your own viper.Runtime instance
import asyncio
import viper
runtime = viper.Runtime("<input>", injected={"myvar": "blue"}, allow_unsafe_imports=False)
code = "say(myvar)"
asyncio.run(runtime.run(code))
You can use this to disable features like unsafe modules, such as the requests module, or the files module.
import asyncio
import viper
runtime = viper.Runtime("<input>", allow_unsafe_imports=False)
code = "import files"
asyncio.run(runtime.run(code))
The above will raise a ViperModuleError.
Variables are set and retrieved like in Python, variables can be marked as static by putting static in front of the variable name. Static variables cannot be changed by anything other than intervention in python code
myvar = "red" static mystaticvar = "blue" mystaticvar = "hello" <-- StaticError
functions are created either in python and passed to the namespace, or in viper. functions created in viper follow this syntax
func myfunc() { return }
quite similar to python, with a few key differences. you may put static ` in front of the `func keyword to mark the function as static, preventing it from being reassigned.
static func myfunc() { return }
arguments look like the following
func myfunc(argument1, argument2) { return }
an argument can be made optional by inserting a question mark (?) in front of the argument name, E.x.
func myfunc(argument1, ?optional_arg1) { return }
optional arguments that are not given will be passed as a none object (note that this is not the same as a python None)
functions are called the same as in python:
func myfunc() { return } myfunc()
the viper namespace is left quite empty by default. The following are included in the default namespace: - say(*args) - equivilant to print in python. - help(obj) - prints an objects help. - dir(obj) - lists all attributes an object has.
Types are included in the namespace: - string - integer - bool - dictionary - list
there is also true / false, which are the booleans.
static globalvar = "hi" func name(arg, ?arg1) { var = 1 if (var is 1) { var += 1 } elif (var is not 1) { var = "stuff" } else { var = none } } func main() { say("hi") name("hello") } main()
to make things easier, the viper.exts.discord module makes it easy to pass safe objects, with limited accessibility, to viper, making it easy to pass discord.py models (indirectly) to your users, without fear of leaking your token and/or other sensitive data. Simply pass a discord.py model to its respective exts.discord counterpart, and pass that to your viper namespace