convert spaces to tabs

This commit is contained in:
Izalia Mae 2023-01-08 23:05:32 -05:00
parent d1145c5995
commit d082438777
76 changed files with 2039 additions and 2039 deletions

View file

@ -1,6 +1,6 @@
class LuaException(Exception):
@property
def message(self):
if len(self.args) < 1:
return None
return self.args[0]
@property
def message(self):
if len(self.args) < 1:
return None
return self.args[0]

View file

@ -8,28 +8,28 @@ LuaNum = Union[int, float]
class LuaExpr:
def get_expr_code(self):
raise NotImplementedError
def get_expr_code(self):
raise NotImplementedError
_tmap = {
'\\': '\\\\',
'\a': '\\a',
'\b': '\\b',
'\f': '\\f',
'\n': '\\n',
'\r': '\\r',
'\t': '\\t',
'\v': '\\v',
'"': '\\"',
"'": "\\'",
'[': '\\[',
']': '\\]',
'\\': '\\\\',
'\a': '\\a',
'\b': '\\b',
'\f': '\\f',
'\n': '\\n',
'\r': '\\r',
'\t': '\\t',
'\v': '\\v',
'"': '\\"',
"'": "\\'",
'[': '\\[',
']': '\\]',
}
_tmap = {ord(c): r for c, r in _tmap.items()}
def lua_string(v):
if isinstance(v, bytes):
v = ser.decode(v)
return '"{}"'.format(v.translate(_tmap))
if isinstance(v, bytes):
v = ser.decode(v)
return '"{}"'.format(v.translate(_tmap))

View file

@ -3,136 +3,136 @@ from .errors import LuaException
def lua_table_to_list(x, length: int = None, low_index: int = 1):
if not x:
return [] if length is None else [None] * length
assert all(map(lambda k: isinstance(k, int), x.keys()))
assert min(x.keys()) >= low_index
dlen = max(x.keys()) - low_index + 1
if length is not None:
assert dlen <= length
else:
length = dlen
return [x.get(i + low_index) for i in range(length)]
if not x:
return [] if length is None else [None] * length
assert all(map(lambda k: isinstance(k, int), x.keys()))
assert min(x.keys()) >= low_index
dlen = max(x.keys()) - low_index + 1
if length is not None:
assert dlen <= length
else:
length = dlen
return [x.get(i + low_index) for i in range(length)]
class ResultProc:
def __init__(self, result):
self._v = result
self._i = 1
def __init__(self, result):
self._v = result
self._i = 1
def forward(self):
self._i += 1
def forward(self):
self._i += 1
def back(self):
self._i -= 1
def back(self):
self._i -= 1
def peek(self):
return self._v.get(self._i)
def peek(self):
return self._v.get(self._i)
def take(self):
r = self.peek()
self.forward()
return r
def take(self):
r = self.peek()
self.forward()
return r
def take_none(self):
x = self.take()
assert x is None
return x
def take_none(self):
x = self.take()
assert x is None
return x
def take_bool(self):
x = self.take()
assert x is True or x is False
return x
def take_bool(self):
x = self.take()
assert x is True or x is False
return x
def take_int(self):
x = self.take()
assert isinstance(x, int)
assert not isinstance(x, bool)
return x
def take_int(self):
x = self.take()
assert isinstance(x, int)
assert not isinstance(x, bool)
return x
def take_number(self):
x = self.take()
assert isinstance(x, (int, float))
assert not isinstance(x, bool)
return x
def take_number(self):
x = self.take()
assert isinstance(x, (int, float))
assert not isinstance(x, bool)
return x
def take_bytes(self):
x = self.take()
assert isinstance(x, bytes)
return x
def take_bytes(self):
x = self.take()
assert isinstance(x, bytes)
return x
def take_string(self):
return self.take_bytes().decode('latin1')
def take_string(self):
return self.take_bytes().decode('latin1')
def take_unicode(self):
return self.take_bytes().decode('utf-8')
def take_unicode(self):
return self.take_bytes().decode('utf-8')
def take_dict(self, keys=None):
x = self.take()
assert isinstance(x, dict)
if keys is None:
return x
return TableProc(x, keys)
def take_dict(self, keys=None):
x = self.take()
assert isinstance(x, dict)
if keys is None:
return x
return TableProc(x, keys)
def take_list(self, length: int = None):
return lua_table_to_list(self.take_dict(), length)
def take_list(self, length: int = None):
return lua_table_to_list(self.take_dict(), length)
def check_bool_error(self):
success = self.take_bool()
if not success:
raise LuaException(self.take_string())
def check_bool_error(self):
success = self.take_bool()
if not success:
raise LuaException(self.take_string())
def check_nil_error(self):
if self.peek() is None:
self.forward()
raise LuaException(self.take_string())
def check_nil_error(self):
if self.peek() is None:
self.forward()
raise LuaException(self.take_string())
def take_option_int(self):
if self.peek() is None:
return self.take_none()
return self.take_int()
def take_option_int(self):
if self.peek() is None:
return self.take_none()
return self.take_int()
def take_option_bytes(self):
if self.peek() is None:
return self.take_none()
return self.take_bytes()
def take_option_bytes(self):
if self.peek() is None:
return self.take_none()
return self.take_bytes()
def take_option_string(self):
if self.peek() is None:
return self.take_none()
return self.take_string()
def take_option_string(self):
if self.peek() is None:
return self.take_none()
return self.take_string()
def take_option_unicode(self):
if self.peek() is None:
return self.take_none()
return self.take_unicode()
def take_option_unicode(self):
if self.peek() is None:
return self.take_none()
return self.take_unicode()
def take_option_string_bool(self):
p = self.peek()
if p is None or p is True or p is False:
self.forward()
return p
return self.take_string()
def take_option_string_bool(self):
p = self.peek()
if p is None or p is True or p is False:
self.forward()
return p
return self.take_string()
def take_list_of_strings(self, length: int = None):
x = self.take_list(length)
assert all(map(lambda v: isinstance(v, bytes), x))
return [ser.decode(v) for v in x]
def take_list_of_strings(self, length: int = None):
x = self.take_list(length)
assert all(map(lambda v: isinstance(v, bytes), x))
return [ser.decode(v) for v in x]
def take_2d_int(self):
x = self.take_list()
x = [lua_table_to_list(item) for item in x]
for row in x:
for item in row:
assert isinstance(item, int)
return x
def take_2d_int(self):
x = self.take_list()
x = [lua_table_to_list(item) for item in x]
for row in x:
for item in row:
assert isinstance(item, int)
return x
class TableProc(ResultProc):
def __init__(self, result, keys):
self._v = result
self._keys = keys
self._i = 0
def __init__(self, result, keys):
self._v = result
self._keys = keys
self._i = 0
def peek(self):
return self._v.get(self._keys[self._i])
def peek(self):
return self._v.get(self._keys[self._i])

View file

