Last active
December 16, 2015 05:08
-
-
Save atdt/5382043 to your computer and use it in GitHub Desktop.
Scribunto REPL. Uses MediaWiki API to evaluates Lua code in remote MediaWiki context.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
# -*- coding: utf-8 -*- | |
""" | |
Scribunto REPL (interactive Lua interpreter) | |
-------------------------------------------- | |
Uses MediaWiki's API to evaluates Lua code in a remote MediaWiki context. Run | |
with no arguments to evaluate code against Module:Sandbox on MediaWiki.org. | |
Usage: | |
scrib [-h] [--module MODULE] [--file FILE] [--api API] | |
Optional arguments: | |
-h, --help show this help message and exit | |
--module MODULE Module to load (default: Module:Sandbox) | |
--file FILE Lua file containing updated module code | |
--api API Full URL to api.php (default: http://mediawiki.org/w/api.php) | |
Written by Ori Livneh <ori@wikimedia.org> | |
""" | |
import argparse | |
import code | |
import json | |
import urllib | |
import urllib2 | |
try: | |
import readline | |
except ImportError: | |
pass | |
red = lambda s: '\033[91m%s\033[0m' % s | |
yellow = lambda s: '\033[93m%s\033[0m' % s | |
class ScribuntoRepl(code.InteractiveConsole): | |
"""Interactive Scribunto REPL. | |
Evaluates Lua code in remote MediaWiki context.""" | |
params = { | |
'action': 'scribunto-console', | |
'format': 'json', | |
} | |
def __init__(self, module='Module:Sandbox', content=None, | |
api='http://www.mediawiki.org/w/api.php'): | |
code.InteractiveConsole.__init__(self) | |
self.api = api | |
# Canonicalize module name | |
if not module.startswith('Module:'): | |
module = 'Module:' + module | |
self.params['title'] = module | |
if content is not None: | |
self.params.update(content=content) | |
self.runsource('=', fatal=True) | |
self.params.pop('content') | |
def runsource(self, source, *args, **kwargs): | |
query = dict(self.params, question=source) | |
try: | |
req = urllib2.urlopen(self.api + '?' + urllib.urlencode(query)) | |
resp = json.load(req) | |
self.params['session'] = resp['session'] | |
except (IOError, KeyError, ValueError) as e: | |
raise IOError('Failed to retrieve or decode API response: %s' % e) | |
if resp.get('type') == 'normal': | |
output = resp.get('print', resp['return']) | |
self.write(output) | |
else: | |
msg = resp.get('message', 'Unknown error') | |
if kwargs.get('fatal', False): | |
raise SystemExit(msg) | |
self.write(red(msg) + '\n') | |
return False | |
if __name__ == '__main__': | |
parser = argparse.ArgumentParser( | |
description='An interactive Scribunto interpreter', | |
epilog=('By default, evaluates code with mediawiki.org/wiki/' | |
'Module:Sandbox as context.')) | |
parser.add_argument( | |
'--module', | |
default='Module:Sandbox', | |
help='Module to load (default: Module:Sandbox)' | |
) | |
parser.add_argument( | |
'--file', | |
type=argparse.FileType('r'), | |
help='Lua file containing updated module code' | |
) | |
parser.add_argument( | |
'--api', | |
default='http://www.mediawiki.org/w/api.php', | |
help='URL to api.php (default: http://mediawiki.org/w/api.php)' | |
) | |
args = parser.parse_args() | |
content = None | |
if args.file is not None: | |
content = args.file.read() | |
args.file.close() | |
print(yellow('Scribunto REPL') + '\n') | |
print('* The module exports are available as the variable "p", including unsaved modifications.') | |
print('* Precede a line with "=" to evaluate it as an expression, or use print().') | |
print('* Use mw.log() in module code to send messages to this console.') | |
repl = ScribuntoRepl(module=args.module, content=content, api=args.api) | |
repl.interact('') | |
# vim set ft=python et sw=4 sts=4: |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment