Skip to main content

Small Uncomplicated Plugin Extensible Reliable Shell in PYthon

Project description

logo

Small Uncomplicated Plugin Extensible Reliable Shell in PYthon

About

SUPERSPY is a implementation of a shell and programming language written completely in Python. It is meant as a replacement of the builtin cmd module which allows scripting and advanced flow control functions.

[SUPERSPY DEMO] >>> i = 4 + 3
[SUPERSPY DEMO] >>> spam 3
SPAM
SPAM
SPAM
[SUPERSPY DEMO] >>> while i {
[SUPERSPY DEMO] >>>     printnl i
[SUPERSPY DEMO] >>>     printnl " to go: "
[SUPERSPY DEMO] >>>     joke
[SUPERSPY DEMO] >>>     i = i - 1
[SUPERSPY DEMO] >>> }
7.0 to go: Wenn ist das Nunstück git und Slotermeyer? Ja! Beiherhund das Oder die Flipperwaldt gersput!
6.0 to go: Wenn ist das Nunstück git und Slotermeyer? Ja! Beiherhund das Oder die Flipperwaldt gersput!
5.0 to go: Wenn ist das Nunstück git und Slotermeyer? Ja! Beiherhund das Oder die Flipperwaldt gersput!
4.0 to go: Wenn ist das Nunstück git und Slotermeyer? Ja! Beiherhund das Oder die Flipperwaldt gersput!
3.0 to go: Wenn ist das Nunstück git und Slotermeyer? Ja! Beiherhund das Oder die Flipperwaldt gersput!
2.0 to go: Wenn ist das Nunstück git und Slotermeyer? Ja! Beiherhund das Oder die Flipperwaldt gersput!
1.0 to go: Wenn ist das Nunstück git und Slotermeyer? Ja! Beiherhund das Oder die Flipperwaldt gersput!

joke and spam here are funktions easily defined in Python code:

from superspy import ast, language

@language.register_function('joke', 0)
class Joke(ast.Function):
    funniest_joke_in_the_world = 'Wenn ist das Nunstück git und Slotermeyer?'\
        'Ja! Beiherhund das Oder die Flipperwaldt gersput!'
    def execute(self):
        print(self.funniest_joke_in_the_world)

@language.register_function('spam')
class Spam(ast.Function):
    def execute(self):
        for _ in range(int(self.argument.execute())):
            print('SPAM')

It also allows for the execution of entire scripts:

printnl "COMPUTE FACTORIAL OF: "
base = getnum
base_backup = base

factorial = 1
while base {
    factorial = factorial * base
    base = base - 1
}

printnl base_backup
printnl "! = "
print factorial

Getting started

Superspy is meant to, in true Python fashion, be very easy to use.

Prerequisites

Superspy was developed in Python 3.7. Older versions cannot be guaranteed to work.

If you get it working on an older version please let me know!

Installing

Setup manually from this repository or just type

pip3 install superspy

Basic usage

To understand how to run a script from file check out the file_factorial script and its corresponding factorial script, that also illustrates basic language functionality.

To learn how to run an interactive shell check out the shell_demo script, that is being exanded upon by the plugin_demo and its example implementation of a plugin.

Superspy Language

Superspy is primarily a shell language, however it uses braces. Commands can be separated by lines or semicolons. Superspy supports strings and numbers, which are always stored as float.

Variables can be used in a similar way to Python:

a = 5
b = 2 * a