@ -4,8 +4,8 @@ from . import lua
__all__ = (
'serialize',
'deserialize',
'serialize',
'deserialize',
)
@ -15,94 +15,94 @@ assert [bytes([i]) for i in range(256)] == [chr(i).encode(_ENC) for i in range(2
def encode(s: str) -> bytes:
return s.encode(_ENC)
return s.encode(_ENC)
def nil_encode(s):
if s is None:
return None
return encode(s)
if s is None:
return None
return encode(s)
def dirty_encode(s: str) -> bytes:
return s.encode(_ENC, errors='replace')
return s.encode(_ENC, errors='replace')
def decode(b):
return b.decode(_ENC)
return b.decode(_ENC)
def serialize(v: Any) -> bytes:
if v is None:
return b'N'
elif v is False:
return b'F'
elif v is True:
return b'T'
elif isinstance(v, (int, float)):
return '[{}]'.format(v).encode(_ENC)
elif isinstance(v, bytes):
return '<{}>'.format(len(v)).encode(_ENC) + v
elif isinstance(v, str):
raise ValueError('Strings are not allowed for serialization')
elif isinstance(v, (list, tuple)):
items = []
for k, x in enumerate(v, start=1):
items.append(b':' + serialize(k) + serialize(x))
return b'{' + b''.join(items) + b'}'
elif isinstance(v, dict):
items = []
for k, x in v.items():
items.append(b':' + serialize(k) + serialize(x))
return b'{' + b''.join(items) + b'}'
elif isinstance(v, lua.LuaExpr):
e = 'return ' + v.get_expr_code()
return 'E{}>'.format(len(e)).encode(_ENC) + e.encode(_ENC)
else:
raise ValueError('Value can\'t be serialized: {}'.format(repr(v)))
if v is None:
return b'N'
elif v is False:
return b'F'
elif v is True:
return b'T'
elif isinstance(v, (int, float)):
return '[{}]'.format(v).encode(_ENC)
elif isinstance(v, bytes):
return '<{}>'.format(len(v)).encode(_ENC) + v
elif isinstance(v, str):
raise ValueError('Strings are not allowed for serialization')
elif isinstance(v, (list, tuple)):
items = []
for k, x in enumerate(v, start=1):
items.append(b':' + serialize(k) + serialize(x))
return b'{' + b''.join(items) + b'}'
elif isinstance(v, dict):
items = []
for k, x in v.items():
items.append(b':' + serialize(k) + serialize(x))
return b'{' + b''.join(items) + b'}'
elif isinstance(v, lua.LuaExpr):
e = 'return ' + v.get_expr_code()
return 'E{}>'.format(len(e)).encode(_ENC) + e.encode(_ENC)
else:
raise ValueError('Value can\'t be serialized: {}'.format(repr(v)))
def _deserialize(b: bytes, _idx: int) -> Tuple[Any, int]:
tok = b[_idx]
_idx += 1
if tok == 78: # N
return None, _idx
elif tok == 70: # F
return False, _idx
elif tok == 84: # T
return True, _idx
elif tok == 91: # [
newidx = b.index(b']', _idx)
f = float(b[_idx:newidx])
if f.is_integer():
f = int(f)
return f, newidx + 1
elif tok == 60: # <
newidx = b.index(b'>', _idx)
ln = int(b[_idx:newidx])
return b[newidx + 1:newidx + 1 + ln], newidx + 1 + ln
elif tok == 123: # {
r = {}
while True:
tok = b[_idx]
_idx += 1
if tok == 125: # }
break
key, _idx = _deserialize(b, _idx)
value, _idx = _deserialize(b, _idx)
r[key] = value
return r, _idx
else:
raise ValueError
tok = b[_idx]
_idx += 1
if tok == 78: # N
return None, _idx
elif tok == 70: # F
return False, _idx
elif tok == 84: # T
return True, _idx
elif tok == 91: # [
newidx = b.index(b']', _idx)
f = float(b[_idx:newidx])
if f.is_integer():
f = int(f)
return f, newidx + 1
elif tok == 60: # <
newidx = b.index(b'>', _idx)
ln = int(b[_idx:newidx])
return b[newidx + 1:newidx + 1 + ln], newidx + 1 + ln
elif tok == 123: # {
r = {}
while True:
tok = b[_idx]
_idx += 1
if tok == 125: # }
break
key, _idx = _deserialize(b, _idx)
value, _idx = _deserialize(b, _idx)
r[key] = value
return r, _idx
else:
raise ValueError
def deserialize(b: bytes) -> Any:
return _deserialize(b, 0)[0]
return _deserialize(b, 0)[0]
def dcmditer(b: bytes):
yield b[0:1]
idx = 1
while idx < len(b):
chunk, idx = _deserialize(b, idx)
yield chunk
yield b[0:1]
idx = 1
while idx < len(b):
chunk, idx = _deserialize(b, idx)
yield chunk

View file

@ -18,111 +18,111 @@ DEBUG_PROTO = False
class CCApplication(web.Application):
@staticmethod
async def _bin_messages(ws):
async for msg in ws:
if msg.type != WSMsgType.BINARY:
continue
if DEBUG_PROTO:
sys.__stdout__.write('ws received ' + repr(msg.data) + '\n')
yield msg.data
@staticmethod
async def _bin_messages(ws):
async for msg in ws:
if msg.type != WSMsgType.BINARY:
continue
if DEBUG_PROTO:
sys.__stdout__.write('ws received ' + repr(msg.data) + '\n')
yield msg.data
@staticmethod
async def _send(ws, data):
if DEBUG_PROTO:
sys.__stdout__.write('ws send ' + repr(data) + '\n')
await ws.send_bytes(data)
@staticmethod
async def _send(ws, data):
if DEBUG_PROTO:
sys.__stdout__.write('ws send ' + repr(data) + '\n')
await ws.send_bytes(data)
async def _launch_program(self, ws):
async for msg in self._bin_messages(ws):
msg = ser.dcmditer(msg)
async def _launch_program(self, ws):
async for msg in self._bin_messages(ws):
msg = ser.dcmditer(msg)
action = next(msg)
if action != b'0':
await self._send(ws, PROTO_ERROR)
return None
action = next(msg)
if action != b'0':
await self._send(ws, PROTO_ERROR)
return None
version = next(msg)
if version != LUA_FILE_VERSION:
await self._send(ws, b'C' + ser.serialize(ser.encode(
'protocol version mismatch (expected {}, got {}), redownload py'.format(
LUA_FILE_VERSION, version,
))))
return None
version = next(msg)
if version != LUA_FILE_VERSION:
await self._send(ws, b'C' + ser.serialize(ser.encode(
'protocol version mismatch (expected {}, got {}), redownload py'.format(
LUA_FILE_VERSION, version,
))))
return None
computer_id = next(msg)
args = lua_table_to_list(next(msg), low_index=0)
computer_id = next(msg)
args = lua_table_to_list(next(msg), low_index=0)
def sender(data):
asyncio.create_task(self._send(ws, data))
def sender(data):
asyncio.create_task(self._send(ws, data))
sess = CCSession(computer_id, sender)
if len(args) >= 2:
sess.run_program(args[1], [ser.decode(x) for x in args[2:]])
else:
sess.run_repl()
return sess
sess = CCSession(computer_id, sender)
if len(args) >= 2:
sess.run_program(args[1], [ser.decode(x) for x in args[2:]])
else:
sess.run_repl()
return sess
async def ws(self, request):
ws = web.WebSocketResponse()
await ws.prepare(request)
async def ws(self, request):
ws = web.WebSocketResponse()
await ws.prepare(request)
sess = await self._launch_program(ws)
if sess is not None:
async for msg in self._bin_messages(ws):
msg = ser.dcmditer(msg)
action = next(msg)
if action == b'E':
sess.on_event(
next(msg),
lua_table_to_list(next(msg)),
)
elif action == b'T':
sess.on_task_result(
next(msg),
next(msg),
)
else:
await self._send(ws, PROTO_ERROR)
break
sess = await self._launch_program(ws)
if sess is not None:
async for msg in self._bin_messages(ws):
msg = ser.dcmditer(msg)
action = next(msg)
if action == b'E':
sess.on_event(
next(msg),
lua_table_to_list(next(msg)),
)
elif action == b'T':
sess.on_task_result(
next(msg),
next(msg),
)
else:
await self._send(ws, PROTO_ERROR)
break
return ws
return ws
@staticmethod
def backdoor(request):
with open(LUA_FILE, 'r') as f:
fcont = f.read()
h = request.host
if ':' not in h:
# fix for malformed Host header
h += ':{}'.format(request.app['port'])
fcont = fcont.replace(
"local url = 'http://127.0.0.1:4343/'",
"local url = '{}://{}/'".format('ws', h)
)
return web.Response(text=fcont)
@staticmethod
def backdoor(request):
with open(LUA_FILE, 'r') as f:
fcont = f.read()
h = request.host
if ':' not in h:
# fix for malformed Host header
h += ':{}'.format(request.app['port'])
fcont = fcont.replace(
"local url = 'http://127.0.0.1:4343/'",
"local url = '{}://{}/'".format('ws', h)
)
return web.Response(text=fcont)
def initialize(self):
self.router.add_get('/', self.backdoor)
self.router.add_get('/ws/', self.ws)
def initialize(self):
self.router.add_get('/', self.backdoor)
self.router.add_get('/ws/', self.ws)
def main():
parser = argparse.ArgumentParser()
parser.add_argument('--host')
parser.add_argument('--port', type=int, default=8080)
args = parser.parse_args()
parser = argparse.ArgumentParser()
parser.add_argument('--host')
parser.add_argument('--port', type=int, default=8080)
args = parser.parse_args()
app_kw = {}
if args.host is not None:
app_kw['host'] = args.host
app_kw['port'] = args.port
app_kw = {}
if args.host is not None:
app_kw['host'] = args.host
app_kw['port'] = args.port
app = CCApplication()
app['port'] = args.port
app.initialize()
web.run_app(app, **app_kw)
app = CCApplication()
app['port'] = args.port
app.initialize()
web.run_app(app, **app_kw)
if __name__ == '__main__':
main()
main()

View file

@ -20,114 +20,114 @@ from . import rproc, ser
__all__ = (
'CCSession',
'get_current_session',
'eval_lua',
'lua_context_object',
'CCSession',
'get_current_session',
'eval_lua',
'lua_context_object',
)
def debug(*args):
sys.__stdout__.write(' '.join(map(str, args)) + '\n')
sys.__stdout__.flush()
sys.__stdout__.write(' '.join(map(str, args)) + '\n')
sys.__stdout__.flush()
DIGITS = string.digits + string.ascii_lowercase
def base36(n):
r = ''
while n:
r += DIGITS[n % 36]
n //= 36
return ser.encode(r[::-1])
r = ''
while n:
r += DIGITS[n % 36]
n //= 36
return ser.encode(r[::-1])
def _is_global_greenlet():
return not hasattr(get_current_greenlet(), 'cc_greenlet')
return not hasattr(get_current_greenlet(), 'cc_greenlet')
def get_current_session():
try:
return get_current_greenlet().cc_greenlet._sess
except AttributeError:
raise RuntimeError('Computercraft function was called outside context')
try:
return get_current_greenlet().cc_greenlet._sess
except AttributeError:
raise RuntimeError('Computercraft function was called outside context')
class StdFileProxy:
def __init__(self, native, err):
self._native = native
self._err = err
def __init__(self, native, err):
self._native = native
self._err = err
def read(self, size=-1):
if _is_global_greenlet():
return self._native.read(size)
else:
raise RuntimeError(
"Computercraft environment doesn't support stdin read method")
def read(self, size=-1):
if _is_global_greenlet():
return self._native.read(size)
else:
raise RuntimeError(
"Computercraft environment doesn't support stdin read method")
def readline(self, size=-1):
if _is_global_greenlet():
return self._native.readline(size)
else:
if size is not None and size >= 0:
raise RuntimeError(
"Computercraft environment doesn't support "
"stdin readline method with parameter")
return eval_lua('return io.read()').take_string() + '\n'
def readline(self, size=-1):
if _is_global_greenlet():
return self._native.readline(size)
else:
if size is not None and size >= 0:
raise RuntimeError(
"Computercraft environment doesn't support "
"stdin readline method with parameter")
return eval_lua('return io.read()').take_string() + '\n'
def write(self, s):
if _is_global_greenlet():
return self._native.write(s)
else:
s = ser.dirty_encode(s)
if self._err:
return eval_lua('io.stderr:write(...)', s).take_none()
else:
return eval_lua('io.write(...)', s).take_none()
def write(self, s):
if _is_global_greenlet():
return self._native.write(s)
else:
s = ser.dirty_encode(s)
if self._err:
return eval_lua('io.stderr:write(...)', s).take_none()
else:
return eval_lua('io.write(...)', s).take_none()
def fileno(self):
if _is_global_greenlet():
return self._native.fileno()
else:
# preventing use of gnu readline here
# https://github.com/python/cpython/blob/master/Python/bltinmodule.c#L1970
raise AttributeError
def fileno(self):
if _is_global_greenlet():
return self._native.fileno()
else:
# preventing use of gnu readline here
# https://github.com/python/cpython/blob/master/Python/bltinmodule.c#L1970
raise AttributeError
def __getattr__(self, name):
return getattr(self._native, name)
def __getattr__(self, name):
return getattr(self._native, name)
class ComputerCraftFinder(MetaPathFinder):
@staticmethod
def find_spec(fullname, path, target=None):
if fullname == 'cc':
return ModuleSpec(fullname, ComputerCraftLoader, is_package=True)
if fullname.startswith('cc.'):
return ModuleSpec(fullname, ComputerCraftLoader, is_package=False)
@staticmethod
def find_spec(fullname, path, target=None):
if fullname == 'cc':
return ModuleSpec(fullname, ComputerCraftLoader, is_package=True)
if fullname.startswith('cc.'):
return ModuleSpec(fullname, ComputerCraftLoader, is_package=False)
class ComputerCraftLoader(Loader):
@staticmethod
def create_module(spec):
sn = spec.name.split('.', 1)
assert sn[0] == 'cc'
if len(sn) == 1:
sn.append('_pkg')
rawmod = import_module('.' + sn[1], 'computercraft.subapis')
mod = ModuleType(spec.name)
for k in rawmod.__all__:
setattr(mod, k, getattr(rawmod, k))
return mod
@staticmethod
def create_module(spec):
sn = spec.name.split('.', 1)
assert sn[0] == 'cc'
if len(sn) == 1:
sn.append('_pkg')
rawmod = import_module('.' + sn[1], 'computercraft.subapis')
mod = ModuleType(spec.name)
for k in rawmod.__all__:
setattr(mod, k, getattr(rawmod, k))
return mod
@staticmethod
def exec_module(module):
pass
@staticmethod
def exec_module(module):
pass
def install_import_hook():
import sys
sys.meta_path.append(ComputerCraftFinder)
import sys
sys.meta_path.append(ComputerCraftFinder)
install_import_hook()
@ -137,208 +137,208 @@ sys.stderr = StdFileProxy(sys.__stderr__, True)
def eval_lua(lua_code, *params, immediate=False):
if isinstance(lua_code, str):
lua_code = ser.encode(lua_code)
request = (
(b'I' if immediate else b'T')
+ ser.serialize(lua_code)
+ ser.serialize(params)
)
result = get_current_session()._server_greenlet.switch(request)
rp = rproc.ResultProc(ser.deserialize(result))
if not immediate:
rp.check_bool_error()
return rp
if isinstance(lua_code, str):
lua_code = ser.encode(lua_code)
request = (
(b'I' if immediate else b'T')
+ ser.serialize(lua_code)
+ ser.serialize(params)
)
result = get_current_session()._server_greenlet.switch(request)
rp = rproc.ResultProc(ser.deserialize(result))
if not immediate:
rp.check_bool_error()
return rp
@contextmanager
def lua_context_object(create_expr: str, create_params: tuple, finalizer_template: str = ''):
sess = get_current_session()
fid = sess.create_task_id()
var = 'temp[{}]'.format(lua_string(fid))
eval_lua('{} = {}'.format(var, create_expr), *create_params)
try:
yield var
finally:
finalizer_template += '; {e} = nil'
finalizer_template = finalizer_template.lstrip(' ;')
eval_lua(finalizer_template.format(e=var))
sess = get_current_session()
fid = sess.create_task_id()
var = 'temp[{}]'.format(lua_string(fid))
eval_lua('{} = {}'.format(var, create_expr), *create_params)
try:
yield var
finally:
finalizer_template += '; {e} = nil'
finalizer_template = finalizer_template.lstrip(' ;')
eval_lua(finalizer_template.format(e=var))
def eval_lua_method_factory(obj):
def method(name, *params):
code = 'return ' + obj + name + '(...)'
return eval_lua(code, *params)
return method
def method(name, *params):
code = 'return ' + obj + name + '(...)'
return eval_lua(code, *params)
return method
class CCGreenlet:
def __init__(self, body_fn, sess=None):
if sess is None:
self._sess = get_current_session()
else:
self._sess = sess
def __init__(self, body_fn, sess=None):
if sess is None:
self._sess = get_current_session()
else:
self._sess = sess
self._task_id = self._sess.create_task_id()
self._sess._greenlets[self._task_id] = self
self._task_id = self._sess.create_task_id()
self._sess._greenlets[self._task_id] = self
parent_g = get_current_greenlet()
if parent_g is self._sess._server_greenlet:
self._parent = None
else:
self._parent = parent_g.cc_greenlet
self._parent._children.add(self._task_id)
parent_g = get_current_greenlet()
if parent_g is self._sess._server_greenlet:
self._parent = None
else:
self._parent = parent_g.cc_greenlet
self._parent._children.add(self._task_id)
self._children = set()
self._g = greenlet(body_fn)
self._g.cc_greenlet = self
self._children = set()
self._g = greenlet(body_fn)
self._g.cc_greenlet = self
def detach_children(self):
if self._children:
ch = list(self._children)
self._children.clear()
self._sess.drop(ch)
def detach_children(self):
if self._children:
ch = list(self._children)
self._children.clear()
self._sess.drop(ch)
def _on_death(self, error=None):
self._sess._greenlets.pop(self._task_id, None)
self.detach_children()
if error is not None:
if error is True:
error = None
else:
error = ser.dirty_encode(error)
self._sess._sender(b'C' + ser.serialize(error))
if self._parent is not None:
self._parent._children.discard(self._task_id)
def _on_death(self, error=None):
self._sess._greenlets.pop(self._task_id, None)
self.detach_children()
if error is not None:
if error is True:
error = None
else:
error = ser.dirty_encode(error)
self._sess._sender(b'C' + ser.serialize(error))
if self._parent is not None:
self._parent._children.discard(self._task_id)
def defer_switch(self, *args, **kwargs):
asyncio.get_running_loop().call_soon(
partial(self.switch, *args, **kwargs))
def defer_switch(self, *args, **kwargs):
asyncio.get_running_loop().call_soon(
partial(self.switch, *args, **kwargs))
def switch(self, *args, **kwargs):
# switch must be called from server greenlet
assert get_current_greenlet() is self._sess._server_greenlet
try:
task = self._g.switch(*args, **kwargs)
except SystemExit:
self._on_death(True)
return
except Exception:
self._on_death(format_exc(limit=None, chain=False))
return
def switch(self, *args, **kwargs):
# switch must be called from server greenlet
assert get_current_greenlet() is self._sess._server_greenlet
try:
task = self._g.switch(*args, **kwargs)
except SystemExit:
self._on_death(True)
return
except Exception:
self._on_death(format_exc(limit=None, chain=False))
return
# lua_eval call or simply idle
if isinstance(task, bytes):
x = self
while x._g.dead:
x = x._parent
self._sess._sender(task[0:1] + ser.serialize(x._task_id) + task[1:])
# lua_eval call or simply idle
if isinstance(task, bytes):
x = self
while x._g.dead:
x = x._parent
self._sess._sender(task[0:1] + ser.serialize(x._task_id) + task[1:])
if self._g.dead:
if self._parent is None:
self._on_death(True)
else:
self._on_death()
if self._g.dead:
if self._parent is None:
self._on_death(True)
else:
self._on_death()
class CCEventRouter:
def __init__(self, on_first_sub, on_last_unsub, resume_task):
self._stacks = {}
self._active = {}
self._on_first_sub = on_first_sub
self._on_last_unsub = on_last_unsub
self._resume_task = resume_task
def __init__(self, on_first_sub, on_last_unsub, resume_task):
self._stacks = {}
self._active = {}
self._on_first_sub = on_first_sub
self._on_last_unsub = on_last_unsub
self._resume_task = resume_task
def sub(self, task_id, event):
if event not in self._stacks:
self._stacks[event] = {}
self._on_first_sub(event)
se = self._stacks[event]
if task_id in se:
raise Exception('Same task subscribes to the same event twice')
se[task_id] = deque()
def sub(self, task_id, event):
if event not in self._stacks:
self._stacks[event] = {}
self._on_first_sub(event)
se = self._stacks[event]
if task_id in se:
raise Exception('Same task subscribes to the same event twice')
se[task_id] = deque()
def unsub(self, task_id, event):
if event not in self._stacks:
return
self._stacks[event].pop(task_id, None)
if len(self._stacks[event]) == 0:
self._on_last_unsub(event)
del self._stacks[event]
def unsub(self, task_id, event):
if event not in self._stacks:
return
self._stacks[event].pop(task_id, None)
if len(self._stacks[event]) == 0:
self._on_last_unsub(event)
del self._stacks[event]
def on_event(self, event, params):
if event not in self._stacks:
self._on_last_unsub(event)
return
for task_id, queue in self._stacks[event].items():
queue.append(params)
if self._active.get(task_id) == event:
self._set_task_status(task_id, event, False)
self._resume_task(task_id)
def on_event(self, event, params):
if event not in self._stacks:
self._on_last_unsub(event)
return
for task_id, queue in self._stacks[event].items():
queue.append(params)
if self._active.get(task_id) == event:
self._set_task_status(task_id, event, False)
self._resume_task(task_id)
def get_from_stack(self, task_id, event):
queue = self._stacks[event][task_id]
try:
return queue.popleft()
except IndexError:
self._set_task_status(task_id, event, True)
return None
def get_from_stack(self, task_id, event):
queue = self._stacks[event][task_id]
try:
return queue.popleft()
except IndexError:
self._set_task_status(task_id, event, True)
return None
def _set_task_status(self, task_id, event, waits: bool):
if waits:
self._active[task_id] = event
else:
self._active.pop(task_id, None)
def _set_task_status(self, task_id, event, waits: bool):
if waits:
self._active[task_id] = event
else:
self._active.pop(task_id, None)
class CCSession:
def __init__(self, computer_id, sender):
# computer_id is unique identifier of a CCSession
self._computer_id = computer_id
self._tid_allocator = map(base36, count(start=1))
self._sender = sender
self._greenlets = {}
self._server_greenlet = get_current_greenlet()
self._program_greenlet = None
self._evr = CCEventRouter(
lambda event: self._sender(b'S' + ser.serialize(event)),
lambda event: self._sender(b'U' + ser.serialize(event)),
lambda task_id: self._greenlets[task_id].defer_switch('event'),
)
def __init__(self, computer_id, sender):
# computer_id is unique identifier of a CCSession
self._computer_id = computer_id
self._tid_allocator = map(base36, count(start=1))
self._sender = sender
self._greenlets = {}
self._server_greenlet = get_current_greenlet()
self._program_greenlet = None
self._evr = CCEventRouter(
lambda event: self._sender(b'S' + ser.serialize(event)),
lambda event: self._sender(b'U' + ser.serialize(event)),
lambda task_id: self._greenlets[task_id].defer_switch('event'),
)
def on_task_result(self, task_id, result):
assert get_current_greenlet() is self._server_greenlet
if task_id not in self._greenlets:
# ignore for dropped tasks
return
self._greenlets[task_id].switch(result)
def on_task_result(self, task_id, result):
assert get_current_greenlet() is self._server_greenlet
if task_id not in self._greenlets:
# ignore for dropped tasks
return
self._greenlets[task_id].switch(result)
def on_event(self, event, params):
self._evr.on_event(event, params)
def on_event(self, event, params):
self._evr.on_event(event, params)
def create_task_id(self):
return next(self._tid_allocator)
def create_task_id(self):
return next(self._tid_allocator)
def drop(self, task_ids):
def collect(task_id):
yield task_id
g = self._greenlets.pop(task_id)
for tid in g._children:
yield from collect(tid)
def drop(self, task_ids):
def collect(task_id):
yield task_id
g = self._greenlets.pop(task_id)
for tid in g._children:
yield from collect(tid)
all_tids = []
for task_id in task_ids:
all_tids.extend(collect(task_id))
all_tids = []
for task_id in task_ids:
all_tids.extend(collect(task_id))
self._sender(b'D' + b''.join(ser.serialize(tid) for tid in all_tids))
self._sender(b'D' + b''.join(ser.serialize(tid) for tid in all_tids))
def _run_sandboxed_greenlet(self, fn):
self._program_greenlet = CCGreenlet(fn, sess=self)
self._program_greenlet.switch()
def _run_sandboxed_greenlet(self, fn):
self._program_greenlet = CCGreenlet(fn, sess=self)
self._program_greenlet.switch()
def run_program(self, program, args):
def _run_program():
rp = eval_lua('''
def run_program(self, program, args):
def _run_program():
rp = eval_lua('''
local p = fs.combine(shell.dir(), ...)
if not fs.exists(p) then return nil end
if fs.isDir(p) then return nil end
@ -347,20 +347,20 @@ local code = f.readAll()
f.close()
return p, code
'''.lstrip(), program)
if rp.peek() is None:
print('Program not found', file=sys.stderr)
return
p = rp.take_string()
code = rp.take_string()
cc = compile(code, p, 'exec')
exec(cc, {'__file__': p, 'args': args})
if rp.peek() is None:
print('Program not found', file=sys.stderr)
return
p = rp.take_string()
code = rp.take_string()
cc = compile(code, p, 'exec')
exec(cc, {'__file__': p, 'args': args})
self._run_sandboxed_greenlet(_run_program)
self._run_sandboxed_greenlet(_run_program)
def run_repl(self):
def _repl():
InteractiveConsole(locals={}).interact(
banner='Python {}'.format(python_version()),
)
def run_repl(self):
def _repl():
InteractiveConsole(locals={}).interact(
banner='Python {}'.format(python_version()),
)
self._run_sandboxed_greenlet(_repl)
self._run_sandboxed_greenlet(_repl)

View file

@ -6,26 +6,26 @@ from ..sess import eval_lua
__all__ = (
'import_file',
'is_commands',
'is_multishell',
'is_turtle',
'is_pocket',
'eval_lua',
'LuaException',
'import_file',
'is_commands',
'is_multishell',
'is_turtle',
'is_pocket',
'eval_lua',
'LuaException',
)
def import_file(path: str, relative_to: str = None):
mod = ModuleType(path)
mod.__file__ = path
path_expr = lua_string(path)
if relative_to is not None:
path_expr = 'fs.combine(fs.getDir({}), {})'.format(
lua_string(relative_to),
path_expr,
)
source = eval_lua('''
mod = ModuleType(path)
mod.__file__ = path
path_expr = lua_string(path)
if relative_to is not None:
path_expr = 'fs.combine(fs.getDir({}), {})'.format(
lua_string(relative_to),
path_expr,
)
source = eval_lua('''
local p = {}
if not fs.exists(p) then return nil end
if fs.isDir(p) then return nil end
@ -34,26 +34,26 @@ local src = f.readAll()
f.close()
return src
'''.lstrip().format(
path_expr,
)).take_option_string()
if source is None:
raise ImportError('File not found: {}'.format(path))
cc = compile(source, mod.__name__, 'exec')
exec(cc, vars(mod))
return mod
path_expr,
)).take_option_string()
if source is None:
raise ImportError('File not found: {}'.format(path))
cc = compile(source, mod.__name__, 'exec')
exec(cc, vars(mod))
return mod
def is_commands() -> bool:
return eval_lua('return commands ~= nil').take_bool()
return eval_lua('return commands ~= nil').take_bool()
def is_multishell() -> bool:
return eval_lua('return multishell ~= nil').take_bool()
return eval_lua('return multishell ~= nil').take_bool()
def is_turtle() -> bool:
return eval_lua('return turtle ~= nil').take_bool()
return eval_lua('return turtle ~= nil').take_bool()
def is_pocket() -> bool:
return eval_lua('return pocket ~= nil').take_bool()
return eval_lua('return pocket ~= nil').take_bool()

View file

@ -3,12 +3,12 @@ from ..sess import eval_lua
class BaseSubAPI(LuaExpr):
def __init__(self, lua_expr):
self._lua_expr = lua_expr
def __init__(self, lua_expr):
self._lua_expr = lua_expr
def get_expr_code(self):
return self._lua_expr
def get_expr_code(self):
return self._lua_expr
def _method(self, name, *params):
code = 'return {}.{}(...)'.format(self.get_expr_code(), name)
return eval_lua(code, *params)
def _method(self, name, *params):
code = 'return {}.{}(...)'.format(self.get_expr_code(), name)
return eval_lua(code, *params)

View file

@ -7,29 +7,29 @@ method = eval_lua_method_factory('colors.')
__all__ = (
'white',
'orange',
'magenta',
'lightBlue',
'yellow',
'lime',
'pink',
'gray',
'lightGray',
'cyan',
'purple',
'blue',
'brown',
'green',
'red',
'black',
'combine',
'subtract',
'test',
'packRGB',
'unpackRGB',
'chars',
'iter_colors',
'white',
'orange',
'magenta',
'lightBlue',
'yellow',
'lime',
'pink',
'gray',
'lightGray',
'cyan',
'purple',
'blue',
'brown',
'green',
'red',
'black',
'combine',
'subtract',
'test',
'packRGB',
'unpackRGB',
'chars',
'iter_colors',
)
@ -54,47 +54,47 @@ black = 0x8000
# combine, subtract and test are mostly for redstone.setBundledOutput
def combine(*colors: int) -> int:
return method('combine', *colors).take_int()
return method('combine', *colors).take_int()
def subtract(color_set: int, *colors: int) -> int:
return method('subtract', color_set, *colors).take_int()
return method('subtract', color_set, *colors).take_int()
def test(colors: int, color: int) -> bool:
return method('test', colors, color).take_bool()
return method('test', colors, color).take_bool()
def packRGB(r: float, g: float, b: float) -> int:
return method('packRGB', r, g, b).take_int()
return method('packRGB', r, g, b).take_int()
def unpackRGB(rgb: int) -> Tuple[float, float, float]:
rp = method('unpackRGB', rgb)
return tuple(rp.take_number() for _ in range(3))
rp = method('unpackRGB', rgb)
return tuple(rp.take_number() for _ in range(3))
# use these chars for term.blit
chars = {
'0': white,
'1': orange,
'2': magenta,
'3': lightBlue,
'4': yellow,
'5': lime,
'6': pink,
'7': gray,
'8': lightGray,
'9': cyan,
'a': purple,
'b': blue,
'c': brown,
'd': green,
'e': red,
'f': black,
'0': white,
'1': orange,
'2': magenta,
'3': lightBlue,
'4': yellow,
'5': lime,
'6': pink,
'7': gray,
'8': lightGray,
'9': cyan,
'a': purple,
'b': blue,
'c': brown,
'd': green,
'e': red,
'f': black,
}
def iter_colors():
for c in chars.values():
yield c
for c in chars.values():
yield c

View file

@ -8,34 +8,34 @@ method = eval_lua_method_factory('commands.')
__all__ = (
'exec',
'list',
'getBlockPosition',
'getBlockInfo',
'getBlockInfos',
'exec',
'list',
'getBlockPosition',
'getBlockInfo',
'getBlockInfos',
)
def exec(command: str) -> Tuple[bool, List[str], Optional[int]]:
rp = method('exec', ser.encode(command))
success = rp.take_bool()
log = rp.take_list_of_strings()
n = rp.take_option_int()
return success, log, n
rp = method('exec', ser.encode(command))
success = rp.take_bool()
log = rp.take_list_of_strings()
n = rp.take_option_int()
return success, log, n
def list() -> List[str]:
return method('list').take_list_of_strings()
return method('list').take_list_of_strings()
def getBlockPosition() -> Tuple[int, int, int]:
rp = method('getBlockPosition')
return tuple(rp.take_int() for _ in range(3))
rp = method('getBlockPosition')
return tuple(rp.take_int() for _ in range(3))
def getBlockInfo(x: int, y: int, z: int) -> dict:
return method('getBlockInfo', x, y, z).take_dict()
return method('getBlockInfo', x, y, z).take_dict()
def getBlockInfos(x1: int, y1: int, z1: int, x2: int, y2: int, z2: int) -> List[dict]:
return method('getBlockInfos', x1, y1, z1, x2, y2, z2).take_list()
return method('getBlockInfos', x1, y1, z1, x2, y2, z2).take_list()

View file

@ -8,59 +8,59 @@ method = eval_lua_method_factory('disk.')
__all__ = (
'isPresent',
'hasData',
'getMountPath',
'setLabel',
'getLabel',
'getID',
'hasAudio',
'getAudioTitle',
'playAudio',
'stopAudio',
'eject',
'isPresent',
'hasData',
'getMountPath',
'setLabel',
'getLabel',
'getID',
'hasAudio',
'getAudioTitle',
'playAudio',
'stopAudio',
'eject',
)
def isPresent(side: str) -> bool:
return method('isPresent', ser.encode(side)).take_bool()
return method('isPresent', ser.encode(side)).take_bool()
def hasData(side: str) -> bool:
return method('hasData', ser.encode(side)).take_bool()
return method('hasData', ser.encode(side)).take_bool()
def getMountPath(side: str) -> Optional[str]:
return method('getMountPath', ser.encode(side)).take_option_string()
return method('getMountPath', ser.encode(side)).take_option_string()
def setLabel(side: str, label: Optional[str]):
return method('setLabel', ser.encode(side), ser.nil_encode(label)).take_none()
return method('setLabel', ser.encode(side), ser.nil_encode(label)).take_none()
def getLabel(side: str) -> Optional[str]:
return method('getLabel', ser.encode(side)).take_option_string()
return method('getLabel', ser.encode(side)).take_option_string()
def getID(side: str) -> Optional[int]:
return method('getID', ser.encode(side)).take_option_int()
return method('getID', ser.encode(side)).take_option_int()
def hasAudio(side: str) -> bool:
return method('hasAudio', ser.encode(side)).take_bool()
return method('hasAudio', ser.encode(side)).take_bool()
def getAudioTitle(side: str) -> Optional[Union[bool, str]]:
return method('getAudioTitle', ser.encode(side)).take_option_string_bool()
return method('getAudioTitle', ser.encode(side)).take_option_string_bool()
def playAudio(side: str):
return method('playAudio', ser.encode(side)).take_none()
return method('playAudio', ser.encode(side)).take_none()
def stopAudio(side: str):
return method('stopAudio', ser.encode(side)).take_none()
return method('stopAudio', ser.encode(side)).take_none()
def eject(side: str):
return method('eject', ser.encode(side)).take_none()
return method('eject', ser.encode(side)).take_none()

View file

@ -7,207 +7,207 @@ from ..sess import eval_lua_method_factory, lua_context_object
class SeekMixin:
def seek(self, whence: str = None, offset: int = None) -> int:
# whence: set, cur, end
rp = self._method('seek', ser.nil_encode(whence), offset)
rp.check_nil_error()
return rp.take_int()
def seek(self, whence: str = None, offset: int = None) -> int:
# whence: set, cur, end
rp = self._method('seek', ser.nil_encode(whence), offset)
rp.check_nil_error()
return rp.take_int()
class ReadMixin:
def _take(self, rp):
raise NotImplementedError
def _take(self, rp):
raise NotImplementedError
def read(self, count: int = 1) -> Optional[str]:
return self._take(self._method('read', count))
def read(self, count: int = 1) -> Optional[str]:
return self._take(self._method('read', count))
def readLine(self, withTrailing: bool = False) -> Optional[str]:
return self._take(self._method('readLine', withTrailing))
def readLine(self, withTrailing: bool = False) -> Optional[str]:
return self._take(self._method('readLine', withTrailing))
def readAll(self) -> Optional[str]:
return self._take(self._method('readAll'))
def readAll(self) -> Optional[str]:
return self._take(self._method('readAll'))
def __iter__(self):
return self
def __iter__(self):
return self
def __next__(self):
line = self.readLine()
if line is None:
raise StopIteration
return line
def __next__(self):
line = self.readLine()
if line is None:
raise StopIteration
return line
class WriteMixin:
def _put(self, t):
raise NotImplementedError
def _put(self, t):
raise NotImplementedError
def write(self, text: str):
return self._method('write', self._put(text)).take_none()
def write(self, text: str):
return self._method('write', self._put(text)).take_none()
def flush(self):
return self._method('flush').take_none()
def flush(self):
return self._method('flush').take_none()
class ReadHandle(ReadMixin, BaseSubAPI):
def _take(self, rp):
return rp.take_option_unicode()
def _take(self, rp):
return rp.take_option_unicode()
class BinaryReadHandle(ReadMixin, SeekMixin, BaseSubAPI):
def _take(self, rp):
return rp.take_option_bytes()
def _take(self, rp):
return rp.take_option_bytes()
class WriteHandle(WriteMixin, BaseSubAPI):
def _put(self, t: str) -> bytes:
return t.encode('utf-8')
def _put(self, t: str) -> bytes:
return t.encode('utf-8')
def writeLine(self, text: str):
return self.write(text + '\n')
def writeLine(self, text: str):
return self.write(text + '\n')
class BinaryWriteHandle(WriteMixin, SeekMixin, BaseSubAPI):
def _put(self, b: bytes) -> bytes:
return b
def _put(self, b: bytes) -> bytes:
return b
method = eval_lua_method_factory('fs.')
__all__ = (
'list',
'exists',
'isDir',
'isReadOnly',
'getDrive',
'getSize',
'getFreeSpace',
'getCapacity',
'makeDir',
'move',
'copy',
'delete',
'combine',
'open',
'find',
'getDir',
'getName',
'isDriveRoot',
'complete',
'attributes',
'list',
'exists',
'isDir',
'isReadOnly',
'getDrive',
'getSize',
'getFreeSpace',
'getCapacity',
'makeDir',
'move',
'copy',
'delete',
'combine',
'open',
'find',
'getDir',
'getName',
'isDriveRoot',
'complete',
'attributes',
)
def list(path: str) -> List[str]:
return method('list', ser.encode(path)).take_list_of_strings()
return method('list', ser.encode(path)).take_list_of_strings()
def exists(path: str) -> bool:
return method('exists', ser.encode(path)).take_bool()
return method('exists', ser.encode(path)).take_bool()
def isDir(path: str) -> bool:
return method('isDir', ser.encode(path)).take_bool()
return method('isDir', ser.encode(path)).take_bool()
def isReadOnly(path: str) -> bool:
return method('isReadOnly', ser.encode(path)).take_bool()
return method('isReadOnly', ser.encode(path)).take_bool()
def getDrive(path: str) -> Optional[str]:
return method('getDrive', ser.encode(path)).take_option_string()
return method('getDrive', ser.encode(path)).take_option_string()
def getSize(path: str) -> int:
return method('getSize', ser.encode(path)).take_int()
return method('getSize', ser.encode(path)).take_int()
def getFreeSpace(path: str) -> int:
return method('getFreeSpace', ser.encode(path)).take_int()
return method('getFreeSpace', ser.encode(path)).take_int()
def getCapacity(path: str) -> int:
return method('getCapacity', ser.encode(path)).take_int()
return method('getCapacity', ser.encode(path)).take_int()
def makeDir(path: str):
return method('makeDir', ser.encode(path)).take_none()
return method('makeDir', ser.encode(path)).take_none()
def move(fromPath: str, toPath: str):
return method('move', ser.encode(fromPath), ser.encode(toPath)).take_none()
return method('move', ser.encode(fromPath), ser.encode(toPath)).take_none()
def copy(fromPath: str, toPath: str):
return method('copy', ser.encode(fromPath), ser.encode(toPath)).take_none()
return method('copy', ser.encode(fromPath), ser.encode(toPath)).take_none()
def delete(path: str):
return method('delete', ser.encode(path)).take_none()
return method('delete', ser.encode(path)).take_none()
def combine(basePath: str, localPath: str) -> str:
return method('combine', ser.encode(basePath), ser.encode(localPath)).take_string()
return method('combine', ser.encode(basePath), ser.encode(localPath)).take_string()
@contextmanager
def open(path: str, mode: str):
'''
Usage:
'''
Usage:
with fs.open('filename', 'w') as f:
f.writeLine('textline')
with fs.open('filename', 'w') as f:
f.writeLine('textline')
with fs.open('filename', 'r') as f:
for line in f:
...
'''
with lua_context_object(
'fs.open(...)',
(ser.encode(path), ser.encode(mode.replace('b', '') + 'b')),
'{e}.close()',
) as var:
if 'b' in mode:
hcls = BinaryReadHandle if 'r' in mode else BinaryWriteHandle
else:
hcls = ReadHandle if 'r' in mode else WriteHandle
yield hcls(var)
with fs.open('filename', 'r') as f:
for line in f:
...
'''
with lua_context_object(
'fs.open(...)',
(ser.encode(path), ser.encode(mode.replace('b', '') + 'b')),
'{e}.close()',
) as var:
if 'b' in mode:
hcls = BinaryReadHandle if 'r' in mode else BinaryWriteHandle
else:
hcls = ReadHandle if 'r' in mode else WriteHandle
yield hcls(var)
def find(wildcard: str) -> List[str]:
return method('find', ser.encode(wildcard)).take_list_of_strings()
return method('find', ser.encode(wildcard)).take_list_of_strings()
def getDir(path: str) -> str:
return method('getDir', ser.encode(path)).take_string()
return method('getDir', ser.encode(path)).take_string()
def getName(path: str) -> str:
return method('getName', ser.encode(path)).take_string()
return method('getName', ser.encode(path)).take_string()
def isDriveRoot(path: str) -> bool:
return method('isDriveRoot', ser.encode(path)).take_bool()
return method('isDriveRoot', ser.encode(path)).take_bool()
def complete(
partialName: str, path: str, includeFiles: bool = None, includeDirs: bool = None,
partialName: str, path: str, includeFiles: bool = None, includeDirs: bool = None,
) -> List[str]:
return method(
'complete', ser.encode(partialName), ser.encode(path), includeFiles, includeDirs,
).take_list_of_strings()
return method(
'complete', ser.encode(partialName), ser.encode(path), includeFiles, includeDirs,
).take_list_of_strings()
def attributes(path: str) -> dict:
tp = method('attributes', ser.encode(path)).take_dict((
b'created',
b'modification',
b'isDir',
b'size',
))
r = {}
r['created'] = tp.take_int()
r['modification'] = tp.take_int()
r['isDir'] = tp.take_bool()
r['size'] = tp.take_int()
return r
tp = method('attributes', ser.encode(path)).take_dict((
b'created',
b'modification',
b'isDir',
b'size',
))
r = {}
r['created'] = tp.take_int()
r['modification'] = tp.take_int()
r['isDir'] = tp.take_bool()
r['size'] = tp.take_int()
return r

View file

@ -8,8 +8,8 @@ method = eval_lua_method_factory('gps.')
__all__ = (
'CHANNEL_GPS',
'locate',
'CHANNEL_GPS',
'locate',
)
@ -17,7 +17,7 @@ CHANNEL_GPS = 65534
def locate(timeout: LuaNum = None, debug: bool = None) -> Optional[Tuple[LuaNum, LuaNum, LuaNum]]:
rp = method('locate', timeout, debug)
if rp.peek() is None:
return None
return tuple(rp.take_number() for _ in range(3))
rp = method('locate', timeout, debug)
if rp.peek() is None:
return None
return tuple(rp.take_number() for _ in range(3))

View file

@ -8,29 +8,29 @@ method = eval_lua_method_factory('help.')
__all__ = (
'path',
'setPath',
'lookup',
'topics',
'completeTopic',
'path',
'setPath',
'lookup',
'topics',
'completeTopic',
)
def path() -> str:
return method('path').take_string()
return method('path').take_string()
def setPath(path: str):
return method('setPath', ser.encode(path)).take_none()
return method('setPath', ser.encode(path)).take_none()
def lookup(topic: str) -> Optional[str]:
return method('lookup', ser.encode(topic)).take_option_string()
return method('lookup', ser.encode(topic)).take_option_string()
def topics() -> List[str]:
return method('topics').take_list_of_strings()
return method('topics').take_list_of_strings()
def completeTopic(topicPrefix: str) -> List[str]:
return method('completeTopic', ser.encode(topicPrefix)).take_list_of_strings()
return method('completeTopic', ser.encode(topicPrefix)).take_list_of_strings()

View file

@ -8,21 +8,21 @@ method = eval_lua_method_factory('keys.')
__all__ = (
'getCode',
'getName',
'getCode',
'getName',
)
def getCode(name: str) -> Optional[int]:
# replaces properties
# keys.space → keys.getCode('space')
return eval_lua('''
# replaces properties
# keys.space → keys.getCode('space')
return eval_lua('''
local k = ...
if type(keys[k]) == 'number' then
return keys[k]
return keys[k]
end
return nil''', ser.encode(name)).take_option_int()
def getName(code: int) -> Optional[str]:
return method('getName', code).take_option_string()
return method('getName', code).take_option_string()

View file

@ -5,64 +5,64 @@ from ..lua import LuaExpr
class TermMixin:
def write(self, text: str):
return self._method('write', ser.dirty_encode(text)).take_none()
def write(self, text: str):
return self._method('write', ser.dirty_encode(text)).take_none()
def blit(self, text: str, textColors: bytes, backgroundColors: bytes):
return self._method('blit', ser.dirty_encode(text), textColors, backgroundColors).take_none()
def blit(self, text: str, textColors: bytes, backgroundColors: bytes):
return self._method('blit', ser.dirty_encode(text), textColors, backgroundColors).take_none()
def clear(self):
return self._method('clear').take_none()
def clear(self):
return self._method('clear').take_none()
def clearLine(self):
return self._method('clearLine').take_none()
def clearLine(self):
return self._method('clearLine').take_none()
def getCursorPos(self) -> Tuple[int, int]:
rp = self._method('getCursorPos')
return tuple(rp.take_int() for _ in range(2))
def getCursorPos(self) -> Tuple[int, int]:
rp = self._method('getCursorPos')
return tuple(rp.take_int() for _ in range(2))
def setCursorPos(self, x: int, y: int):
return self._method('setCursorPos', x, y).take_none()
def setCursorPos(self, x: int, y: int):
return self._method('setCursorPos', x, y).take_none()
def getCursorBlink(self) -> bool:
return self._method('getCursorBlink').take_bool()
def getCursorBlink(self) -> bool:
return self._method('getCursorBlink').take_bool()
def setCursorBlink(self, value: bool):
return self._method('setCursorBlink', value).take_none()
def setCursorBlink(self, value: bool):
return self._method('setCursorBlink', value).take_none()
def isColor(self) -> bool:
return self._method('isColor').take_bool()
def isColor(self) -> bool:
return self._method('isColor').take_bool()
def getSize(self) -> Tuple[int, int]:
rp = self._method('getSize')
return tuple(rp.take_int() for _ in range(2))
def getSize(self) -> Tuple[int, int]:
rp = self._method('getSize')
return tuple(rp.take_int() for _ in range(2))
def scroll(self, lines: int):
return self._method('scroll', lines).take_none()
def scroll(self, lines: int):
return self._method('scroll', lines).take_none()
def setTextColor(self, colorID: int):
return self._method('setTextColor', colorID).take_none()
def setTextColor(self, colorID: int):
return self._method('setTextColor', colorID).take_none()
def getTextColor(self) -> int:
return self._method('getTextColor').take_int()
def getTextColor(self) -> int:
return self._method('getTextColor').take_int()
def setBackgroundColor(self, colorID: int):
return self._method('setBackgroundColor', colorID).take_none()
def setBackgroundColor(self, colorID: int):
return self._method('setBackgroundColor', colorID).take_none()
def getBackgroundColor(self) -> int:
return self._method('getBackgroundColor').take_int()
def getBackgroundColor(self) -> int:
return self._method('getBackgroundColor').take_int()
def getPaletteColor(self, colorID: int) -> Tuple[float, float, float]:
rp = self._method('getPaletteColor', colorID)
return tuple(rp.take_number() for _ in range(3))
def getPaletteColor(self, colorID: int) -> Tuple[float, float, float]:
rp = self._method('getPaletteColor', colorID)
return tuple(rp.take_number() for _ in range(3))
def setPaletteColor(self, colorID: int, r: float, g: float, b: float):
return self._method('setPaletteColor', colorID, r, g, b).take_none()
def setPaletteColor(self, colorID: int, r: float, g: float, b: float):
return self._method('setPaletteColor', colorID, r, g, b).take_none()
class TermTarget(LuaExpr):
def __init__(self, code):
self._code = code
def __init__(self, code):
self._code = code
def get_expr_code(self):
return self._code
def get_expr_code(self):
return self._code

View file

@ -8,40 +8,40 @@ method = eval_lua_method_factory('multishell.')
__all__ = (
'getCurrent',
'getCount',
'launch',
'setTitle',
'getTitle',
'setFocus',
'getFocus',
'getCurrent',
'getCount',
'launch',
'setTitle',
'getTitle',
'setFocus',
'getFocus',
)
def getCurrent() -> int:
return method('getCurrent').take_int()
return method('getCurrent').take_int()
def getCount() -> int:
return method('getCount').take_int()
return method('getCount').take_int()
def launch(environment: dict, programPath: str, *args: str) -> int:
args = tuple(ser.encode(a) for a in args)
return method('launch', environment, ser.encode(programPath), *args).take_int()
args = tuple(ser.encode(a) for a in args)
return method('launch', environment, ser.encode(programPath), *args).take_int()
def setTitle(tabID: int, title: str):
return method('setTitle', tabID, ser.encode(title)).take_none()
return method('setTitle', tabID, ser.encode(title)).take_none()
def getTitle(tabID: int) -> Optional[str]:
return method('getTitle', tabID).take_option_string()
return method('getTitle', tabID).take_option_string()
def setFocus(tabID: int) -> bool:
return method('setFocus', tabID).take_bool()
return method('setFocus', tabID).take_bool()
def getFocus() -> int:
return method('getFocus').take_int()
return method('getFocus').take_int()

View file

@ -9,73 +9,73 @@ method = eval_lua_method_factory('os.')
__all__ = (
'version',
'getComputerID',
'getComputerLabel',
'setComputerLabel',
'run',
'captureEvent',
'queueEvent',
'clock',
'time',
'day',
'epoch',
'sleep',
'startTimer',
'cancelTimer',
'setAlarm',
'cancelAlarm',
'shutdown',
'reboot',
'version',
'getComputerID',
'getComputerLabel',
'setComputerLabel',
'run',
'captureEvent',
'queueEvent',
'clock',
'time',
'day',
'epoch',
'sleep',
'startTimer',
'cancelTimer',
'setAlarm',
'cancelAlarm',
'shutdown',
'reboot',
)
def version() -> str:
return method('version').take_string()
return method('version').take_string()
def getComputerID() -> int:
return method('getComputerID').take_int()
return method('getComputerID').take_int()
def getComputerLabel() -> Optional[str]:
return method('getComputerLabel').take_option_string()
return method('getComputerLabel').take_option_string()
def setComputerLabel(label: Optional[str]):
return method('setComputerLabel', ser.nil_encode(label)).take_none()
return method('setComputerLabel', ser.nil_encode(label)).take_none()
def run(environment: dict, programPath: str, *args: str):
args = tuple(ser.encode(a) for a in args)
return method('run', environment, ser.encode(programPath), *args).take_bool()
args = tuple(ser.encode(a) for a in args)
return method('run', environment, ser.encode(programPath), *args).take_bool()
def captureEvent(event: str):
event = ser.encode(event)
glet = get_current_greenlet().cc_greenlet
sess = glet._sess
evr = sess._evr
evr.sub(glet._task_id, event)
try:
while True:
val = evr.get_from_stack(glet._task_id, event)
if val is None:
res = sess._server_greenlet.switch()
assert res == 'event'
else:
yield val
finally:
evr.unsub(glet._task_id, event)
event = ser.encode(event)
glet = get_current_greenlet().cc_greenlet
sess = glet._sess
evr = sess._evr
evr.sub(glet._task_id, event)
try:
while True:
val = evr.get_from_stack(glet._task_id, event)
if val is None:
res = sess._server_greenlet.switch()
assert res == 'event'
else:
yield val
finally:
evr.unsub(glet._task_id, event)
def queueEvent(event: str, *params):
return method('queueEvent', ser.encode(event), *params).take_none()
return method('queueEvent', ser.encode(event), *params).take_none()
def clock() -> LuaNum:
# number of game ticks * 0.05, roughly seconds
return method('clock').take_number()
# number of game ticks * 0.05, roughly seconds
return method('clock').take_number()
# regarding ingame parameter below:
@ -83,43 +83,43 @@ def clock() -> LuaNum:
# we keep here only in-game time methods and parameters
def time() -> LuaNum:
# in hours 0..24
return method('time', b'ingame').take_number()
# in hours 0..24
return method('time', b'ingame').take_number()
def day() -> int:
return method('day', b'ingame').take_int()
return method('day', b'ingame').take_int()
def epoch() -> int:
return method('epoch', b'ingame').take_int()
return method('epoch', b'ingame').take_int()
def sleep(seconds: LuaNum):
return method('sleep', seconds).take_none()
return method('sleep', seconds).take_none()
def startTimer(timeout: LuaNum) -> int:
return method('startTimer', timeout).take_int()
return method('startTimer', timeout).take_int()
def cancelTimer(timerID: int):
return method('cancelTimer', timerID).take_none()
return method('cancelTimer', timerID).take_none()
def setAlarm(time: LuaNum) -> int:
# takes time of the day in hours 0..24
# returns integer alarmID
return method('setAlarm', time).take_int()
# takes time of the day in hours 0..24
# returns integer alarmID
return method('setAlarm', time).take_int()
def cancelAlarm(alarmID: int):
return method('cancelAlarm', alarmID).take_none()
return method('cancelAlarm', alarmID).take_none()
def shutdown():
return method('shutdown').take_none()
return method('shutdown').take_none()
def reboot():
return method('reboot').take_none()
return method('reboot').take_none()

View file

@ -8,39 +8,39 @@ method = eval_lua_method_factory('paintutils.')
__all__ = (
'parseImage',
'loadImage',
'drawPixel',
'drawLine',
'drawBox',
'drawFilledBox',
'drawImage',
'parseImage',
'loadImage',
'drawPixel',
'drawLine',
'drawBox',
'drawFilledBox',
'drawImage',
)
def parseImage(data: bytes) -> List[List[int]]:
return method('parseImage', data).take_2d_int()
return method('parseImage', data).take_2d_int()
def loadImage(path: str) -> List[List[int]]:
return method('loadImage', ser.encode(path)).take_2d_int()
return method('loadImage', ser.encode(path)).take_2d_int()
def drawPixel(x: int, y: int, color: int = None):
return method('drawPixel', x, y, color).take_none()
return method('drawPixel', x, y, color).take_none()
def drawLine(startX: int, startY: int, endX: int, endY: int, color: int = None):
return method('drawLine', startX, startY, endX, endY, color).take_none()
return method('drawLine', startX, startY, endX, endY, color).take_none()
def drawBox(startX: int, startY: int, endX: int, endY: int, color: int = None):
return method('drawBox', startX, startY, endX, endY, color).take_none()
return method('drawBox', startX, startY, endX, endY, color).take_none()
def drawFilledBox(startX: int, startY: int, endX: int, endY: int, color: int = None):
return method('drawFilledBox', startX, startY, endX, endY, color).take_none()
return method('drawFilledBox', startX, startY, endX, endY, color).take_none()
def drawImage(image: List[List[int]], xPos: int, yPos: int):
return method('drawImage', image, xPos, yPos).take_none()
return method('drawImage', image, xPos, yPos).take_none()

View file

@ -2,35 +2,35 @@ from ..sess import CCGreenlet, get_current_greenlet
__all__ = (
'waitForAny',
'waitForAll',
'waitForAny',
'waitForAll',
)
def waitForAny(*task_fns):
pgl = get_current_greenlet().cc_greenlet
sess = pgl._sess
pgl = get_current_greenlet().cc_greenlet
sess = pgl._sess
gs = [CCGreenlet(fn) for fn in task_fns]
for g in gs:
g.defer_switch()
gs = [CCGreenlet(fn) for fn in task_fns]
for g in gs:
g.defer_switch()
try:
sess._server_greenlet.switch()
finally:
pgl.detach_children()
try:
sess._server_greenlet.switch()
finally:
pgl.detach_children()
def waitForAll(*task_fns):
pgl = get_current_greenlet().cc_greenlet
sess = pgl._sess
pgl = get_current_greenlet().cc_greenlet
sess = pgl._sess
gs = [CCGreenlet(fn) for fn in task_fns]
for g in gs:
g.defer_switch()
gs = [CCGreenlet(fn) for fn in task_fns]
for g in gs:
g.defer_switch()
try:
for _ in range(len(task_fns)):
sess._server_greenlet.switch()
finally:
pgl.detach_children()
try:
for _ in range(len(task_fns)):
sess._server_greenlet.switch()
finally:
pgl.detach_children()

View file

@ -8,262 +8,262 @@ from ..sess import eval_lua, eval_lua_method_factory
class BasePeripheral:
# NOTE: is not LuaExpr, you can't pass peripheral as parameter
# TODO: to fix this we can supply separate lua expr, result of .wrap()
# NOTE: is not LuaExpr, you can't pass peripheral as parameter
# TODO: to fix this we can supply separate lua expr, result of .wrap()
def __init__(self, lua_method_expr, *prepend_params):
self._lua_method_expr = lua_method_expr
self._prepend_params = prepend_params
def __init__(self, lua_method_expr, *prepend_params):
self._lua_method_expr = lua_method_expr
self._prepend_params = prepend_params
def _method(self, name, *params):
code = 'return ' + self._lua_method_expr + '(...)'
return eval_lua(code, *self._prepend_params, ser.encode(name), *params)
def _method(self, name, *params):
code = 'return ' + self._lua_method_expr + '(...)'
return eval_lua(code, *self._prepend_params, ser.encode(name), *params)
class CCDrive(BasePeripheral):
def isDiskPresent(self) -> bool:
return self._method('isDiskPresent').take_bool()
def isDiskPresent(self) -> bool:
return self._method('isDiskPresent').take_bool()
def getDiskLabel(self) -> Optional[str]:
return self._method('getDiskLabel').take_option_string()
def getDiskLabel(self) -> Optional[str]:
return self._method('getDiskLabel').take_option_string()
def setDiskLabel(self, label: Optional[str]):
return self._method('setDiskLabel', ser.nil_encode(label)).take_none()
def setDiskLabel(self, label: Optional[str]):
return self._method('setDiskLabel', ser.nil_encode(label)).take_none()
def hasData(self) -> bool:
return self._method('hasData').take_bool()
def hasData(self) -> bool:
return self._method('hasData').take_bool()
def getMountPath(self) -> Optional[str]:
return self._method('getMountPath').take_option_string()
def getMountPath(self) -> Optional[str]:
return self._method('getMountPath').take_option_string()
def hasAudio(self) -> bool:
return self._method('hasAudio').take_bool()
def hasAudio(self) -> bool:
return self._method('hasAudio').take_bool()
def getAudioTitle(self) -> Optional[Union[bool, str]]:
return self._method('getAudioTitle').take_option_string_bool()
def getAudioTitle(self) -> Optional[Union[bool, str]]:
return self._method('getAudioTitle').take_option_string_bool()
def playAudio(self):
return self._method('playAudio').take_none()
def playAudio(self):
return self._method('playAudio').take_none()
def stopAudio(self):
return self._method('stopAudio').take_none()
def stopAudio(self):
return self._method('stopAudio').take_none()
def ejectDisk(self):
return self._method('ejectDisk').take_none()
def ejectDisk(self):
return self._method('ejectDisk').take_none()
def getDiskID(self) -> Optional[int]:
return self._method('getDiskID').take_option_int()
def getDiskID(self) -> Optional[int]:
return self._method('getDiskID').take_option_int()
class CCMonitor(BasePeripheral, TermMixin):
def getTextScale(self) -> int:
return self._method('getTextScale').take_int()
def getTextScale(self) -> int:
return self._method('getTextScale').take_int()
def setTextScale(self, scale: int):
return self._method('setTextScale', scale).take_none()
def setTextScale(self, scale: int):
return self._method('setTextScale', scale).take_none()
class ComputerMixin:
def turnOn(self):
return self._method('turnOn').take_none()
def turnOn(self):
return self._method('turnOn').take_none()
def shutdown(self):
return self._method('shutdown').take_none()
def shutdown(self):
return self._method('shutdown').take_none()
def reboot(self):
return self._method('reboot').take_none()
def reboot(self):
return self._method('reboot').take_none()
def getID(self) -> int:
return self._method('getID').take_int()
def getID(self) -> int:
return self._method('getID').take_int()
def getLabel(self) -> Optional[str]:
return self._method('getLabel').take_option_string()
def getLabel(self) -> Optional[str]:
return self._method('getLabel').take_option_string()
def isOn(self) -> bool:
return self._method('isOn').take_bool()
def isOn(self) -> bool:
return self._method('isOn').take_bool()
class CCComputer(BasePeripheral, ComputerMixin):
pass
pass
class CCTurtle(BasePeripheral, ComputerMixin):
pass
pass
@dataclass
class ModemMessage:
reply_channel: int
content: Any
distance: LuaNum
reply_channel: int
content: Any
distance: LuaNum
class ModemMixin:
def isOpen(self, channel: int) -> bool:
return self._method('isOpen', channel).take_bool()
def isOpen(self, channel: int) -> bool:
return self._method('isOpen', channel).take_bool()
def open(self, channel: int):
return self._method('open', channel).take_none()
def open(self, channel: int):
return self._method('open', channel).take_none()
def close(self, channel: int):
return self._method('close', channel).take_none()
def close(self, channel: int):
return self._method('close', channel).take_none()
def closeAll(self):
return self._method('closeAll').take_none()
def closeAll(self):
return self._method('closeAll').take_none()
def transmit(self, channel: int, replyChannel: int, message: Any):
return self._method('transmit', channel, replyChannel, message).take_none()
def transmit(self, channel: int, replyChannel: int, message: Any):
return self._method('transmit', channel, replyChannel, message).take_none()
def isWireless(self) -> bool:
return self._method('isWireless').take_bool()
def isWireless(self) -> bool:
return self._method('isWireless').take_bool()
@property
def _side(self):
return self._prepend_params[0]
@property
def _side(self):
return self._prepend_params[0]
def receive(self, channel: int):
from .os import captureEvent
def receive(self, channel: int):
from .os import captureEvent
if self.isOpen(channel):
raise Exception('Channel is busy')
if self.isOpen(channel):
raise Exception('Channel is busy')
self.open(channel)
try:
for evt in captureEvent('modem_message'):
if evt[0] != self._side:
continue
if evt[1] != channel:
continue
yield ModemMessage(*evt[2:])
finally:
self.close(channel)
self.open(channel)
try:
for evt in captureEvent('modem_message'):
if evt[0] != self._side:
continue
if evt[1] != channel:
continue
yield ModemMessage(*evt[2:])
finally:
self.close(channel)
class CCWirelessModem(BasePeripheral, ModemMixin):
pass
pass
class CCWiredModem(BasePeripheral, ModemMixin):
def getNameLocal(self) -> Optional[str]:
return self._method('getNameLocal').take_option_string()
def getNameLocal(self) -> Optional[str]:
return self._method('getNameLocal').take_option_string()
def getNamesRemote(self) -> List[str]:
return self._method('getNamesRemote').take_list_of_strings()
def getNamesRemote(self) -> List[str]:
return self._method('getNamesRemote').take_list_of_strings()
def getTypeRemote(self, peripheralName: str) -> Optional[str]:
return self._method('getTypeRemote', ser.encode(peripheralName)).take_option_string()
def getTypeRemote(self, peripheralName: str) -> Optional[str]:
return self._method('getTypeRemote', ser.encode(peripheralName)).take_option_string()
def isPresentRemote(self, peripheralName: str) -> bool:
return self._method('isPresentRemote', ser.encode(peripheralName)).take_bool()
def isPresentRemote(self, peripheralName: str) -> bool:
return self._method('isPresentRemote', ser.encode(peripheralName)).take_bool()
def wrapRemote(self, peripheralName: str) -> Optional[BasePeripheral]:
# use instead getMethodsRemote and callRemote
# NOTE: you can also use peripheral.wrap(peripheralName)
def wrapRemote(self, peripheralName: str) -> Optional[BasePeripheral]:
# use instead getMethodsRemote and callRemote
# NOTE: you can also use peripheral.wrap(peripheralName)
ptype = self.getTypeRemote(peripheralName)
if ptype is None:
return None
ptype = self.getTypeRemote(peripheralName)
if ptype is None:
return None
return TYPE_MAP[ptype](
self._lua_method_expr, *self._prepend_params,
b'callRemote', ser.encode(peripheralName),
)
return TYPE_MAP[ptype](
self._lua_method_expr, *self._prepend_params,
b'callRemote', ser.encode(peripheralName),
)
# NOTE: for TermTarget use peripheral.get_term_target(peripheralName)
# NOTE: for TermTarget use peripheral.get_term_target(peripheralName)
class CCPrinter(BasePeripheral):
def newPage(self) -> bool:
return self._method('newPage').take_bool()
def newPage(self) -> bool:
return self._method('newPage').take_bool()
def endPage(self) -> bool:
return self._method('endPage').take_bool()
def endPage(self) -> bool:
return self._method('endPage').take_bool()
def write(self, text: str):
return self._method('write', ser.dirty_encode(text)).take_none()
def write(self, text: str):
return self._method('write', ser.dirty_encode(text)).take_none()
def setCursorPos(self, x: int, y: int):
return self._method('setCursorPos', x, y).take_none()
def setCursorPos(self, x: int, y: int):
return self._method('setCursorPos', x, y).take_none()
def getCursorPos(self) -> Tuple[int, int]:
rp = self._method('getCursorPos')
return tuple(rp.take_int() for _ in range(2))
def getCursorPos(self) -> Tuple[int, int]:
rp = self._method('getCursorPos')
return tuple(rp.take_int() for _ in range(2))
def getPageSize(self) -> Tuple[int, int]:
rp = self._method('getPageSize')
return tuple(rp.take_int() for _ in range(2))
def getPageSize(self) -> Tuple[int, int]:
rp = self._method('getPageSize')
return tuple(rp.take_int() for _ in range(2))
def setPageTitle(self, title: str):
return self._method('setPageTitle', ser.encode(title)).take_none()
def setPageTitle(self, title: str):
return self._method('setPageTitle', ser.encode(title)).take_none()
def getPaperLevel(self) -> int:
return self._method('getPaperLevel').take_int()
def getPaperLevel(self) -> int:
return self._method('getPaperLevel').take_int()
def getInkLevel(self) -> int:
return self._method('getInkLevel').take_int()
def getInkLevel(self) -> int:
return self._method('getInkLevel').take_int()
class CCSpeaker(BasePeripheral):
def playNote(self, instrument: str, volume: int = 1, pitch: int = 1) -> bool:
# instrument:
# https://minecraft.gamepedia.com/Note_Block#Instruments
# bass
# basedrum
# bell
# chime
# flute
# guitar
# hat
# snare
# xylophone
# iron_xylophone
# pling
# banjo
# bit
# didgeridoo
# cow_bell
def playNote(self, instrument: str, volume: int = 1, pitch: int = 1) -> bool:
# instrument:
# https://minecraft.gamepedia.com/Note_Block#Instruments
# bass
# basedrum
# bell
# chime
# flute
# guitar
# hat
# snare
# xylophone
# iron_xylophone
# pling
# banjo
# bit
# didgeridoo
# cow_bell
# volume 0..3
# pitch 0..24
return self._method('playNote', ser.encode(instrument), volume, pitch).take_bool()
# volume 0..3
# pitch 0..24
return self._method('playNote', ser.encode(instrument), volume, pitch).take_bool()
def playSound(self, sound: str, volume: int = 1, pitch: int = 1) -> bool:
# volume 0..3
# pitch 0..2
return self._method('playSound', ser.encode(sound), volume, pitch).take_bool()
def playSound(self, sound: str, volume: int = 1, pitch: int = 1) -> bool:
# volume 0..3
# pitch 0..2
return self._method('playSound', ser.encode(sound), volume, pitch).take_bool()
class CCCommandBlock(BasePeripheral):
def getCommand(self) -> str:
return self._method('getCommand').take_string()
def getCommand(self) -> str:
return self._method('getCommand').take_string()
def setCommand(self, command: str):
return self._method('setCommand', ser.encode(command)).take_none()
def setCommand(self, command: str):
return self._method('setCommand', ser.encode(command)).take_none()
def runCommand(self):
return self._method('runCommand').check_bool_error()
def runCommand(self):
return self._method('runCommand').check_bool_error()
class CCWorkbench(BasePeripheral):
def craft(self, quantity: int = 64):
return self._method('craft', quantity).check_bool_error()
def craft(self, quantity: int = 64):
return self._method('craft', quantity).check_bool_error()
class CCInventory(BasePeripheral):
def getItemDetail(self, slot: int) -> Optional[dict]:
return self._method('getItemDetail', slot).take()
def getItemDetail(self, slot: int) -> Optional[dict]:
return self._method('getItemDetail', slot).take()
def list(self) -> Dict[int, dict]:
return self._method('list').take_dict()
def list(self) -> Dict[int, dict]:
return self._method('list').take_dict()
def pullItems(self, fromName: str, fromSlot: int, limit: int = None, toSlot: int = None) -> int:
return self._method('pullItems', ser.encode(fromName), fromSlot, limit, toSlot).take_int()
def pullItems(self, fromName: str, fromSlot: int, limit: int = None, toSlot: int = None) -> int:
return self._method('pullItems', ser.encode(fromName), fromSlot, limit, toSlot).take_int()
def pushItems(self, toName: str, fromSlot: int, limit: int = None, toSlot: int = None) -> int:
return self._method('pushItems', ser.encode(toName), fromSlot, limit, toSlot).take_int()
def pushItems(self, toName: str, fromSlot: int, limit: int = None, toSlot: int = None) -> int:
return self._method('pushItems', ser.encode(toName), fromSlot, limit, toSlot).take_int()
def size(self) -> int:
return self._method('size').take_int()
def size(self) -> int:
return self._method('size').take_int()
TYPE_MAP = {}
@ -273,55 +273,55 @@ method = eval_lua_method_factory('peripheral.')
__all__ = (
'BasePeripheral', # exposed for subclassing & registerType
'CCInventory', # exposed for registerType for 3rdparty mod inventory-like entities
'isPresent',
'getType',
'getNames',
'wrap',
'registerType',
'get_term_target',
'BasePeripheral', # exposed for subclassing & registerType
'CCInventory', # exposed for registerType for 3rdparty mod inventory-like entities
'isPresent',
'getType',
'getNames',
'wrap',
'registerType',
'get_term_target',
)
def isPresent(side: str) -> bool:
return method('isPresent', ser.encode(side)).take_bool()
return method('isPresent', ser.encode(side)).take_bool()
def getType(side: str) -> Optional[str]:
return method('getType', ser.encode(side)).take_option_string()
return method('getType', ser.encode(side)).take_option_string()
def getNames() -> List[str]:
return method('getNames').take_list_of_strings()
return method('getNames').take_list_of_strings()
# use instead getMethods and call
def wrap(side: str) -> Optional[BasePeripheral]:
ptype = getType(side)
if ptype is None:
return None
ptype = getType(side)
if ptype is None:
return None
m = 'peripheral.call'
m = 'peripheral.call'
side = ser.encode(side)
if ptype == 'modem':
if method('call', side, b'isWireless').take_bool():
return CCWirelessModem(m, side)
else:
return CCWiredModem(m, side)
else:
return TYPE_MAP[ptype](m, side)
side = ser.encode(side)
if ptype == 'modem':
if method('call', side, b'isWireless').take_bool():
return CCWirelessModem(m, side)
else:
return CCWiredModem(m, side)
else:
return TYPE_MAP[ptype](m, side)
def registerType(ptype: str, pcls: Type[BasePeripheral]):
TYPE_MAP[ptype] = pcls
TYPE_MAP[ptype] = pcls
def get_term_target(side: str) -> TermTarget:
return TermTarget('peripheral.wrap({})'.format(
lua_string(side),
))
return TermTarget('peripheral.wrap({})'.format(
lua_string(side),
))
registerType('drive', CCDrive)
@ -333,15 +333,15 @@ registerType('speaker', CCSpeaker)
registerType('command', CCCommandBlock)
registerType('workbench', CCWorkbench)
for k in [
'chest',
'furnace',
'barrel',
'hopper',
'dropper',
'dispenser',
'blast_furnace',
'smoker',
'shulker_box',
'brewing_stand',
'chest',
'furnace',
'barrel',
'hopper',
'dropper',
'dispenser',
'blast_furnace',
'smoker',
'shulker_box',
'brewing_stand',
]:
registerType('minecraft:' + k, CCInventory)
registerType('minecraft:' + k, CCInventory)

View file

@ -5,14 +5,14 @@ method = eval_lua_method_factory('pocket.')
__all__ = (
'equipBack',
'unequipBack',
'equipBack',
'unequipBack',
)
def equipBack():
return method('equipBack').check_bool_error()
return method('equipBack').check_bool_error()
def unequipBack():
return method('unequipBack').check_bool_error()
return method('unequipBack').check_bool_error()

View file

@ -9,17 +9,17 @@ method = eval_lua_method_factory('rednet.')
__all__ = (
'CHANNEL_REPEAT',
'CHANNEL_BROADCAST',
'open',
'close',
'send',
'broadcast',
'receive',
'isOpen',
'host',
'unhost',
'lookup',
'CHANNEL_REPEAT',
'CHANNEL_BROADCAST',
'open',
'close',
'send',
'broadcast',
'receive',
'isOpen',
'host',
'unhost',
'lookup',
)
@ -28,48 +28,48 @@ CHANNEL_BROADCAST = 65535
def open(side: str):
return method('open', ser.encode(side)).take_none()
return method('open', ser.encode(side)).take_none()
def close(side: str = None):
return method('close', ser.nil_encode(side)).take_none()
return method('close', ser.nil_encode(side)).take_none()
def send(receiverID: int, message: Any, protocol: str = None) -> bool:
return method('send', receiverID, message, ser.nil_encode(protocol)).take_bool()
return method('send', receiverID, message, ser.nil_encode(protocol)).take_bool()
def broadcast(message: Any, protocol: str = None):
return method('broadcast', message, ser.nil_encode(protocol)).take_none()
return method('broadcast', message, ser.nil_encode(protocol)).take_none()
def receive(
protocolFilter: str = None, timeout: LuaNum = None,
protocolFilter: str = None, timeout: LuaNum = None,
) -> Optional[Tuple[int, Any, Optional[str]]]:
rp = method('receive', ser.nil_encode(protocolFilter), timeout)
if rp.peek() is None:
return None
return (rp.take_int(), rp.take(), rp.take_option_string())
rp = method('receive', ser.nil_encode(protocolFilter), timeout)
if rp.peek() is None:
return None
return (rp.take_int(), rp.take(), rp.take_option_string())
def isOpen(side: str = None) -> bool:
return method('isOpen', ser.nil_encode(side)).take_bool()
return method('isOpen', ser.nil_encode(side)).take_bool()
def host(protocol: str, hostname: str):
return method('host', ser.encode(protocol), ser.encode(hostname)).take_none()
return method('host', ser.encode(protocol), ser.encode(hostname)).take_none()
def unhost(protocol: str):
return method('unhost', ser.encode(protocol)).take_none()
return method('unhost', ser.encode(protocol)).take_none()
def lookup(protocol: str, hostname: str = None) -> Union[Optional[int], List[int]]:
rp = method('lookup', ser.encode(protocol), ser.nil_encode(hostname))
if hostname is None:
r = []
while rp.peek() is not None:
r.append(rp.take_int())
return r
else:
return rp.take_option_int()
rp = method('lookup', ser.encode(protocol), ser.nil_encode(hostname))
if hostname is None:
r = []
while rp.peek() is not None:
r.append(rp.take_int())
return r
else:
return rp.take_option_int()

View file

@ -8,61 +8,61 @@ method = eval_lua_method_factory('redstone.')
__all__ = (
'getSides',
'getInput',
'setOutput',
'getOutput',
'getAnalogInput',
'setAnalogOutput',
'getAnalogOutput',
'getBundledInput',
'setBundledOutput',
'getBundledOutput',
'testBundledInput',
'getSides',
'getInput',
'setOutput',
'getOutput',
'getAnalogInput',
'setAnalogOutput',
'getAnalogOutput',
'getBundledInput',
'setBundledOutput',
'getBundledOutput',
'testBundledInput',
)
def getSides() -> List[str]:
return method('getSides').take_list_of_strings()
return method('getSides').take_list_of_strings()
def getInput(side: str) -> bool:
return method('getInput', ser.encode(side)).take_bool()
return method('getInput', ser.encode(side)).take_bool()
def setOutput(side: str, value: bool):
return method('setOutput', ser.encode(side), value).take_none()
return method('setOutput', ser.encode(side), value).take_none()
def getOutput(side: str) -> bool:
return method('getOutput', ser.encode(side)).take_bool()
return method('getOutput', ser.encode(side)).take_bool()
def getAnalogInput(side: str) -> int:
return method('getAnalogInput', ser.encode(side)).take_int()
return method('getAnalogInput', ser.encode(side)).take_int()
def setAnalogOutput(side: str, strength: int):
return method('setAnalogOutput', ser.encode(side), strength).take_none()
return method('setAnalogOutput', ser.encode(side), strength).take_none()
def getAnalogOutput(side: str) -> int:
return method('getAnalogOutput', ser.encode(side)).take_int()
return method('getAnalogOutput', ser.encode(side)).take_int()
# bundled cables are not available in vanilla
def getBundledInput(side: str) -> int:
return method('getBundledInput', ser.encode(side)).take_int()
return method('getBundledInput', ser.encode(side)).take_int()
def setBundledOutput(side: str, colors: int):
return method('setBundledOutput', ser.encode(side), colors).take_none()
return method('setBundledOutput', ser.encode(side), colors).take_none()
def getBundledOutput(side: str) -> int:
return method('getBundledOutput', ser.encode(side)).take_int()
return method('getBundledOutput', ser.encode(side)).take_int()
def testBundledInput(side: str, color: int) -> bool:
return method('testBundledInput', ser.encode(side), color).take_bool()
return method('testBundledInput', ser.encode(side), color).take_bool()

View file

@ -8,78 +8,78 @@ method = eval_lua_method_factory('settings.')
__all__ = (
'define',
'undefine',
'getDetails',
'set',
'get',
'unset',
'clear',
'getNames',
'load',
'save',
'define',
'undefine',
'getDetails',
'set',
'get',
'unset',
'clear',
'getNames',
'load',
'save',
)
def define(name: str, description: str = None, default: Any = None, type: str = None):
options = {}
if description is not None:
options[b'description'] = ser.encode(description)
if default is not None:
options[b'default'] = default
if type is not None:
options[b'type'] = ser.encode(type)
return method('define', ser.encode(name), options).take_none()
options = {}
if description is not None:
options[b'description'] = ser.encode(description)
if default is not None:
options[b'default'] = default
if type is not None:
options[b'type'] = ser.encode(type)
return method('define', ser.encode(name), options).take_none()
def undefine(name: str):
return method('undefine', ser.encode(name)).take_none()
return method('undefine', ser.encode(name)).take_none()
def getDetails(name: str) -> dict:
tp = method('getDetails', ser.encode(name)).take_dict((
b'changed',
b'description',
b'default',
b'type',
b'value',
))
r = {}
r['changed'] = tp.take_bool()
for k, v in [
('description', tp.take_option_string()),
('default', tp.take()),
('type', tp.take_option_string()),
('value', tp.take()),
]:
if v is not None:
r[k] = v
return r
tp = method('getDetails', ser.encode(name)).take_dict((
b'changed',
b'description',
b'default',
b'type',
b'value',
))
r = {}
r['changed'] = tp.take_bool()
for k, v in [
('description', tp.take_option_string()),
('default', tp.take()),
('type', tp.take_option_string()),
('value', tp.take()),
]:
if v is not None:
r[k] = v
return r
def set(name: str, value: Any):
return method('set', ser.encode(name), value).take_none()
return method('set', ser.encode(name), value).take_none()
def get(name: str, default: Any = None) -> Any:
return method('get', ser.encode(name), default).take()
return method('get', ser.encode(name), default).take()
def unset(name: str):
return method('unset', ser.encode(name)).take_none()
return method('unset', ser.encode(name)).take_none()
def clear():
return method('clear').take_none()
return method('clear').take_none()
def getNames() -> List[str]:
return method('getNames').take_list_of_strings()
return method('getNames').take_list_of_strings()
def load(path: str = None) -> bool:
return method('load', ser.nil_encode(path)).take_bool()
return method('load', ser.nil_encode(path)).take_bool()
def save(path: str = None) -> bool:
return method('save', ser.nil_encode(path)).take_bool()
return method('save', ser.nil_encode(path)).take_bool()

View file

@ -8,101 +8,101 @@ method = eval_lua_method_factory('shell.')
__all__ = (
'exit',
'dir',
'setDir',
'path',
'setPath',
'resolve',
'resolveProgram',
'aliases',
'setAlias',
'clearAlias',
'programs',
'getRunningProgram',
'run',
'execute',
'openTab',
'switchTab',
'complete',
'completeProgram',
'exit',
'dir',
'setDir',
'path',
'setPath',
'resolve',
'resolveProgram',
'aliases',
'setAlias',
'clearAlias',
'programs',
'getRunningProgram',
'run',
'execute',
'openTab',
'switchTab',
'complete',
'completeProgram',
)
def exit():
return method('exit').take_none()
return method('exit').take_none()
def dir() -> str:
return method('dir').take_string()
return method('dir').take_string()
def setDir(path: str):
return method('setDir', ser.encode(path)).take_none()
return method('setDir', ser.encode(path)).take_none()
def path() -> str:
return method('path').take_string()
return method('path').take_string()
def setPath(path: str):
return method('setPath', ser.encode(path)).take_none()
return method('setPath', ser.encode(path)).take_none()
def resolve(localPath: str) -> str:
return method('resolve', ser.encode(localPath)).take_string()
return method('resolve', ser.encode(localPath)).take_string()
def resolveProgram(name: str) -> Optional[str]:
return method('resolveProgram', ser.encode(name)).take_option_string()
return method('resolveProgram', ser.encode(name)).take_option_string()
def aliases() -> Dict[str, str]:
d = method('aliases').take_dict()
return {ser.decode(k): ser.decode(v) for k, v in d.items()}
d = method('aliases').take_dict()
return {ser.decode(k): ser.decode(v) for k, v in d.items()}
def setAlias(alias: str, program: str):
return method('setAlias', ser.encode(alias), ser.encode(program)).take_none()
return method('setAlias', ser.encode(alias), ser.encode(program)).take_none()
def clearAlias(alias: str):
return method('clearAlias', ser.encode(alias)).take_none()
return method('clearAlias', ser.encode(alias)).take_none()
def programs(showHidden: bool = None) -> List[str]:
return method('programs', showHidden).take_list_of_strings()
return method('programs', showHidden).take_list_of_strings()
def getRunningProgram() -> str:
return method('getRunningProgram').take_string()
return method('getRunningProgram').take_string()
def run(command: str, *args: str) -> bool:
args = tuple(ser.encode(a) for a in args)
return method('run', ser.encode(command), *args).take_bool()
args = tuple(ser.encode(a) for a in args)
return method('run', ser.encode(command), *args).take_bool()
def execute(command: str, *args: str) -> bool:
args = tuple(ser.encode(a) for a in args)
return method('execute', ser.encode(command), *args).take_bool()
args = tuple(ser.encode(a) for a in args)
return method('execute', ser.encode(command), *args).take_bool()
def openTab(command: str, *args: str) -> int:
args = tuple(ser.encode(a) for a in args)
return method('openTab', ser.encode(command), *args).take_int()
args = tuple(ser.encode(a) for a in args)
return method('openTab', ser.encode(command), *args).take_int()
def switchTab(tabID: int):
return method('switchTab', tabID).take_none()
return method('switchTab', tabID).take_none()
def complete(prefix: str) -> List[str]:
return method('complete', ser.encode(prefix)).take_list_of_strings()
return method('complete', ser.encode(prefix)).take_list_of_strings()
def completeProgram(prefix: str) -> List[str]:
return method('completeProgram', ser.encode(prefix)).take_list_of_strings()
return method('completeProgram', ser.encode(prefix)).take_list_of_strings()
# TODO: ?
# these functions won't be implemented
@ -112,4 +112,4 @@ def completeProgram(prefix: str) -> List[str]:
# getCompletionInfo
# we can create callbacks to python code, but this will require
# connection to python, and will break the shell if python disconnects
# connection to python, and will break the shell if python disconnects

View file

@ -7,7 +7,7 @@ from ..sess import eval_lua_method_factory, lua_context_object
class TermAPI(BaseSubAPI, TermMixin):
pass
pass
method = eval_lua_method_factory('term.')
@ -15,27 +15,27 @@ tapi = TermAPI('term')
__all__ = (
'write',
'blit',
'clear',
'clearLine',
'getCursorPos',
'setCursorPos',
'getCursorBlink',
'setCursorBlink',
'isColor',
'getSize',
'scroll',
'setTextColor',
'getTextColor',
'setBackgroundColor',
'getBackgroundColor',
'getPaletteColor',
'setPaletteColor',
'nativePaletteColor',
'redirect',
'get_current_target',
'get_native_target',
'write',
'blit',
'clear',
'clearLine',
'getCursorPos',
'setCursorPos',
'getCursorBlink',
'setCursorBlink',
'isColor',
'getSize',
'scroll',
'setTextColor',
'getTextColor',
'setBackgroundColor',
'getBackgroundColor',
'getPaletteColor',
'setPaletteColor',
'nativePaletteColor',
'redirect',
'get_current_target',
'get_native_target',
)
@ -59,23 +59,23 @@ setPaletteColor = tapi.setPaletteColor
def nativePaletteColor(colorID: int) -> Tuple[float, float, float]:
rp = method('nativePaletteColor', colorID)
return tuple(rp.take_number() for _ in range(3))
rp = method('nativePaletteColor', colorID)
return tuple(rp.take_number() for _ in range(3))
@contextmanager
def redirect(target: TermTarget):
with lua_context_object(
'term.redirect(...)',
(target, ),
'term.redirect({e})',
):
yield
with lua_context_object(
'term.redirect(...)',
(target, ),
'term.redirect({e})',
):
yield
def get_current_target() -> TermTarget:
return TermTarget('term.current()')
return TermTarget('term.current()')
def get_native_target() -> TermTarget:
return TermTarget('term.native()')
return TermTarget('term.native()')

View file

@ -9,52 +9,52 @@ method = eval_lua_method_factory('textutils.')
__all__ = (
'slowWrite',
'slowPrint',
'formatTime',
'tabulate',
'pagedTabulate',
'pagedPrint',
'complete',
'slowWrite',
'slowPrint',
'formatTime',
'tabulate',
'pagedTabulate',
'pagedPrint',
'complete',
)
def slowWrite(text: str, rate: LuaNum = None):
return method('slowWrite', ser.dirty_encode(text), rate).take_none()
return method('slowWrite', ser.dirty_encode(text), rate).take_none()
def slowPrint(text: str, rate: LuaNum = None):
return method('slowPrint', ser.dirty_encode(text), rate).take_none()
return method('slowPrint', ser.dirty_encode(text), rate).take_none()
def formatTime(time: LuaNum, twentyFourHour: bool = None) -> str:
return method('formatTime', time, twentyFourHour).take_string()
return method('formatTime', time, twentyFourHour).take_string()
def _prepareTab(rows_and_colors):
r = []
for item in rows_and_colors:
if isinstance(item, int):
r.append(item)
else:
r.append([ser.dirty_encode(x) for x in item])
return r
r = []
for item in rows_and_colors:
if isinstance(item, int):
r.append(item)
else:
r.append([ser.dirty_encode(x) for x in item])
return r
def tabulate(*rows_and_colors: Union[List[str], int]):
return method('tabulate', *_prepareTab(rows_and_colors)).take_none()
return method('tabulate', *_prepareTab(rows_and_colors)).take_none()
def pagedTabulate(*rows_and_colors: Union[List[str], int]):
return method('pagedTabulate', *_prepareTab(rows_and_colors)).take_none()
return method('pagedTabulate', *_prepareTab(rows_and_colors)).take_none()
def pagedPrint(text: str, freeLines: int = None) -> int:
return method('pagedPrint', ser.dirty_encode(text), freeLines).take_int()
return method('pagedPrint', ser.dirty_encode(text), freeLines).take_int()
def complete(partial: str, possible: List[str]) -> List[str]:
return [p[len(partial):] for p in possible if p.startswith(partial)]
return [p[len(partial):] for p in possible if p.startswith(partial)]
# Questionable to implement
@ -66,4 +66,4 @@ def complete(partial: str, possible: List[str]) -> List[str]:
# unserializeJSON
# urlEncode
# json_null
# empty_json_array
# empty_json_array

View file

@ -9,233 +9,233 @@ method = eval_lua_method_factory('turtle.')
def inspect_result(rp):
success = rp.take_bool()
if not success:
msg = rp.take_string()
if msg == 'No block to inspect':
return None
raise LuaException(msg)
else:
return rp.take_dict()
success = rp.take_bool()
if not success:
msg = rp.take_string()
if msg == 'No block to inspect':
return None
raise LuaException(msg)
else:
return rp.take_dict()
__all__ = (
'craft',
'forward',
'back',
'up',
'down',
'turnLeft',
'turnRight',
'select',
'getSelectedSlot',
'getItemCount',
'getItemSpace',
'getItemDetail',
'equipLeft',
'equipRight',
'attack',
'attackUp',
'attackDown',
'dig',
'digUp',
'digDown',
'place',
'placeUp',
'placeDown',
'detect',
'detectUp',
'detectDown',
'inspect',
'inspectUp',
'inspectDown',
'compare',
'compareUp',
'compareDown',
'compareTo',
'drop',
'dropUp',
'dropDown',
'suck',
'suckUp',
'suckDown',
'refuel',
'getFuelLevel',
'getFuelLimit',
'transferTo',
'craft',
'forward',
'back',
'up',
'down',
'turnLeft',
'turnRight',
'select',
'getSelectedSlot',
'getItemCount',
'getItemSpace',
'getItemDetail',
'equipLeft',
'equipRight',
'attack',
'attackUp',
'attackDown',
'dig',
'digUp',
'digDown',
'place',
'placeUp',
'placeDown',
'detect',
'detectUp',
'detectDown',
'inspect',
'inspectUp',
'inspectDown',
'compare',
'compareUp',
'compareDown',
'compareTo',
'drop',
'dropUp',
'dropDown',
'suck',
'suckUp',
'suckDown',
'refuel',
'getFuelLevel',
'getFuelLimit',
'transferTo',
)
def craft(quantity: int = 64):
return method('craft', quantity).check_bool_error()
return method('craft', quantity).check_bool_error()
def forward():
return method('forward').check_bool_error()
return method('forward').check_bool_error()
def back():
return method('back').check_bool_error()
return method('back').check_bool_error()
def up():
return method('up').check_bool_error()
return method('up').check_bool_error()
def down():
return method('down').check_bool_error()
return method('down').check_bool_error()
def turnLeft():
return method('turnLeft').check_bool_error()
return method('turnLeft').check_bool_error()
def turnRight():
return method('turnRight').check_bool_error()
return method('turnRight').check_bool_error()
def select(slotNum: int):
return method('select', slotNum).check_bool_error()
return method('select', slotNum).check_bool_error()
def getSelectedSlot() -> int:
return method('getSelectedSlot').take_int()
return method('getSelectedSlot').take_int()
def getItemCount(slotNum: int = None) -> int:
return method('getItemCount', slotNum).take_int()
return method('getItemCount', slotNum).take_int()
def getItemSpace(slotNum: int = None) -> int:
return method('getItemSpace', slotNum).take_int()
return method('getItemSpace', slotNum).take_int()
def getItemDetail(slotNum: int = None) -> Optional[dict]:
rp = method('getItemDetail', slotNum)
if rp.peek() is None:
return None
return rp.take_dict()
rp = method('getItemDetail', slotNum)
if rp.peek() is None:
return None
return rp.take_dict()
def equipLeft():
return method('equipLeft').check_bool_error()
return method('equipLeft').check_bool_error()
def equipRight():
return method('equipRight').check_bool_error()
return method('equipRight').check_bool_error()
def attack():
return method('attack').check_bool_error()
return method('attack').check_bool_error()
def attackUp():
return method('attackUp').check_bool_error()
return method('attackUp').check_bool_error()
def attackDown():
return method('attackDown').check_bool_error()
return method('attackDown').check_bool_error()
def dig():
return method('dig').check_bool_error()
return method('dig').check_bool_error()
def digUp():
return method('digUp').check_bool_error()
return method('digUp').check_bool_error()
def digDown():
return method('digDown').check_bool_error()
return method('digDown').check_bool_error()
def place(signText: str = None):
return method('place', ser.nil_encode(signText)).check_bool_error()
return method('place', ser.nil_encode(signText)).check_bool_error()
def placeUp(signText: str = None):
return method('placeUp', ser.nil_encode(signText)).check_bool_error()
return method('placeUp', ser.nil_encode(signText)).check_bool_error()
def placeDown(signText: str = None):
return method('placeDown', ser.nil_encode(signText)).check_bool_error()
return method('placeDown', ser.nil_encode(signText)).check_bool_error()
def detect() -> bool:
return method('detect').take_bool()
return method('detect').take_bool()
def detectUp() -> bool:
return method('detectUp').take_bool()
return method('detectUp').take_bool()
def detectDown() -> bool:
return method('detectDown').take_bool()
return method('detectDown').take_bool()
def inspect() -> Optional[dict]:
return inspect_result(method('inspect'))
return inspect_result(method('inspect'))
def inspectUp() -> Optional[dict]:
return inspect_result(method('inspectUp'))
return inspect_result(method('inspectUp'))
def inspectDown() -> Optional[dict]:
return inspect_result(method('inspectDown'))
return inspect_result(method('inspectDown'))
def compare() -> bool:
return method('compare').take_bool()
return method('compare').take_bool()
def compareUp() -> bool:
return method('compareUp').take_bool()
return method('compareUp').take_bool()
def compareDown() -> bool:
return method('compareDown').take_bool()
return method('compareDown').take_bool()
def compareTo(slot: int) -> bool:
return method('compareTo', slot).take_bool()
return method('compareTo', slot).take_bool()
def drop(count: int = None):
return method('drop', count).check_bool_error()
return method('drop', count).check_bool_error()
def dropUp(count: int = None):
return method('dropUp', count).check_bool_error()
return method('dropUp', count).check_bool_error()
def dropDown(count: int = None):
return method('dropDown', count).check_bool_error()
return method('dropDown', count).check_bool_error()
def suck(amount: int = None):
return method('suck', amount).check_bool_error()
return method('suck', amount).check_bool_error()
def suckUp(amount: int = None):
return method('suckUp', amount).check_bool_error()
return method('suckUp', amount).check_bool_error()
def suckDown(amount: int = None):
return method('suckDown', amount).check_bool_error()
return method('suckDown', amount).check_bool_error()
def refuel(quantity: int = None):
return method('refuel', quantity).check_bool_error()
return method('refuel', quantity).check_bool_error()
def getFuelLevel() -> int:
return method('getFuelLevel').take_int()
return method('getFuelLevel').take_int()
def getFuelLimit() -> int:
return method('getFuelLimit').take_int()
return method('getFuelLimit').take_int()
def transferTo(slot: int, quantity: int = None):
return method('transferTo', slot, quantity).check_bool_error()
return method('transferTo', slot, quantity).check_bool_error()

View file

@ -7,44 +7,44 @@ from .mixins import TermMixin, TermTarget
class CCWindow(BaseSubAPI, TermMixin):
def setVisible(self, visibility: bool):
return self._method('setVisible', visibility).take_none()
def setVisible(self, visibility: bool):
return self._method('setVisible', visibility).take_none()
def redraw(self):
return self._method('redraw').take_none()
def redraw(self):
return self._method('redraw').take_none()
def restoreCursor(self):
return self._method('restoreCursor').take_none()
def restoreCursor(self):
return self._method('restoreCursor').take_none()
def getPosition(self) -> Tuple[int, int]:
rp = self._method('getPosition')
return tuple(rp.take_int() for _ in range(2))
def getPosition(self) -> Tuple[int, int]:
rp = self._method('getPosition')
return tuple(rp.take_int() for _ in range(2))
def reposition(self, x: int, y: int, width: int = None, height: int = None, parent: TermTarget = None):
return self._method('reposition', x, y, width, height, parent).take_none()
def reposition(self, x: int, y: int, width: int = None, height: int = None, parent: TermTarget = None):
return self._method('reposition', x, y, width, height, parent).take_none()
def getLine(self, y: int) -> Tuple[str, bytes, bytes]:
rp = self._method('getLine', y)
return rp.take_string(), rp.take_bytes(), rp.take_bytes()
def getLine(self, y: int) -> Tuple[str, bytes, bytes]:
rp = self._method('getLine', y)
return rp.take_string(), rp.take_bytes(), rp.take_bytes()
def get_term_target(self) -> TermTarget:
return TermTarget(self.get_expr_code())
def get_term_target(self) -> TermTarget:
return TermTarget(self.get_expr_code())
method = eval_lua_method_factory('window.')
__all__ = (
'create',
'create',
)
@contextmanager
def create(
parentTerm: TermTarget, x: int, y: int, width: int, height: int, visible: bool = None,
parentTerm: TermTarget, x: int, y: int, width: int, height: int, visible: bool = None,
) -> CCWindow:
with lua_context_object(
'window.create(...)',
(parentTerm, x, y, width, height, visible),
) as var:
yield CCWindow(var)
with lua_context_object(
'window.create(...)',
(parentTerm, x, y, width, height, visible),
) as var:
yield CCWindow(var)

View file

@ -7,133 +7,133 @@ from cc import eval_lua
@contextmanager
def assert_raises(etype, message=None):
try:
yield
except Exception as e:
assert isinstance(e, etype), repr(e)
if message is not None:
assert e.args == (message, )
else:
raise AssertionError(f'Exception of type {etype} was not raised')
try:
yield
except Exception as e:
assert isinstance(e, etype), repr(e)
if message is not None:
assert e.args == (message, )
else:
raise AssertionError(f'Exception of type {etype} was not raised')
@contextmanager
def assert_takes_time(at_least, at_most):
t = monotonic()
yield
dt = monotonic() - t
# print(at_least, '<=', dt, '<=', at_most)
assert at_least <= dt <= at_most
t = monotonic()
yield
dt = monotonic() - t
# print(at_least, '<=', dt, '<=', at_most)
assert at_least <= dt <= at_most
class AnyInstanceOf:
def __init__(self, cls):
self.c = cls
def __init__(self, cls):
self.c = cls
def __eq__(self, other):
return isinstance(other, self.c)
def __eq__(self, other):
return isinstance(other, self.c)
def step(text):
input(f'{text} [enter]')
input(f'{text} [enter]')
def get_object_table(objname):
rp = eval_lua(f"""
rp = eval_lua(f"""
local r = {{}}
for k in pairs({objname}) do
local t = type({objname}[k])
if r[t] == nil then r[t] = {{}} end
if t == 'number' or t == 'boolean' or t == 'string' then
r[t][k] = {objname}[k]
else
r[t][k] = true
end
local t = type({objname}[k])
if r[t] == nil then r[t] = {{}} end
if t == 'number' or t == 'boolean' or t == 'string' then
r[t][k] = {objname}[k]
else
r[t][k] = true
end
end
return r""", immediate=True)
d = rp.take_dict()
return {
k1.decode('latin1'): {
k2.decode('latin1'): v for k2, v in t.items()
} for k1, t in d.items()
}
d = rp.take_dict()
return {
k1.decode('latin1'): {
k2.decode('latin1'): v for k2, v in t.items()
} for k1, t in d.items()
}
def get_class_table(cls):
items = {
k: v for k, v in vars(cls).items()
if not k.startswith('_')
}
nums = {
k: v for k, v in items.items()
if isinstance(v, (int, float))
}
methods = {
k: True for k, v in items.items()
if isinstance(v, FunctionType)
}
r = {}
if nums:
r['number'] = nums
if methods:
r['function'] = methods
return r
items = {
k: v for k, v in vars(cls).items()
if not k.startswith('_')
}
nums = {
k: v for k, v in items.items()
if isinstance(v, (int, float))
}
methods = {
k: True for k, v in items.items()
if isinstance(v, FunctionType)
}
r = {}
if nums:
r['number'] = nums
if methods:
r['function'] = methods
return r
def get_multiclass_table(*cls):
result = {}
for c in cls:
for k, v in get_class_table(c).items():
result.setdefault(k, {}).update(v)
return result
result = {}
for c in cls:
for k, v in get_class_table(c).items():
result.setdefault(k, {}).update(v)
return result
def term_step(text):
from cc import colors, term
from cc import colors, term
for color in colors.iter_colors():
r, g, b = term.nativePaletteColor(color)
term.setPaletteColor(color, r, g, b)
term.setBackgroundColor(colors.black)
term.setTextColor(colors.white)
term.clear()
term.setCursorPos(1, 1)
term.setCursorBlink(True)
step(text)
for color in colors.iter_colors():
r, g, b = term.nativePaletteColor(color)
term.setPaletteColor(color, r, g, b)
term.setBackgroundColor(colors.black)
term.setTextColor(colors.white)
term.clear()
term.setCursorPos(1, 1)
term.setCursorBlink(True)
step(text)
def _computer_peri(place_thing, thing):
from cc import peripheral
from cc import peripheral
side = 'left'
side = 'left'
step(
f'Place {place_thing} on {side} side of computer\n'
"Don't turn it on!",
)
step(
f'Place {place_thing} on {side} side of computer\n'
"Don't turn it on!",
)
c = peripheral.wrap(side)
assert c is not None
c = peripheral.wrap(side)
assert c is not None
from computercraft.subapis.peripheral import ComputerMixin
tbl = get_object_table(f'peripheral.wrap("{side}")')
assert get_class_table(ComputerMixin) == tbl
from computercraft.subapis.peripheral import ComputerMixin
tbl = get_object_table(f'peripheral.wrap("{side}")')
assert get_class_table(ComputerMixin) == tbl
assert c.isOn() is False
assert isinstance(c.getID(), int)
assert c.getLabel() is None
assert c.turnOn() is None
assert c.isOn() is False
assert isinstance(c.getID(), int)
assert c.getLabel() is None
assert c.turnOn() is None
step(f'{thing.capitalize()} must be turned on now')
step(f'{thing.capitalize()} must be turned on now')
assert c.shutdown() is None
assert c.shutdown() is None
step(f'{thing.capitalize()} must shutdown')
step(f'{thing.capitalize()} must shutdown')
step(f'Now turn on {thing} manually and enter some commands')
step(f'Now turn on {thing} manually and enter some commands')
assert c.reboot() is None
assert c.reboot() is None
step(f'{thing.capitalize()} must reboot')
step(f'{thing.capitalize()} must reboot')
print('Test finished successfully')
print('Test finished successfully')

View file

@ -6,10 +6,10 @@ import argparse
parser = argparse.ArgumentParser(prog=__file__, description='Process some integers.')
parser.add_argument('integers', metavar='N', type=int, nargs='+',
help='an integer for the accumulator')
help='an integer for the accumulator')
parser.add_argument('--sum', dest='accumulate', action='store_const',
const=sum, default=max,
help='sum the integers (default: find the max)')
const=sum, default=max,
help='sum the integers (default: find the max)')
args = parser.parse_args(args=args)
print(args.accumulate(args.integers))
print(args.accumulate(args.integers))

View file

@ -1 +1 @@
raise ValueError
raise ValueError

View file

@ -1 +1 @@
print('Hello world!')
print('Hello world!')

View file

@ -2,4 +2,4 @@ from cc import os
print('ID', os.getComputerID())
print('Label', os.getComputerLabel())
print('Version', os.version())
print('Version', os.version())

View file

@ -6,8 +6,8 @@ m = peripheral.wrap(side)
listen_channel = 5
m.close(listen_channel)
for msg in m.receive(listen_channel):
print(repr(msg))
if msg.content == b'stop':
break
else:
m.transmit(msg.reply_channel, listen_channel, msg.content)
print(repr(msg))
if msg.content == b'stop':
break
else:
m.transmit(msg.reply_channel, listen_channel, msg.content)

View file

@ -1,9 +1,9 @@
from cc import is_turtle, turtle
if not is_turtle():
print('Turtle required!')
exit()
print('Turtle required!')
exit()
for _ in range(4):
turtle.forward()
turtle.turnLeft()
turtle.forward()
turtle.turnLeft()

View file

@ -1,2 +1,2 @@
line = input()
print(f'Entered line: {line}')
print(f'Entered line: {line}')

View file

@ -13,18 +13,18 @@ tbl['function']['iter_colors'] = True
assert _lib.get_class_table(colors) == tbl
cs = colors.combine(
colors.orange,
colors.cyan,
colors.pink,
colors.brown,
colors.orange,
colors.cyan,
colors.pink,
colors.brown,
)
assert isinstance(cs, int)
cs = colors.subtract(cs, colors.brown, colors.green)
assert isinstance(cs, int)
assert cs == colors.combine(
colors.orange,
colors.cyan,
colors.pink,
colors.orange,
colors.cyan,
colors.pink,
)
assert colors.test(cs, colors.red) is False
assert colors.test(cs, colors.cyan) is True
@ -35,4 +35,4 @@ assert 0.68 < r < 0.72
assert 0.18 < g < 0.22
assert 0.58 < b < 0.62
print('Test finished successfully')
print('Test finished successfully')

View file

@ -13,24 +13,24 @@ xyz = commands.getBlockPosition()
assert len(xyz) == 3
for c in xyz:
assert isinstance(c, int)
assert isinstance(c, int)
# TODO: decode bytes?
expected_binfo = {
b'state': {
b'state': AnyInstanceOf(bytes),
b'facing': AnyInstanceOf(bytes),
},
b'name': b'computercraft:computer_command',
b'nbt': {
b'x': xyz[0],
b'y': xyz[1],
b'z': xyz[2],
b'ComputerId': AnyInstanceOf(int),
b'id': b'computercraft:computer_command',
b'On': 1,
},
b'tags': {},
b'state': {
b'state': AnyInstanceOf(bytes),
b'facing': AnyInstanceOf(bytes),
},
b'name': b'computercraft:computer_command',
b'nbt': {
b'x': xyz[0],
b'y': xyz[1],
b'z': xyz[2],
b'ComputerId': AnyInstanceOf(int),
b'id': b'computercraft:computer_command',
b'On': 1,
},
b'tags': {},
}
assert commands.getBlockInfo(*xyz) == expected_binfo
@ -40,7 +40,7 @@ cmdlist = commands.list()
assert len(cmdlist) > 0
for c in cmdlist:
assert isinstance(c, str)
assert isinstance(c, str)
assert commands.exec('say Hello!') == (True, [], AnyInstanceOf(int))
@ -53,4 +53,4 @@ assert len(d[1]) == 1
assert d[1][0].startswith('The difficulty is ')
assert isinstance(d[2], int)
print('Test finished successfully')
print('Test finished successfully')

View file

@ -70,9 +70,9 @@ assert label != 'label'
print(f'Label is {label}')
assert disk.getLabel(s) == label
with assert_raises(LuaException):
assert disk.setLabel(s, 'label') is None
assert disk.setLabel(s, 'label') is None
with assert_raises(LuaException):
assert disk.setLabel(s, None) is None
assert disk.setLabel(s, None) is None
# no effect
assert disk.getLabel(s) == label
@ -83,4 +83,4 @@ step('Audio must be playing now')
assert disk.stopAudio(s) is None
assert disk.eject(s) is None
print('Test finished successfully')
print('Test finished successfully')

View file

@ -7,12 +7,12 @@ assert_raises, AnyInstanceOf = _lib.assert_raises, _lib.AnyInstanceOf
assert _lib.get_class_table(fs) == _lib.get_object_table('fs')
for name in ('tdir', 'tfile'):
if fs.exists(name):
fs.delete(name)
if fs.exists(name):
fs.delete(name)
assert fs.makeDir('tdir') is None
with fs.open('tfile', 'w') as f:
f.writeLine('textline')
f.writeLine('textline')
dlist = set(fs.list('.'))
@ -91,7 +91,7 @@ assert fs.combine('a/b/c', './../.') == 'a/b'
assert fs.getSize('tfile') == 9
assert fs.getSize('tdir') == 0
with assert_raises(LuaException):
fs.getSize('doesnotexist')
fs.getSize('doesnotexist')
assert fs.move('tfile', 'tdir/apple') is None
assert fs.list('tdir') == ['apple']
@ -126,19 +126,19 @@ dlist = set(fs.list('tdir'))
assert dlist == {'apple', 'banana', 'cherry'}
assert fs.attributes('tdir/banana') == {
'created': AnyInstanceOf(int),
'modification': AnyInstanceOf(int),
'isDir': False,
'size': 9,
'created': AnyInstanceOf(int),
'modification': AnyInstanceOf(int),
'isDir': False,
'size': 9,
}
assert fs.attributes('tdir') == {
'created': AnyInstanceOf(int),
'modification': AnyInstanceOf(int),
'isDir': True,
'size': 0,
'created': AnyInstanceOf(int),
'modification': AnyInstanceOf(int),
'isDir': True,
'size': 0,
}
with assert_raises(LuaException):
fs.attributes('doesnotexist')
fs.attributes('doesnotexist')
assert fs.complete('ba', 'tdir') == ['nana']
assert fs.complete('ap', 'tdir') == ['ple']
@ -151,55 +151,55 @@ assert fs.complete('ap', 'tdir', includeFiles=False) == []
assert fs.getSize('tdir/banana') == 9
with fs.open('tdir/banana', 'r') as f:
assert f.read(4) == 'text'
assert f.readLine() == 'line'
assert f.read(1) is None
assert f.readLine() is None
assert f.readAll() is None
assert f.readAll() is None
assert f.read(4) == 'text'
assert f.readLine() == 'line'
assert f.read(1) is None
assert f.readLine() is None
assert f.readAll() is None
assert f.readAll() is None
assert fs.getSize('tdir/banana') == 9
with fs.open('tdir/banana', 'a') as f:
assert f.write('x') is None
assert f.write('x') is None
assert fs.getSize('tdir/banana') == 10
with fs.open('tdir/banana', 'w') as f:
pass
pass
assert fs.getSize('tdir/banana') == 0 # truncate
with fs.open('tdir/banana', 'w') as f:
assert f.write('Bro') is None
assert f.writeLine('wn fox jumps') is None
# assert fs.getSize('tdir/banana') == 0 # changes are not on a disk
assert f.flush() is None
assert fs.getSize('tdir/banana') == len('Brown fox jumps\n')
assert f.write('ov') is None
assert f.write('er ') is None
assert f.write('a lazy') is None
assert f.writeLine(' дог.') is None # supports unicode!
assert f.write('Bro') is None
assert f.writeLine('wn fox jumps') is None
# assert fs.getSize('tdir/banana') == 0 # changes are not on a disk
assert f.flush() is None
assert fs.getSize('tdir/banana') == len('Brown fox jumps\n')
assert f.write('ov') is None
assert f.write('er ') is None
assert f.write('a lazy') is None
assert f.writeLine(' дог.') is None # supports unicode!
assert fs.getSize('tdir/banana') > 9
with fs.open('tdir/banana', 'r') as f:
assert f.readAll() == 'Brown fox jumps\nover a lazy дог.\n'
assert f.readAll() == 'Brown fox jumps\nover a lazy дог.\n'
with assert_raises(LuaException):
with fs.open('tdir/banana', 'rw') as f:
pass
with fs.open('tdir/banana', 'rw') as f:
pass
assert fs.exists('tdir/banana') is True
with fs.open('tdir/binfile', 'wb') as f:
assert f.write(b'a' * 9) is None
assert f.seek() == 9
assert f.seek('set', 0) == 0
assert f.write(b'b' * 3) is None
assert f.seek('cur', -1) == 2
assert f.write(b'c' * 3) is None
assert f.seek('end') == 9
assert f.write(b'd' * 3) is None
with assert_raises(LuaException):
f.seek('set', -10)
assert f.write(b'a' * 9) is None
assert f.seek() == 9
assert f.seek('set', 0) == 0
assert f.write(b'b' * 3) is None
assert f.seek('cur', -1) == 2
assert f.write(b'c' * 3) is None
assert f.seek('end') == 9
assert f.write(b'd' * 3) is None
with assert_raises(LuaException):
f.seek('set', -10)
with fs.open('tdir/binfile', 'rb') as f:
assert f.readAll() == b'bbcccaaaaddd'
assert f.readAll() == b'bbcccaaaaddd'
with fs.open('tdir/binfile', 'r') as f:
assert [line for line in f] == ['bbcccaaaaddd']
assert [line for line in f] == ['bbcccaaaaddd']
assert fs.delete('tdir') is None
assert fs.delete('tfile') is None
@ -207,4 +207,4 @@ assert fs.delete('doesnotexist') is None
assert fs.exists('tdir/banana') is False
print('Test finished successfully')
print('Test finished successfully')

View file

@ -15,4 +15,4 @@ assert gps.locate(debug=True) is None
assert gps.locate(timeout=5, debug=True) is None
print('Test finished successfully')
print('Test finished successfully')

View file

@ -6,9 +6,9 @@ _lib = import_file('_lib.py', __file__)
assert _lib.get_class_table(gps) == _lib.get_object_table('gps')
assert gps.locate() == (
_lib.AnyInstanceOf(int),
_lib.AnyInstanceOf(int),
_lib.AnyInstanceOf(int),
_lib.AnyInstanceOf(int),
_lib.AnyInstanceOf(int),
_lib.AnyInstanceOf(int),
)
print('Test finished successfully')
print('Test finished successfully')

View file

@ -26,4 +26,4 @@ assert help.path() == '/kek'
assert help.topics() == ['index']
assert help.setPath('/rom/help') is None
print('Test finished successfully')
print('Test finished successfully')

View file

@ -17,4 +17,4 @@ assert keys.getName(enter) == 'enter'
# for i in range(255):
# print(i, keys.getName(i))
print('Test finished successfully')
print('Test finished successfully')

View file

@ -27,4 +27,4 @@ assert multishell.getTitle(2) is None
assert multishell.launch({}, 'rom/programs/fun/hello.lua') == 2
assert isinstance(multishell.getTitle(2), str)
print('Test finished successfully')
print('Test finished successfully')

View file

@ -25,11 +25,11 @@ assert _lib.get_class_table(os) == tbl
with _lib.assert_takes_time(1.5, 3):
timer_id = os.startTimer(2)
for e in os.captureEvent('timer'):
if e[0] == timer_id:
print('Timer reached')
break
timer_id = os.startTimer(2)
for e in os.captureEvent('timer'):
if e[0] == timer_id:
print('Timer reached')
break
timer_id = os.startTimer(20)
@ -43,7 +43,7 @@ assert os.cancelAlarm(alarm_id) is None
assert os.cancelAlarm(alarm_id) is None
with _lib.assert_takes_time(1.5, 3):
assert os.sleep(2) is None
assert os.sleep(2) is None
assert (os.version()).startswith('CraftOS ')
assert isinstance(os.getComputerID(), int)
@ -62,4 +62,4 @@ assert isinstance(os.clock(), (int, float))
assert os.run({}, 'rom/programs/fun/hello.lua') is True
print('Test finished successfully')
print('Test finished successfully')

View file

@ -28,7 +28,7 @@ bbbbbbbbbbbbbbbbbbbbbb399399bbbbbbbbbbbbbbbbbbbbb
assert _lib.get_class_table(paintutils) == _lib.get_object_table('paintutils')
with fs.open('img.nfp', 'w') as f:
f.write(pixels)
f.write(pixels)
int_pixels = paintutils.loadImage('img.nfp')
assert len(int_pixels) > 0
@ -69,4 +69,4 @@ term.setCursorPos(1, by + 6)
os.sleep(2)
print('Test finished successfully')
print('Test finished successfully')

View file

@ -8,128 +8,128 @@ tags = set()
def partial(tag, fn, *args):
def wrap():
tags.add(tag)
return fn(*args)
return wrap
def wrap():
tags.add(tag)
return fn(*args)
return wrap
all_parallels = [
('waitForAll', parallel.waitForAll),
('waitForAny', parallel.waitForAny),
('waitForAll', parallel.waitForAll),
('waitForAny', parallel.waitForAny),
]
for name, fn in all_parallels:
tags.clear()
with assert_takes_time(1.5, 3):
# Since os.sleep is mostly waiting for events, it doesn't block execution of parallel threads
# and this snippet takes approximately 2 seconds to complete.
fn(
partial('a', os.sleep, 2),
partial('b', os.sleep, 2),
partial('c', os.sleep, 2),
)
assert tags == {'a', 'b', 'c'}
print(name, 'OK')
tags.clear()
with assert_takes_time(1.5, 3):
# Since os.sleep is mostly waiting for events, it doesn't block execution of parallel threads
# and this snippet takes approximately 2 seconds to complete.
fn(
partial('a', os.sleep, 2),
partial('b', os.sleep, 2),
partial('c', os.sleep, 2),
)
assert tags == {'a', 'b', 'c'}
print(name, 'OK')
for name, fn in all_parallels:
tags.clear()
tts = (0, 1) if name == 'waitForAny' else (1.5, 3)
with assert_takes_time(*tts):
fn(
partial('fast', os.version),
partial('s1', os.sleep, 2),
partial('s2', os.sleep, 2),
)
assert tags == {'fast', 's1', 's2'}
print(name, 'fast OK')
tags.clear()
tts = (0, 1) if name == 'waitForAny' else (1.5, 3)
with assert_takes_time(*tts):
fn(
partial('fast', os.version),
partial('s1', os.sleep, 2),
partial('s2', os.sleep, 2),
)
assert tags == {'fast', 's1', 's2'}
print(name, 'fast OK')
def breaks_fast(etype):
os.sleep(0.5)
raise etype
os.sleep(0.5)
raise etype
def breaks_slow(etype):
os.sleep(3)
raise etype
os.sleep(3)
raise etype
tags.clear()
with assert_takes_time(0, 1):
parallel.waitForAny(
partial('fast', os.version),
partial('bomb', breaks_slow, IndexError),
)
parallel.waitForAny(
partial('fast', os.version),
partial('bomb', breaks_slow, IndexError),
)
assert tags == {'fast', 'bomb'}
print('waitForAny fast success OK')
tags.clear()
with assert_takes_time(2.5, 3.8):
with assert_raises(IndexError):
parallel.waitForAll(
partial('fast', os.version),
partial('bomb', breaks_slow, IndexError),
)
with assert_raises(IndexError):
parallel.waitForAll(
partial('fast', os.version),
partial('bomb', breaks_slow, IndexError),
)
assert tags == {'fast', 'bomb'}
print('waitForAll waits for bomb OK')
for name, fn in all_parallels:
tags.clear()
with assert_takes_time(0.4, 1.2):
with assert_raises(ValueError):
fn(
partial('v', breaks_fast, ValueError),
partial('s', os.sleep, 2),
partial('i', breaks_slow, IndexError),
)
os.sleep(4)
assert tags == {'v', 's', 'i'}
print(name + ' handles error OK')
tags.clear()
with assert_takes_time(0.4, 1.2):
with assert_raises(ValueError):
fn(
partial('v', breaks_fast, ValueError),
partial('s', os.sleep, 2),
partial('i', breaks_slow, IndexError),
)
os.sleep(4)
assert tags == {'v', 's', 'i'}
print(name + ' handles error OK')
for name, fn in all_parallels:
tags.clear()
with assert_takes_time(1.5, 3):
fn(
partial('1_s', os.sleep, 2),
partial(
'1_p',
fn,
partial('2_s', os.sleep, 2),
partial(
'2_p',
fn,
partial('3_s', os.sleep, 2),
),
),
)
assert tags == {'1_s', '1_p', '2_s', '2_p', '3_s'}
print('Nested', name, 'OK')
tags.clear()
with assert_takes_time(1.5, 3):
fn(
partial('1_s', os.sleep, 2),
partial(
'1_p',
fn,
partial('2_s', os.sleep, 2),
partial(
'2_p',
fn,
partial('3_s', os.sleep, 2),
),
),
)
assert tags == {'1_s', '1_p', '2_s', '2_p', '3_s'}
print('Nested', name, 'OK')
def nested_err():
parallel.waitForAll(
partial('n_v', breaks_fast, ValueError),
partial('n_s', os.sleep, 2),
partial('n_i', breaks_slow, IndexError),
)
parallel.waitForAll(
partial('n_v', breaks_fast, ValueError),
partial('n_s', os.sleep, 2),
partial('n_i', breaks_slow, IndexError),
)
tags.clear()
with assert_takes_time(0.4, 1.2):
with assert_raises(ValueError):
parallel.waitForAll(
nested_err,
partial('s', os.sleep, 2),
partial('i', breaks_slow, IndexError),
)
with assert_raises(ValueError):
parallel.waitForAll(
nested_err,
partial('s', os.sleep, 2),
partial('i', breaks_slow, IndexError),
)
assert tags == {'s', 'i', 'n_v', 'n_s', 'n_i'}
print('Nested errors OK')
print('Test finished successfully')
print('Test finished successfully')

View file

@ -37,4 +37,4 @@ assert d.isDiskPresent() is False
print('Remove disk drive')
print('Test finished successfully')
print('Test finished successfully')

View file

@ -25,7 +25,7 @@ assert m.runCommand() is None
assert m.setCommand('') is None
assert m.getCommand() == ''
with _lib.assert_raises(LuaException):
m.runCommand()
m.runCommand()
print('You must have seen chat message')
print('Test finished successfully')
print('Test finished successfully')

View file

@ -2,4 +2,4 @@ from cc import import_file
_lib = import_file('_lib.py', __file__)
_lib._computer_peri('another computer', 'computer')
_lib._computer_peri('another computer', 'computer')

View file

@ -60,9 +60,9 @@ assert label != 'label'
print(f'Label is {label}')
assert d.getDiskLabel() == label
with _lib.assert_raises(LuaException):
d.setDiskLabel('label')
d.setDiskLabel('label')
with _lib.assert_raises(LuaException):
d.setDiskLabel(None)
d.setDiskLabel(None)
# no effect
assert d.getDiskLabel() == label
@ -73,4 +73,4 @@ _lib.step('Audio must be playing now')
assert d.stopAudio() is None
assert d.ejectDisk() is None
print('Test finished successfully')
print('Test finished successfully')

View file

@ -8,10 +8,10 @@ _lib = import_file('_lib.py', __file__)
side = 'back'
_lib.step(
f'Attach modem to {side} side of computer\n'
f'Place another computer with similar modem at {side} side\n'
'In case of wired modems connect them\n'
'On another computer start py modem_server.py'
f'Attach modem to {side} side of computer\n'
f'Place another computer with similar modem at {side} side\n'
'In case of wired modems connect them\n'
'On another computer start py modem_server.py'
)
m = peripheral.wrap(side)
@ -22,25 +22,25 @@ messages = []
def _send():
for msg in [
1,
b'hi',
{b'data': 5},
b'stop',
]:
os.sleep(1)
m.transmit(remote_channel, local_channel, msg)
for msg in [
1,
b'hi',
{b'data': 5},
b'stop',
]:
os.sleep(1)
m.transmit(remote_channel, local_channel, msg)
def _recv():
assert m.isOpen(local_channel) is False
for msg in m.receive(local_channel):
assert m.isOpen(local_channel) is True
assert msg.reply_channel == remote_channel
assert msg.distance > 0
messages.append(msg.content)
if len(messages) == 3:
break
assert m.isOpen(local_channel) is False
for msg in m.receive(local_channel):
assert m.isOpen(local_channel) is True
assert msg.reply_channel == remote_channel
assert msg.distance > 0
messages.append(msg.content)
if len(messages) == 3:
break
assert m.closeAll() is None
@ -51,4 +51,4 @@ assert m.isOpen(local_channel) is False
assert m.closeAll() is None
assert isinstance(m.isWireless(), bool)
print('Test finished successfully')
print('Test finished successfully')

View file

@ -8,8 +8,8 @@ _lib = import_file('_lib.py', __file__)
side = 'left'
_lib.step(
'Use advanced computer and monitor for colors\n'
f'Place single block monitor on {side} side of computer',
'Use advanced computer and monitor for colors\n'
f'Place single block monitor on {side} side of computer',
)
m = peripheral.wrap(side)
@ -50,25 +50,25 @@ _lib.step('You must have seen word Alpha with blinking cursor')
assert m.clear() is None
assert m.setCursorBlink(False) is None
for offs, (tc, bc) in enumerate((
(colors.lime, colors.green),
(colors.yellow, colors.brown),
(colors.red, colors.orange),
(colors.lime, colors.green),
(colors.yellow, colors.brown),
(colors.red, colors.orange),
), start=1):
assert m.setTextColor(tc) is None
assert m.getTextColor() == tc
assert m.setBackgroundColor(bc) is None
assert m.getBackgroundColor() == bc
assert m.setCursorPos(offs, offs) is None
assert m.getCursorPos() == (offs, offs)
assert m.write('text') is None
assert m.setTextColor(tc) is None
assert m.getTextColor() == tc
assert m.setBackgroundColor(bc) is None
assert m.getBackgroundColor() == bc
assert m.setCursorPos(offs, offs) is None
assert m.getCursorPos() == (offs, offs)
assert m.write('text') is None
assert m.setBackgroundColor(colors.black) is None
os.sleep(1)
for i in range(2):
assert m.scroll(-1) is None
os.sleep(0.5)
assert m.scroll(-1) is None
os.sleep(0.5)
for i in range(2):
assert m.scroll(1) is None
os.sleep(0.5)
assert m.scroll(1) is None
os.sleep(0.5)
_lib.step('You must have seen three texts with different colors scrolling')
@ -76,12 +76,12 @@ assert m.setTextColor(colors.white) is None
assert m.setBackgroundColor(colors.black) is None
assert m.clear() is None
for i in range(1, 5):
assert m.setCursorPos(1, i) is None
assert m.write((str(i) + ' ') * 4) is None
assert m.setCursorPos(1, i) is None
assert m.write((str(i) + ' ') * 4) is None
os.sleep(2)
for i in range(2, 5, 2):
assert m.setCursorPos(1, i) is None
assert m.clearLine() is None
assert m.setCursorPos(1, i) is None
assert m.clearLine() is None
_lib.step('You must have seen some lines disappearing')
@ -89,15 +89,15 @@ assert m.setBackgroundColor(colors.black) is None
assert m.clear() is None
assert m.setCursorPos(1, 1) is None
assert m.blit(
'rainbow',
b'e14d3ba',
b'fffffff',
'rainbow',
b'e14d3ba',
b'fffffff',
) is None
assert m.setCursorPos(1, 2) is None
assert m.blit(
'rainbow',
b'0000000',
b'e14d3ba',
'rainbow',
b'0000000',
b'e14d3ba',
) is None
_lib.step('You must have seen per-letter colored text')
@ -118,27 +118,27 @@ assert m.setTextScale(1) is None
assert m.setBackgroundColor(colors.white) is None
assert m.clear() is None
for i, color in enumerate(colors.iter_colors()):
m.setPaletteColor(color, i / 15, 0, 0)
m.setPaletteColor(color, i / 15, 0, 0)
assert m.setCursorPos(1, 1) is None
assert m.blit(
' redtex',
b'0123456',
b'0000000',
' redtex',
b'0123456',
b'0000000',
) is None
assert m.setCursorPos(1, 2) is None
assert m.blit(
'tappear',
b'789abcd',
b'0000000',
'tappear',
b'789abcd',
b'0000000',
) is None
assert m.setCursorPos(1, 3) is None
assert m.blit(
's!',
b'ef',
b'00',
's!',
b'ef',
b'00',
) is None
_lib.step('You must have seen different shades of red made using palettes')
print('Remove monitor')
print('Test finished successfully')
print('Test finished successfully')

View file

@ -21,17 +21,17 @@ assert m.getInkLevel() == 0
assert m.newPage() is False
# page not started
with assert_raises(LuaException):
m.endPage()
m.endPage()
with assert_raises(LuaException):
m.write('test')
m.write('test')
with assert_raises(LuaException):
m.setCursorPos(2, 2)
m.setCursorPos(2, 2)
with assert_raises(LuaException):
m.getCursorPos()
m.getCursorPos()
with assert_raises(LuaException):
m.getPageSize()
m.getPageSize()
with assert_raises(LuaException):
m.setPageTitle('title')
m.setPageTitle('title')
_lib.step('Put paper into printer')
paper_level = m.getPaperLevel()
@ -56,39 +56,39 @@ assert m.getPageSize() == (25, 21)
def row(n=1):
_, r = m.getCursorPos()
m.setCursorPos(1, r + n)
_, r = m.getCursorPos()
m.setCursorPos(1, r + n)
def split_text(text, max_width=25):
for i in range(0, len(text), max_width):
yield text[i:i + max_width]
for i in range(0, len(text), max_width):
yield text[i:i + max_width]
def split_by_words(text, max_width=25):
stack = []
stack_len = 0
for word in text.split(' '):
assert len(word) <= max_width
with_word = len(word) if stack_len == 0 else stack_len + 1 + len(word)
if with_word > max_width:
yield ' '.join(stack)
stack.clear()
stack_len = 0
else:
stack.append(word)
stack_len = with_word
if stack:
yield ' '.join(stack)
stack = []
stack_len = 0
for word in text.split(' '):
assert len(word) <= max_width
with_word = len(word) if stack_len == 0 else stack_len + 1 + len(word)
if with_word > max_width:
yield ' '.join(stack)
stack.clear()
stack_len = 0
else:
stack.append(word)
stack_len = with_word
if stack:
yield ' '.join(stack)
def multiline_write(text):
_, r = m.getCursorPos()
for pt in split_by_words(text):
assert m.setCursorPos(1, r) is None
assert m.write(pt) is None
r += 1
assert m.setCursorPos(1, r) is None
_, r = m.getCursorPos()
for pt in split_by_words(text):
assert m.setCursorPos(1, r) is None
assert m.write(pt) is None
r += 1
assert m.setCursorPos(1, r) is None
assert m.write('Green bottles'.center(25)) is None
@ -96,13 +96,13 @@ row(2)
x = 2
while x > 0:
multiline_write(f'{x} green bottles hanging on the wall')
multiline_write(f'{x} green bottles hanging on the wall')
multiline_write('if one green bottle accidently falls')
x -= 1
multiline_write(f'there will be {x} hanging on the wall')
row()
multiline_write(f'{x} green bottles hanging on the wall')
multiline_write(f'{x} green bottles hanging on the wall')
multiline_write('if one green bottle accidently falls')
x -= 1
multiline_write(f'there will be {x} hanging on the wall')
row()
assert m.endPage() is True
print('Test finished successfully')
print('Test finished successfully')

View file

@ -22,9 +22,9 @@ assert isinstance(names, list)
assert len(names) > 0
speaker = []
for n in names:
assert isinstance(n, str)
if n.startswith('speaker_'):
speaker.append(n)
assert isinstance(n, str)
if n.startswith('speaker_'):
speaker.append(n)
assert len(speaker) == 1
speaker = speaker[0]
@ -40,4 +40,4 @@ s = m.wrapRemote(speaker)
assert s.playSound('minecraft:entity.player.levelup') is True
print('You must have heard levelup sound')
print('Test finished successfully')
print('Test finished successfully')

View file

@ -17,18 +17,18 @@ tbl = _lib.get_object_table(f'peripheral.wrap("{side}")')
assert _lib.get_class_table(CCSpeaker) == tbl
for _ in range(48):
assert m.playNote(
random.choice([
'bass', 'basedrum', 'bell', 'chime', 'flute', 'guitar', 'hat',
'snare', 'xylophone', 'iron_xylophone', 'pling', 'banjo',
'bit', 'didgeridoo', 'cow_bell',
]),
3,
random.randint(0, 24)
) is True
os.sleep(0.2)
assert m.playNote(
random.choice([
'bass', 'basedrum', 'bell', 'chime', 'flute', 'guitar', 'hat',
'snare', 'xylophone', 'iron_xylophone', 'pling', 'banjo',
'bit', 'didgeridoo', 'cow_bell',
]),
3,
random.randint(0, 24)
) is True
os.sleep(0.2)
assert m.playSound('minecraft:entity.player.levelup') is True
print('You must have heard notes and sounds')
print('Test finished successfully')
print('Test finished successfully')

View file

@ -2,4 +2,4 @@ from cc import import_file
_lib = import_file('_lib.py', __file__)
_lib._computer_peri('turtle', 'turtle')
_lib._computer_peri('turtle', 'turtle')

View file

@ -11,9 +11,9 @@ assert _lib.get_class_table(pocket) == tbl
_lib.step('Clean inventory from any pocket upgrades')
with _lib.assert_raises(LuaException):
pocket.equipBack()
pocket.equipBack()
with _lib.assert_raises(LuaException):
pocket.unequipBack()
pocket.unequipBack()
assert peripheral.isPresent('back') is False
_lib.step('Put any pocket upgrade to inventory')
@ -24,4 +24,4 @@ assert peripheral.isPresent('back') is True
assert pocket.unequipBack() is None
assert peripheral.isPresent('back') is False
print('Test finished successfully')
print('Test finished successfully')

View file

@ -2,4 +2,4 @@ from cc import os
assert os.reboot() is None
print('Test finished successfully')
print('Test finished successfully')

View file

@ -7,10 +7,10 @@ side = 'left'
_lib.step(f'Attach 3x3 color monitor to {side} side of computer')
with term.redirect(peripheral.get_term_target(side)):
term.setBackgroundColor(colors.green)
term.setTextColor(colors.white)
term.clear()
term.setCursorPos(1, 1)
print('Redirected to monitor')
term.setBackgroundColor(colors.green)
term.setTextColor(colors.white)
term.clear()
term.setCursorPos(1, 1)
print('Redirected to monitor')
print('Test finished successfully')
print('Test finished successfully')

View file

@ -11,16 +11,16 @@ mod = peripheral.wrap(side)
_lib.step('Connect remote monitor using wires, activate its modem')
for name in mod.getNamesRemote():
if mod.getTypeRemote(name) == 'monitor':
break
if mod.getTypeRemote(name) == 'monitor':
break
else:
assert False
assert False
with term.redirect(peripheral.get_term_target(name)):
term.setBackgroundColor(colors.blue)
term.setTextColor(colors.white)
term.clear()
term.setCursorPos(1, 1)
print('Redirected to monitor')
term.setBackgroundColor(colors.blue)
term.setTextColor(colors.white)
term.clear()
term.setCursorPos(1, 1)
print('Redirected to monitor')
print('Test finished successfully')
print('Test finished successfully')

View file

@ -5,26 +5,26 @@ from cc import colors, term, window
w, h = term.getSize()
with ExitStack() as stack:
left = stack.enter_context(window.create(
term.get_current_target(),
1, 1, w // 2, h, True,
))
right = stack.enter_context(window.create(
term.get_current_target(),
w // 2 + 1, 1, w // 2, h, True,
))
with term.redirect(left.get_term_target()):
term.setBackgroundColor(colors.green)
term.setTextColor(colors.white)
term.clear()
term.setCursorPos(1, h // 2)
print('Left part')
with term.redirect(right.get_term_target()):
term.setBackgroundColor(colors.red)
term.setTextColor(colors.yellow)
term.clear()
term.setCursorPos(1, h // 2)
print('Right part')
print('Default terminal restored')
left = stack.enter_context(window.create(
term.get_current_target(),
1, 1, w // 2, h, True,
))
right = stack.enter_context(window.create(
term.get_current_target(),
w // 2 + 1, 1, w // 2, h, True,
))
with term.redirect(left.get_term_target()):
term.setBackgroundColor(colors.green)
term.setTextColor(colors.white)
term.clear()
term.setCursorPos(1, h // 2)
print('Left part')
with term.redirect(right.get_term_target()):
term.setBackgroundColor(colors.red)
term.setTextColor(colors.yellow)
term.clear()
term.setCursorPos(1, h // 2)
print('Right part')
print('Default terminal restored')
print('Test finished successfully')
print('Test finished successfully')

View file

@ -18,19 +18,19 @@ assert rednet.isOpen(side) is False
assert rednet.isOpen() is False
with assert_raises(LuaException):
rednet.close('doesnotexist')
rednet.close('doesnotexist')
assert rednet.close(side) is None
with assert_raises(LuaException):
rednet.open('doesnotexist')
rednet.open('doesnotexist')
assert rednet.open(side) is None
assert rednet.isOpen(side) is True
with assert_raises(LuaException):
# disallowed hostname
rednet.host('helloproto', 'localhost')
# disallowed hostname
rednet.host('helloproto', 'localhost')
assert rednet.host('helloproto', 'alpha') is None
cid = os.getComputerID()
@ -49,11 +49,11 @@ assert rednet.receive(timeout=1) is None
def _send():
assert rednet.send(cid, b'message') is True
assert rednet.send(cid, b'message') is True
def _recv():
assert rednet.receive(timeout=1) == (cid, b'message', None)
assert rednet.receive(timeout=1) == (cid, b'message', None)
parallel.waitForAll(_send, _recv)
@ -61,4 +61,4 @@ parallel.waitForAll(_send, _recv)
assert rednet.close() is None
assert rednet.isOpen(side) is False
print('Test finished successfully')
print('Test finished successfully')

View file

@ -52,4 +52,4 @@ assert redstone.setOutput(side, False) is None
print('Piston must have been activated\nRemove piston')
print('Test finished successfully')
print('Test finished successfully')

View file

@ -18,37 +18,37 @@ assert settings.define('test.c', type='string') is None
assert settings.define('test.d', default=42) is None
assert settings.getDetails('test.a') == {
'changed': False,
'changed': False,
}
assert settings.getDetails('test.b') == {
'changed': False,
'description': 'b',
'changed': False,
'description': 'b',
}
assert settings.getDetails('test.c') == {
'changed': False,
'type': 'string',
'changed': False,
'type': 'string',
}
assert settings.getDetails('test.d') == {
'changed': False,
'default': 42,
'value': 42,
'changed': False,
'default': 42,
'value': 42,
}
# redefining
assert settings.define('test.a', type='number', default=11) is None
assert settings.getDetails('test.a') == {
'changed': False,
'type': 'number',
'default': 11,
'value': 11,
'changed': False,
'type': 'number',
'default': 11,
'value': 11,
}
assert settings.get('test.a') == 11
assert settings.set('test.a', 12) is None
assert settings.get('test.a') == 12
with assert_raises(LuaException):
settings.set('test.a', b'text')
settings.set('test.a', b'text')
assert settings.get('test.a') == 12
assert settings.unset('test.a') is None
assert settings.get('test.a') == 11
@ -65,15 +65,15 @@ assert settings.undefine('test.d') is None
assert 'test.c' in settings.getNames()
assert settings.get('test.c') == b'hello'
assert settings.getDetails('test.c') == {
'changed': True,
'value': b'hello',
'changed': True,
'value': b'hello',
}
assert settings.unset('test.c') is None
assert settings.get('test.c') is None
assert settings.getDetails('test.c') == {
'changed': False,
'changed': False,
}
assert {'test.a', 'test.b', 'test.c', 'test.d'} & set(settings.getNames()) == set()
@ -98,4 +98,4 @@ assert settings.load('sfile') is True
fs.delete('sfile')
print('Test finished successfully')
print('Test finished successfully')

View file

@ -58,4 +58,4 @@ _lib.step('Computer will shutdown after test due to shell.exit')
assert shell.exit() is None
print('Test finished successfully')
print('Test finished successfully')

View file

@ -2,4 +2,4 @@ from cc import os
assert os.shutdown() is None
print('Test finished successfully')
print('Test finished successfully')

View file

@ -25,9 +25,9 @@ del tbl['function']['setTextColour']
assert _lib.get_class_table(TermMixin) == tbl
_lib.step(
'Detach all monitors\n'
'Use advanced computer for colors\n'
'Screen will be cleared'
'Detach all monitors\n'
'Use advanced computer for colors\n'
'Screen will be cleared'
)
assert term.getSize() == (51, 19)
@ -47,36 +47,36 @@ _lib.term_step('You must have seen word Alpha with blinking cursor')
assert term.clear() is None
for offs, (tc, bc) in enumerate((
(colors.lime, colors.green),
(colors.yellow, colors.brown),
(colors.red, colors.orange),
(colors.lime, colors.green),
(colors.yellow, colors.brown),
(colors.red, colors.orange),
), start=1):
assert term.setTextColor(tc) is None
assert term.getTextColor() == tc
assert term.setBackgroundColor(bc) is None
assert term.getBackgroundColor() == bc
assert term.setCursorPos(offs * 2, offs) is None
assert term.getCursorPos() == (offs * 2, offs)
assert term.write('text with colors') is None
assert term.setTextColor(tc) is None
assert term.getTextColor() == tc
assert term.setBackgroundColor(bc) is None
assert term.getBackgroundColor() == bc
assert term.setCursorPos(offs * 2, offs) is None
assert term.getCursorPos() == (offs * 2, offs)
assert term.write('text with colors') is None
assert term.setBackgroundColor(colors.black) is None
os.sleep(1)
for i in range(3):
assert term.scroll(-2) is None
os.sleep(0.5)
assert term.scroll(-2) is None
os.sleep(0.5)
for i in range(6):
assert term.scroll(1) is None
os.sleep(0.25)
assert term.scroll(1) is None
os.sleep(0.25)
_lib.term_step('You must have seen three texts with different colors scrolling')
assert term.clear() is None
for i in range(1, 10):
assert term.setCursorPos(1, i) is None
assert term.write((str(i) + ' ') * 10) is None
assert term.setCursorPos(1, i) is None
assert term.write((str(i) + ' ') * 10) is None
os.sleep(2)
for i in range(2, 10, 2):
assert term.setCursorPos(1, i) is None
assert term.clearLine() is None
assert term.setCursorPos(1, i) is None
assert term.clearLine() is None
os.sleep(2)
_lib.term_step('You must have seen some lines disappearing')
@ -84,9 +84,9 @@ _lib.term_step('You must have seen some lines disappearing')
assert term.clear() is None
assert term.setCursorPos(1, 1) is None
assert term.blit(
'rainbowrainbow',
b'e14d3ba0000000',
b'fffffffe14d3ba',
'rainbowrainbow',
b'e14d3ba0000000',
b'fffffffe14d3ba',
) is None
os.sleep(3)
@ -96,14 +96,14 @@ assert term.setBackgroundColor(colors.white) is None
assert term.clear() is None
assert term.setCursorPos(1, 1) is None
for i, color in enumerate(colors.iter_colors()):
term.setPaletteColor(color, i / 15, 0, 0)
term.setPaletteColor(color, i / 15, 0, 0)
assert term.blit(
' redtextappears!',
b'0123456789abcdef',
b'0000000000000000',
' redtextappears!',
b'0123456789abcdef',
b'0000000000000000',
) is None
os.sleep(3)
_lib.term_step('You must have seen different shades of red made using palettes')
print('Test finished successfully')
print('Test finished successfully')

View file

@ -10,25 +10,25 @@ assert textutils.formatTime(0) == '0:00 AM'
assert textutils.formatTime(0, True) == '0:00'
table = [
colors.red,
['Planet', 'Distance', 'Mass'],
colors.gray,
['Mercury', '0.387', '0.055'],
colors.lightGray,
['Venus', '0.723', '0.815'],
colors.green,
['Earth', '1.000', '1.000'],
colors.red,
['Mars', '1.524', '0.107'],
colors.orange,
['Jupiter', '5.203', '318'],
colors.yellow,
['Saturn', '9.537', '95'],
colors.cyan,
['Uranus', '19.191', '14.5'],
colors.blue,
['Neptune', '30.069', '17'],
colors.white,
colors.red,
['Planet', 'Distance', 'Mass'],
colors.gray,
['Mercury', '0.387', '0.055'],
colors.lightGray,
['Venus', '0.723', '0.815'],
colors.green,
['Earth', '1.000', '1.000'],
colors.red,
['Mars', '1.524', '0.107'],
colors.orange,
['Jupiter', '5.203', '318'],
colors.yellow,
['Saturn', '9.537', '95'],
colors.cyan,
['Uranus', '19.191', '14.5'],
colors.blue,
['Neptune', '30.069', '17'],
colors.white,
]
assert textutils.tabulate(*table) is None
@ -47,6 +47,6 @@ assert lines > 0
assert textutils.pagedTabulate(*table[:-1], *table[2:-1], *table[2:]) is None
assert textutils.complete('co', ['command', 'row', 'column']) == [
'mmand', 'lumn']
'mmand', 'lumn']
print('Test finished successfully')
print('Test finished successfully')

View file

@ -21,7 +21,7 @@ assert 0 <= flevel <= flimit
assert turtle.select(2) is None
assert turtle.getSelectedSlot() == 2
with assert_raises(LuaException):
turtle.select(0)
turtle.select(0)
assert turtle.select(1) is None
assert turtle.getSelectedSlot() == 1
@ -31,12 +31,12 @@ assert turtle.getItemCount() == 3
assert turtle.getItemCount(1) == 3
assert turtle.getItemDetail() == {
b'count': 3, # TODO: binary output
b'name': b'minecraft:coal',
b'count': 3, # TODO: binary output
b'name': b'minecraft:coal',
}
assert turtle.getItemDetail(1) == {
b'count': 3,
b'name': b'minecraft:coal',
b'count': 3,
b'name': b'minecraft:coal',
}
assert turtle.getItemSpace() == 61
@ -54,9 +54,9 @@ assert turtle.getFuelLevel() > flevel
assert turtle.getItemCount() == 0
with assert_raises(LuaException):
turtle.refuel(1)
turtle.refuel(1)
with assert_raises(LuaException):
turtle.refuel()
turtle.refuel()
step('Remove blocks in front/below/above turtle')
@ -75,12 +75,12 @@ assert turtle.detectUp() is True
assert turtle.detectDown() is True
for c in [
turtle.inspect(),
turtle.inspectUp(),
turtle.inspectDown()
turtle.inspect(),
turtle.inspectUp(),
turtle.inspectDown()
]:
assert isinstance(c, dict)
assert c[b'name'] == b'minecraft:cobblestone'
assert isinstance(c, dict)
assert c[b'name'] == b'minecraft:cobblestone'
assert turtle.select(1) is None
assert turtle.getItemCount() == 0
@ -91,17 +91,17 @@ assert turtle.getItemCount() == 0
assert turtle.equipRight() is None
if (
turtle.getItemCount(1) != 0
or turtle.getItemCount(2) != 0
turtle.getItemCount(1) != 0
or turtle.getItemCount(2) != 0
):
step('Remove all items from slots 1 and 2')
step('Remove all items from slots 1 and 2')
assert turtle.select(1) is None
if turtle.getItemDetail(1) != {
b'count': 1,
b'name': b'minecraft:diamond_pickaxe',
b'count': 1,
b'name': b'minecraft:diamond_pickaxe',
}:
step('Put fresh diamond pickaxe at slot 1')
step('Put fresh diamond pickaxe at slot 1')
assert turtle.equipLeft() is None
@ -127,7 +127,7 @@ assert turtle.placeUp() is True
assert turtle.placeUp() is False
assert turtle.placeDown() is True
with assert_raises(LuaException, 'No items to place'):
turtle.placeDown()
turtle.placeDown()
step('Put 3 cobblestone blocks to slot 1')
@ -173,9 +173,9 @@ assert turtle.getItemCount() == 0
assert turtle.drop() is False
step(
'Collect dropped cobblestone\n'
'Drop stack of sticks right in front of the turtle\n'
'Its better to build 1-block room then throw sticks there',
'Collect dropped cobblestone\n'
'Drop stack of sticks right in front of the turtle\n'
'Its better to build 1-block room then throw sticks there',
)
assert turtle.suck(1) is True
@ -187,9 +187,9 @@ assert turtle.drop() is True
assert turtle.getItemCount() == 0
step(
'Collect dropped sticks\n'
'Drop stack of sticks right below the turtle\n'
'Its better to build 1-block room then throw sticks there',
'Collect dropped sticks\n'
'Drop stack of sticks right below the turtle\n'
'Its better to build 1-block room then throw sticks there',
)
assert turtle.suckDown(1) is True
@ -201,9 +201,9 @@ assert turtle.dropDown() is True
assert turtle.getItemCount() == 0
step(
'Collect dropped sticks\n'
'Drop stack of sticks right above the turtle\n'
'Its better to build 1-block room then throw sticks there',
'Collect dropped sticks\n'
'Drop stack of sticks right above the turtle\n'
'Its better to build 1-block room then throw sticks there',
)
assert turtle.suckUp(1) is True
@ -216,12 +216,12 @@ assert turtle.getItemCount() == 0
def craft1():
return turtle.craft()
return turtle.craft()
def craft2():
c = peripheral.wrap('right')
return c.craft()
c = peripheral.wrap('right')
return c.craft()
step('Put crafting table into slot 1')
@ -229,20 +229,20 @@ assert turtle.select(1) is None
assert turtle.equipRight() is None
for craft_fn in craft1, craft2:
step(
'Clean inventory of turtle\n'
'Put 8 cobblestones into slot 1',
)
step(
'Clean inventory of turtle\n'
'Put 8 cobblestones into slot 1',
)
assert turtle.select(1) is None
assert craft_fn() is False
for idx in [2, 3, 5, 7, 9, 10, 11]:
assert turtle.transferTo(idx, 1)
assert craft_fn() is True
assert craft_fn() is False
assert turtle.getItemDetail() == {
b'count': 1,
b'name': b'minecraft:furnace',
}
assert turtle.select(1) is None
assert craft_fn() is False
for idx in [2, 3, 5, 7, 9, 10, 11]:
assert turtle.transferTo(idx, 1)
assert craft_fn() is True
assert craft_fn() is False
assert turtle.getItemDetail() == {
b'count': 1,
b'name': b'minecraft:furnace',
}
print('Test finished successfully')
print('Test finished successfully')

View file

@ -4,9 +4,9 @@ _lib = import_file('_lib.py', __file__)
_lib.step(
'NOTE: this test is unreliable\n'
'Build 1x1x1 stone cage in front of turtle\n'
'Spawn here a chicken',
'NOTE: this test is unreliable\n'
'Build 1x1x1 stone cage in front of turtle\n'
'Spawn here a chicken',
)
assert turtle.attack() is True
@ -14,8 +14,8 @@ assert turtle.attack() is True
assert turtle.attack() is False
_lib.step(
'Build 1x1x1 stone cage below turtle\n'
'Spawn here a chicken',
'Build 1x1x1 stone cage below turtle\n'
'Spawn here a chicken',
)
assert turtle.attackDown() is True
@ -23,12 +23,12 @@ assert turtle.attackDown() is True
assert turtle.attackDown() is False
_lib.step(
'Build 1x1x1 stone cage above turtle\n'
'Spawn here a chicken',
'Build 1x1x1 stone cage above turtle\n'
'Spawn here a chicken',
)
assert turtle.attackUp() is True
assert turtle.attackUp() is True
assert turtle.attackUp() is False
print('Test finished successfully')
print('Test finished successfully')

View file

@ -2,35 +2,35 @@ from cc import colors, term, os, window
with window.create(
term.get_current_target(),
15, 5, 5, 5, False,
term.get_current_target(),
15, 5, 5, 5, False,
) as win:
assert win.getPosition() == (15, 5)
assert win.getSize() == (5, 5)
assert win.getPosition() == (15, 5)
assert win.getSize() == (5, 5)
win.setBackgroundColor(colors.red)
win.clear()
win.setVisible(True)
win.setBackgroundColor(colors.red)
win.clear()
win.setVisible(True)
os.sleep(1)
os.sleep(1)
win.setVisible(False)
win.setCursorPos(1, 1)
win.setTextColor(colors.yellow)
win.write('*********')
win.setVisible(True)
win.setVisible(False)
win.setCursorPos(1, 1)
win.setTextColor(colors.yellow)
win.write('*********')
win.setVisible(True)
os.sleep(1)
os.sleep(1)
term.clear()
term.clear()
os.sleep(1)
os.sleep(1)
win.redraw()
assert win.getLine(1) == ('*****', b'44444', b'eeeee')
win.redraw()
assert win.getLine(1) == ('*****', b'44444', b'eeeee')
# draws immediately
win.reposition(21, 5)
win.reposition(27, 5)
# draws immediately
win.reposition(21, 5)
win.reposition(27, 5)
print('Test finished successfully')
print('Test finished successfully')

View file

@ -3,6 +3,6 @@ from cc import os
timer_id = os.startTimer(2)
for e in os.captureEvent('timer'):
if e[0] == timer_id:
print('Timer reached')
break
if e[0] == timer_id:
print('Timer reached')
break