convert spaces to tabs
This commit is contained in:
parent
d1145c5995
commit
d082438777
|
@ -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]
|
|
@ -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))
|
|
@ -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])
|
|
@ -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
|
|
@ -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()
|
|
@ -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)
|
|
@ -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()
|
|
@ -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)
|
|
@ -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
|
|
@ -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()
|
|
@ -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()
|
|
@ -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
|
|
@ -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))
|
|
@ -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()
|
|
@ -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()
|
|
@ -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
|
|
@ -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()
|
|
@ -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()
|
|
@ -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()
|
|
@ -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()
|
|
@ -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)
|
|
@ -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()
|
|
@ -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()
|
|
@ -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()
|
|
@ -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()
|
|
@ -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
|
|
@ -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()')
|
|
@ -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
|
|
@ -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()
|
|
@ -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)
|
174
examples/_lib.py
174
examples/_lib.py
|
@ -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')
|
|
@ -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))
|
|
@ -1 +1 @@
|
|||
raise ValueError
|
||||
raise ValueError
|
|
@ -1 +1 @@
|
|||
print('Hello world!')
|
||||
print('Hello world!')
|
|
@ -2,4 +2,4 @@ from cc import os
|
|||
|
||||
print('ID', os.getComputerID())
|
||||
print('Label', os.getComputerLabel())
|
||||
print('Version', os.version())
|
||||
print('Version', os.version())
|
|
@ -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)
|
|
@ -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()
|
|
@ -1,2 +1,2 @@
|
|||
line = input()
|
||||
print(f'Entered line: {line}')
|
||||
print(f'Entered line: {line}')
|
|
@ -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')
|
|
@ -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')
|
|
@ -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')
|
|
@ -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')
|
|
@ -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')
|
|
@ -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')
|
|
@ -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')
|
|
@ -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')
|
|
@ -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')
|
|
@ -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')
|
|
@ -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')
|
|
@ -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')
|
|
@ -37,4 +37,4 @@ assert d.isDiskPresent() is False
|
|||
|
||||
print('Remove disk drive')
|
||||
|
||||
print('Test finished successfully')
|
||||
print('Test finished successfully')
|
|
@ -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')
|
|
@ -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')
|
|
@ -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')
|
|
@ -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')
|
|
@ -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')
|
|
@ -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')
|
|
@ -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')
|
|
@ -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')
|
|
@ -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')
|
|
@ -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')
|
|
@ -2,4 +2,4 @@ from cc import os
|
|||
|
||||
|
||||
assert os.reboot() is None
|
||||
print('Test finished successfully')
|
||||
print('Test finished successfully')
|
|
@ -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')
|
|
@ -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')
|
|
@ -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')
|
|
@ -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')
|
|
@ -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')
|
|
@ -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')
|
|
@ -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')
|
|
@ -2,4 +2,4 @@ from cc import os
|
|||
|
||||
|
||||
assert os.shutdown() is None
|
||||
print('Test finished successfully')
|
||||
print('Test finished successfully')
|
|
@ -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')
|
|
@ -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')
|
|
@ -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')
|
|
@ -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')
|
|
@ -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')
|
|
@ -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
|
Loading…
Reference in a new issue