Basic Arithmetic and Logic is also supported, in (mostly) the correct order of operations (see the Bugfixes section of the Roadmap:

b = 2 * a - 3 / 4
c = a == 9.25
d = a != 10

Basic IO is also supported:

my_num_from_input = getnum
my_str_from_input = getstr
printnl "Your inputed number was"
printnl my_num_from_input
printnl " and your string was "
print my_str_from_input

Here printnl means Print No Lline, since the normal print has a line break. Also dis prints the entire token tree and should be used for debugging.

However, one of the primary reasons for Superspy's existence is the Flow Control:

while base != 0 {
    factorial = factorial * base
    base = base - 1
}
if factorial == 120 {
    print "Your number was 5"
} else {
    print "Your number was not 5"
}

For further features, that are not mentioned in the (roadmap)[#Roadmap], like running scripts from a shell, please create an issue (or even a pull request)!

Python

The way a new Ast/Interpreter is created will get further simplified in the future.

Currently you have to create a Language object, because a custom language might be defined. Then a CodeSource object has to be defined to be created to feed that Ast lines. Those can for example come from a file, string, or shell. Finally an Ast object, that does all the parsing and interpreting has to be created and executed.

from superspy import ast, code_source, language

# Run file
lang = language.SuperSpyLanguage()
source = code_source.FileSource(f'path/to/my/script.spy')
my_ast = ast.Ast(source, lang)
exit_code = my_ast.complete_run()

# Run shell
lang = language.SuperSpyLanguage(['path/to/my/plugin/folder']) # Plugin folder can be left out
source = code_source.ShellSource()
my_ast = ast.Ast(source, lang)
my_ast.error_mode = ast.ErrorMode.PRINT
exit_code = my_ast.complete_run(run_after_each_line=True)

Advanced Usage

The complete_run method is an abstraction for something similar to this:

my_ast.build_token_list()
my_ast.guess_variables()
my_ast.build_token_tree()
my_ast.interpret()
exit_code: int = my_ast.get_exit_code()

It can obviously be executed manually in this order and then customized any way. Everything is open source and the source code is hopefully documented very clearly, so if there are any questions of how something is implemented by default you check out the source code.

To implement custom functions available inside the language specify a plugin search path with custom python files inside. Check out the plugin_demo example and its example implementation of a plugin.

from superspy import language

@language.register_function('my_function_name_inside_the_shell', number_of_arguments)
class MyFunction(ast.Function):
    def execute(self):
        # Run code

Rationale

This module was created because I wanted scripting functionality inside the cmd module, that was not there. I have also been toying around with creating my own programming language for a few years and never got around to it. But most of all I needed a distraction during the exams this year.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

superspy-0.3.14.tar.gz (90.0 kB view details)

Uploaded Source

Built Distribution

superspy-0.3.14-py3-none-any.whl (23.8 kB view details)

Uploaded Python 3

File details

Details for the file superspy-0.3.14.tar.gz.

File metadata

  • Download URL: superspy-0.3.14.tar.gz
  • Upload date:
  • Size: 90.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/1.11.0 pkginfo/1.4.2 requests/2.18.1 setuptools/40.0.0 requests-toolbelt/0.8.0 tqdm/4.19.5 CPython/2.7.15

File hashes

Hashes for superspy-0.3.14.tar.gz
Algorithm Hash digest
SHA256 906dbe3daa2d683823d4d6faba70b9bcbdaef0de64941b9b4e4589065f4ba38e
MD5 6097242b9fbaabe35147c3d1cb77dfaa
BLAKE2b-256 d62c6bc5113b02a28b7118cffef7c3659f9b1b0f5d7b8b66f2d40504617c7a36

See more details on using hashes here.

File details

Details for the file superspy-0.3.14-py3-none-any.whl.

File metadata

  • Download URL: superspy-0.3.14-py3-none-any.whl
  • Upload date:
  • Size: 23.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/1.11.0 pkginfo/1.4.2 requests/2.18.1 setuptools/40.0.0 requests-toolbelt/0.8.0 tqdm/4.19.5 CPython/2.7.15

File hashes

Hashes for superspy-0.3.14-py3-none-any.whl
Algorithm Hash digest
SHA256 6c1efe44d1d7e8f32df3793c4ccb0b307c077df57eb55d478bbffd94b1df10de
MD5 2c242cccc212fdf79d97614f5527d38a
BLAKE2b-256 d8875d22ed0d46c96570ef6b3a61b3b2af0ad85c2638bfd136c417bbe40ba13e

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page