easycoder 250826.2__py2.py3-none-any.whl → 251104.1__py2.py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- easycoder/__init__.py +1 -1
- easycoder/ec_classes.py +0 -4
- easycoder/ec_compiler.py +35 -8
- easycoder/ec_condition.py +1 -1
- easycoder/ec_core.py +112 -47
- easycoder/ec_handler.py +2 -2
- easycoder/ec_keyboard.py +13 -3
- easycoder/ec_program.py +6 -5
- easycoder/ec_pyside.py +189 -87
- {easycoder-250826.2.dist-info → easycoder-251104.1.dist-info}/METADATA +1 -1
- easycoder-251104.1.dist-info/RECORD +19 -0
- easycoder-250826.2.dist-info/RECORD +0 -19
- {easycoder-250826.2.dist-info → easycoder-251104.1.dist-info}/WHEEL +0 -0
- {easycoder-250826.2.dist-info → easycoder-251104.1.dist-info}/entry_points.txt +0 -0
- {easycoder-250826.2.dist-info → easycoder-251104.1.dist-info}/licenses/LICENSE +0 -0
easycoder/__init__.py
CHANGED
easycoder/ec_classes.py
CHANGED
|
@@ -16,7 +16,6 @@ class AssertionError:
|
|
|
16
16
|
def __init__(self, program, msg=None):
|
|
17
17
|
code = program.code[program.pc]
|
|
18
18
|
lino = code['lino']
|
|
19
|
-
script = program.script.lines[lino].strip()
|
|
20
19
|
message = f'Assertion Error in {program.name} at line {lino + 1}'
|
|
21
20
|
if msg != None:
|
|
22
21
|
message += f': {msg}'
|
|
@@ -58,8 +57,5 @@ class Token:
|
|
|
58
57
|
self.lino = lino
|
|
59
58
|
self.token = token
|
|
60
59
|
|
|
61
|
-
class Condition():
|
|
62
|
-
negate = False
|
|
63
|
-
|
|
64
60
|
class Object():
|
|
65
61
|
pass
|
easycoder/ec_compiler.py
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from .ec_classes import
|
|
1
|
+
from .ec_classes import FatalError
|
|
2
2
|
from .ec_value import Value
|
|
3
3
|
from .ec_condition import Condition
|
|
4
4
|
|
|
@@ -18,9 +18,11 @@ class Compiler:
|
|
|
18
18
|
self.debugCompile = False
|
|
19
19
|
self.valueTypes = {}
|
|
20
20
|
|
|
21
|
-
|
|
21
|
+
# Get the current code size. Used during compilation
|
|
22
|
+
def getCodeSize(self):
|
|
22
23
|
return len(self.program.code)
|
|
23
24
|
|
|
25
|
+
# Get the current index (the program counter)
|
|
24
26
|
def getIndex(self):
|
|
25
27
|
return self.index
|
|
26
28
|
|
|
@@ -39,6 +41,7 @@ class Compiler:
|
|
|
39
41
|
self.index += 1
|
|
40
42
|
return self.getToken()
|
|
41
43
|
|
|
44
|
+
# Peek ahead to see the next token without advancing the index
|
|
42
45
|
def peek(self):
|
|
43
46
|
try:
|
|
44
47
|
return self.tokens[self.index + 1].token
|
|
@@ -68,19 +71,23 @@ class Compiler:
|
|
|
68
71
|
self.index += 1
|
|
69
72
|
return self.condition.compileCondition()
|
|
70
73
|
|
|
74
|
+
# Test if the current token has a specified value
|
|
71
75
|
def tokenIs(self, value):
|
|
72
76
|
return self.getToken() == value
|
|
73
77
|
|
|
78
|
+
# Test if the next token has the specified value
|
|
74
79
|
def nextIs(self, value):
|
|
75
80
|
return self.nextToken() == value
|
|
76
81
|
|
|
82
|
+
# Get the command at a given pc in the code list
|
|
77
83
|
def getCommandAt(self, pc):
|
|
78
84
|
return self.program.code[pc]
|
|
79
85
|
|
|
80
86
|
# Add a command to the code list
|
|
81
|
-
def
|
|
87
|
+
def addCommand(self, command):
|
|
82
88
|
self.code.append(command)
|
|
83
89
|
|
|
90
|
+
# Test if the current token is a symbol
|
|
84
91
|
def isSymbol(self):
|
|
85
92
|
token = self.getToken()
|
|
86
93
|
try:
|
|
@@ -89,10 +96,12 @@ class Compiler:
|
|
|
89
96
|
return False
|
|
90
97
|
return True
|
|
91
98
|
|
|
99
|
+
# Test if the next token is a symbol
|
|
92
100
|
def nextIsSymbol(self):
|
|
93
101
|
self.next()
|
|
94
102
|
return self.isSymbol()
|
|
95
103
|
|
|
104
|
+
# Skip the next token if it matches the value given
|
|
96
105
|
def skip(self, token):
|
|
97
106
|
next = self.peek()
|
|
98
107
|
if type(token) == list:
|
|
@@ -102,21 +111,26 @@ class Compiler:
|
|
|
102
111
|
return
|
|
103
112
|
elif next == token: self.nextToken()
|
|
104
113
|
|
|
114
|
+
# Rewind to a given position in the code list
|
|
105
115
|
def rewindTo(self, index):
|
|
106
116
|
self.index = index
|
|
107
117
|
|
|
118
|
+
# Get source line number containing the current token
|
|
108
119
|
def getLino(self):
|
|
109
120
|
if self.index >= len(self.tokens):
|
|
110
121
|
return 0
|
|
111
122
|
return self.tokens[self.index].lino
|
|
112
123
|
|
|
124
|
+
# Issue a warning
|
|
113
125
|
def warning(self, message):
|
|
114
126
|
self.warnings.append(f'Warning at line {self.getLino() + 1} of {self.program.name}: {message}')
|
|
115
127
|
|
|
128
|
+
# Print all warnings
|
|
116
129
|
def showWarnings(self):
|
|
117
130
|
for warning in self.warnings:
|
|
118
131
|
print(warning)
|
|
119
132
|
|
|
133
|
+
# Get the symbol record for the current token (assumes it is a symbol name)
|
|
120
134
|
def getSymbolRecord(self):
|
|
121
135
|
token = self.getToken()
|
|
122
136
|
if not token in self.symbols:
|
|
@@ -128,18 +142,23 @@ class Compiler:
|
|
|
128
142
|
symbolRecord['used'] = True
|
|
129
143
|
return symbolRecord
|
|
130
144
|
|
|
145
|
+
# Add a value type
|
|
131
146
|
def addValueType(self):
|
|
132
147
|
self.valueTypes[self.getToken()] = True
|
|
133
148
|
|
|
149
|
+
# Test if a given value is in the value types list
|
|
134
150
|
def hasValue(self, type):
|
|
135
151
|
return type in self.valueTypes
|
|
136
152
|
|
|
153
|
+
# Compile a program label (a symbol ending with ':')
|
|
137
154
|
def compileLabel(self, command):
|
|
138
155
|
return self.compileSymbol(command, self.getToken())
|
|
139
156
|
|
|
157
|
+
# Compile a variable
|
|
140
158
|
def compileVariable(self, command, extra=None):
|
|
141
159
|
return self.compileSymbol(command, self.nextToken(), extra)
|
|
142
160
|
|
|
161
|
+
# Compile a symbol
|
|
143
162
|
def compileSymbol(self, command, name, extra=None):
|
|
144
163
|
try:
|
|
145
164
|
v = self.symbols[name]
|
|
@@ -148,7 +167,7 @@ class Compiler:
|
|
|
148
167
|
if v:
|
|
149
168
|
FatalError(self, f'Duplicate symbol name "{name}"')
|
|
150
169
|
return False
|
|
151
|
-
self.symbols[name] = self.
|
|
170
|
+
self.symbols[name] = self.getCodeSize()
|
|
152
171
|
command['program'] = self.program
|
|
153
172
|
command['type'] = 'symbol'
|
|
154
173
|
command['name'] = name
|
|
@@ -161,7 +180,7 @@ class Compiler:
|
|
|
161
180
|
command['locked'] = False
|
|
162
181
|
command['extra'] = extra
|
|
163
182
|
if 'keyword' in command: command['hasValue'] = self.hasValue(command['keyword'])
|
|
164
|
-
self.
|
|
183
|
+
self.addCommand(command)
|
|
165
184
|
return True
|
|
166
185
|
|
|
167
186
|
# Compile the current token
|
|
@@ -171,6 +190,10 @@ class Compiler:
|
|
|
171
190
|
# print(f'Compile {token}')
|
|
172
191
|
if not token:
|
|
173
192
|
return False
|
|
193
|
+
if len(self.code) == 0:
|
|
194
|
+
if self.program.parent == None and hasattr(self.program, 'usingGraphics'):
|
|
195
|
+
cmd = {'domain': 'graphics', 'keyword': 'init', 'debug': False}
|
|
196
|
+
self.code.append(cmd)
|
|
174
197
|
mark = self.getIndex()
|
|
175
198
|
for domain in self.program.getDomains():
|
|
176
199
|
handler = domain.keywordHandler(token)
|
|
@@ -195,7 +218,7 @@ class Compiler:
|
|
|
195
218
|
keyword = self.getToken()
|
|
196
219
|
if not keyword:
|
|
197
220
|
return False
|
|
198
|
-
|
|
221
|
+
# print(f'Compile keyword "{keyword}"')
|
|
199
222
|
if keyword.endswith(':'):
|
|
200
223
|
command = {}
|
|
201
224
|
command['domain'] = None
|
|
@@ -209,9 +232,8 @@ class Compiler:
|
|
|
209
232
|
self.index = index
|
|
210
233
|
while True:
|
|
211
234
|
token = self.tokens[self.index]
|
|
212
|
-
keyword = token.token
|
|
235
|
+
# keyword = token.token
|
|
213
236
|
if self.debugCompile: print(self.script.lines[token.lino])
|
|
214
|
-
# print(f'{keyword} - {line}')
|
|
215
237
|
# if keyword != 'else':
|
|
216
238
|
if self.compileOne() == True:
|
|
217
239
|
if self.index == len(self.tokens) - 1:
|
|
@@ -222,5 +244,10 @@ class Compiler:
|
|
|
222
244
|
else:
|
|
223
245
|
return False
|
|
224
246
|
|
|
247
|
+
# Compile fom the current location, stopping on any of a list of tokens
|
|
225
248
|
def compileFromHere(self, stopOn):
|
|
226
249
|
return self.compileFrom(self.getIndex(), stopOn)
|
|
250
|
+
|
|
251
|
+
# Compile from the start of the script
|
|
252
|
+
def compileFromStart(self):
|
|
253
|
+
return self.compileFrom(0, [])
|
easycoder/ec_condition.py
CHANGED
easycoder/ec_core.py
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import json, math, hashlib, threading, os, subprocess, time
|
|
2
2
|
import numbers, base64, binascii, random, requests, paramiko
|
|
3
|
+
from copy import deepcopy
|
|
3
4
|
from psutil import Process
|
|
4
5
|
from datetime import datetime
|
|
5
|
-
from .ec_classes import FatalError, RuntimeWarning, RuntimeError, AssertionError, NoValueError, NoValueRuntimeError,
|
|
6
|
+
from .ec_classes import FatalError, RuntimeWarning, RuntimeError, AssertionError, NoValueError, NoValueRuntimeError, Object
|
|
6
7
|
from .ec_handler import Handler
|
|
7
8
|
from .ec_timestamp import getTimestamp
|
|
8
9
|
|
|
@@ -30,13 +31,13 @@ class Core(Handler):
|
|
|
30
31
|
cmd['keyword'] = 'gotoPC'
|
|
31
32
|
cmd['goto'] = 0
|
|
32
33
|
cmd['debug'] = False
|
|
33
|
-
skip = self.
|
|
34
|
+
skip = self.getCodeSize()
|
|
34
35
|
self.add(cmd)
|
|
35
36
|
# Process the 'or'
|
|
36
|
-
self.getCommandAt(orHere)['or'] = self.
|
|
37
|
+
self.getCommandAt(orHere)['or'] = self.getCodeSize()
|
|
37
38
|
self.compileOne()
|
|
38
39
|
# Fixup the skip
|
|
39
|
-
self.getCommandAt(skip)['goto'] = self.
|
|
40
|
+
self.getCommandAt(skip)['goto'] = self.getCodeSize()
|
|
40
41
|
|
|
41
42
|
#############################################################################
|
|
42
43
|
# Keyword handlers
|
|
@@ -159,23 +160,25 @@ class Core(Handler):
|
|
|
159
160
|
else:
|
|
160
161
|
return self.compileFromHere(['end'])
|
|
161
162
|
|
|
162
|
-
# Clear (set false)
|
|
163
163
|
# clear {variable}
|
|
164
164
|
def k_clear(self, command):
|
|
165
165
|
if self.nextIsSymbol():
|
|
166
166
|
target = self.getSymbolRecord()
|
|
167
|
-
|
|
168
|
-
|
|
167
|
+
command['target'] = target['name']
|
|
168
|
+
if target['hasValue'] or target['keyword'] == 'ssh':
|
|
169
169
|
self.add(command)
|
|
170
170
|
return True
|
|
171
171
|
return False
|
|
172
172
|
|
|
173
173
|
def r_clear(self, command):
|
|
174
174
|
target = self.getVariable(command['target'])
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
175
|
+
if target['keyword'] == 'ssh':
|
|
176
|
+
target['ssh'] = None
|
|
177
|
+
else:
|
|
178
|
+
val = {}
|
|
179
|
+
val['type'] = 'boolean'
|
|
180
|
+
val['content'] = False
|
|
181
|
+
self.putSymbolValue(target, val)
|
|
179
182
|
return self.nextPC()
|
|
180
183
|
|
|
181
184
|
# Close a file
|
|
@@ -276,7 +279,7 @@ class Core(Handler):
|
|
|
276
279
|
return self.incdec(command, '-')
|
|
277
280
|
|
|
278
281
|
# Delete a file or a property
|
|
279
|
-
# delete {filename}
|
|
282
|
+
# delete file {filename}
|
|
280
283
|
# delete property {value} of {variable}
|
|
281
284
|
# delete element {name} of {variable}
|
|
282
285
|
def k_delete(self, command):
|
|
@@ -305,8 +308,8 @@ class Core(Handler):
|
|
|
305
308
|
type = command['type']
|
|
306
309
|
if type == 'file':
|
|
307
310
|
filename = self.getRuntimeValue(command['filename'])
|
|
308
|
-
if
|
|
309
|
-
os.remove(filename)
|
|
311
|
+
if filename != None:
|
|
312
|
+
if os.path.isfile(filename): os.remove(filename)
|
|
310
313
|
elif type == 'property':
|
|
311
314
|
key = self.getRuntimeValue(command['key'])
|
|
312
315
|
symbolRecord = self.getVariable(command['var'])
|
|
@@ -320,7 +323,8 @@ class Core(Handler):
|
|
|
320
323
|
symbolRecord = self.getVariable(command['var'])
|
|
321
324
|
value = self.getSymbolValue(symbolRecord)
|
|
322
325
|
content = value['content']
|
|
323
|
-
content
|
|
326
|
+
if key >= 0 and key < len(content): del(content[key])
|
|
327
|
+
else: RuntimeError(self.program, f'Index {key} out of range')
|
|
324
328
|
value['content'] = content
|
|
325
329
|
self.putSymbolValue(symbolRecord, value)
|
|
326
330
|
return self.nextPC()
|
|
@@ -464,7 +468,7 @@ class Core(Handler):
|
|
|
464
468
|
if url != None:
|
|
465
469
|
command['url'] = url
|
|
466
470
|
command['or'] = None
|
|
467
|
-
get = self.
|
|
471
|
+
get = self.getCodeSize()
|
|
468
472
|
if self.peek() == 'timeout':
|
|
469
473
|
self.nextToken()
|
|
470
474
|
command['timeout'] = self.nextValue()
|
|
@@ -552,7 +556,7 @@ class Core(Handler):
|
|
|
552
556
|
command['condition'] = self.nextCondition()
|
|
553
557
|
self.add(command)
|
|
554
558
|
self.nextToken()
|
|
555
|
-
pcElse = self.
|
|
559
|
+
pcElse = self.getCodeSize()
|
|
556
560
|
cmd = {}
|
|
557
561
|
cmd['lino'] = command['lino']
|
|
558
562
|
cmd['domain'] = 'core'
|
|
@@ -565,7 +569,7 @@ class Core(Handler):
|
|
|
565
569
|
if self.peek() == 'else':
|
|
566
570
|
self.nextToken()
|
|
567
571
|
# Add a 'goto' to skip the 'else'
|
|
568
|
-
pcNext = self.
|
|
572
|
+
pcNext = self.getCodeSize()
|
|
569
573
|
cmd = {}
|
|
570
574
|
cmd['lino'] = command['lino']
|
|
571
575
|
cmd['domain'] = 'core'
|
|
@@ -574,15 +578,15 @@ class Core(Handler):
|
|
|
574
578
|
cmd['debug'] = False
|
|
575
579
|
self.add(cmd)
|
|
576
580
|
# Fixup the link to the 'else' branch
|
|
577
|
-
self.getCommandAt(pcElse)['goto'] = self.
|
|
581
|
+
self.getCommandAt(pcElse)['goto'] = self.getCodeSize()
|
|
578
582
|
# Process the 'else' branch
|
|
579
583
|
self.nextToken()
|
|
580
584
|
self.compileOne()
|
|
581
585
|
# Fixup the pcNext 'goto'
|
|
582
|
-
self.getCommandAt(pcNext)['goto'] = self.
|
|
586
|
+
self.getCommandAt(pcNext)['goto'] = self.getCodeSize()
|
|
583
587
|
else:
|
|
584
588
|
# We're already at the next command
|
|
585
|
-
self.getCommandAt(pcElse)['goto'] = self.
|
|
589
|
+
self.getCommandAt(pcElse)['goto'] = self.getCodeSize()
|
|
586
590
|
return True
|
|
587
591
|
|
|
588
592
|
def r_if(self, command):
|
|
@@ -601,7 +605,7 @@ class Core(Handler):
|
|
|
601
605
|
name = self.nextToken()
|
|
602
606
|
item = [keyword, name]
|
|
603
607
|
imports.append(item)
|
|
604
|
-
self.symbols[name] = self.
|
|
608
|
+
self.symbols[name] = self.getCodeSize()
|
|
605
609
|
variable = {}
|
|
606
610
|
variable['domain'] = None
|
|
607
611
|
variable['name'] = name
|
|
@@ -743,7 +747,7 @@ class Core(Handler):
|
|
|
743
747
|
else:
|
|
744
748
|
command['file'] = self.getValue()
|
|
745
749
|
command['or'] = None
|
|
746
|
-
load = self.
|
|
750
|
+
load = self.getCodeSize()
|
|
747
751
|
self.processOr(command, load)
|
|
748
752
|
return True
|
|
749
753
|
else:
|
|
@@ -912,7 +916,7 @@ class Core(Handler):
|
|
|
912
916
|
cmd['debug'] = False
|
|
913
917
|
self.add(cmd)
|
|
914
918
|
# Fixup the link
|
|
915
|
-
command['goto'] = self.
|
|
919
|
+
command['goto'] = self.getCodeSize()
|
|
916
920
|
return True
|
|
917
921
|
return False
|
|
918
922
|
|
|
@@ -1003,7 +1007,7 @@ class Core(Handler):
|
|
|
1003
1007
|
else:
|
|
1004
1008
|
command['result'] = None
|
|
1005
1009
|
command['or'] = None
|
|
1006
|
-
post = self.
|
|
1010
|
+
post = self.getCodeSize()
|
|
1007
1011
|
self.processOr(command, post)
|
|
1008
1012
|
return True
|
|
1009
1013
|
|
|
@@ -1076,7 +1080,7 @@ class Core(Handler):
|
|
|
1076
1080
|
return False
|
|
1077
1081
|
|
|
1078
1082
|
def r_push(self, command):
|
|
1079
|
-
value = self.getRuntimeValue(command['value'])
|
|
1083
|
+
value = deepcopy(self.getRuntimeValue(command['value']))
|
|
1080
1084
|
stackRecord = self.getVariable(command['to'])
|
|
1081
1085
|
if stackRecord['keyword'] != 'stack':
|
|
1082
1086
|
RuntimeError(self.program, f'{stackRecord["name"]} is not a stack')
|
|
@@ -1102,7 +1106,7 @@ class Core(Handler):
|
|
|
1102
1106
|
FatalError(self.compiler, f'Symbol {symbolRecord["name"]} is not a value holder')
|
|
1103
1107
|
else:
|
|
1104
1108
|
command['or'] = None
|
|
1105
|
-
self.processOr(command, self.
|
|
1109
|
+
self.processOr(command, self.getCodeSize())
|
|
1106
1110
|
return True
|
|
1107
1111
|
else:
|
|
1108
1112
|
FatalError(self.compiler, f'Symbol {self.getToken()} is not a variable')
|
|
@@ -1270,7 +1274,7 @@ class Core(Handler):
|
|
|
1270
1274
|
else:
|
|
1271
1275
|
command['file'] = self.getValue()
|
|
1272
1276
|
command['or'] = None
|
|
1273
|
-
save = self.
|
|
1277
|
+
save = self.getCodeSize()
|
|
1274
1278
|
self.processOr(command, save)
|
|
1275
1279
|
return True
|
|
1276
1280
|
|
|
@@ -1503,8 +1507,11 @@ class Core(Handler):
|
|
|
1503
1507
|
ssh = paramiko.SSHClient()
|
|
1504
1508
|
target['ssh'] = ssh
|
|
1505
1509
|
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
|
1506
|
-
|
|
1507
|
-
|
|
1510
|
+
try:
|
|
1511
|
+
ssh.connect(host, username=user, password=password, timeout=10)
|
|
1512
|
+
target['sftp'] = ssh.open_sftp()
|
|
1513
|
+
except:
|
|
1514
|
+
target['error'] = f'Unable to connect to {host} (timeout)'
|
|
1508
1515
|
return self.nextPC()
|
|
1509
1516
|
|
|
1510
1517
|
# Shuffle a list
|
|
@@ -1762,12 +1769,17 @@ class Core(Handler):
|
|
|
1762
1769
|
self.program.importPlugin(f'{source}:{clazz}')
|
|
1763
1770
|
return True
|
|
1764
1771
|
return False
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1772
|
+
else:
|
|
1773
|
+
token = self.nextToken()
|
|
1774
|
+
if token in ['graphics', 'debugger']:
|
|
1775
|
+
if not hasattr(self.program, 'usingGraphics'):
|
|
1776
|
+
print('Loading graphics module')
|
|
1777
|
+
from .ec_pyside import Graphics
|
|
1778
|
+
self.program.graphics = Graphics
|
|
1779
|
+
self.program.useClass(Graphics)
|
|
1780
|
+
self.program.usingGraphics = True
|
|
1781
|
+
if token == 'debugger': self.program.debugging = True
|
|
1782
|
+
return True
|
|
1771
1783
|
return False
|
|
1772
1784
|
|
|
1773
1785
|
# Declare a general-purpose variable
|
|
@@ -1811,10 +1823,10 @@ class Core(Handler):
|
|
|
1811
1823
|
return None
|
|
1812
1824
|
# token = self.getToken()
|
|
1813
1825
|
command['condition'] = code
|
|
1814
|
-
test = self.
|
|
1826
|
+
test = self.getCodeSize()
|
|
1815
1827
|
self.add(command)
|
|
1816
1828
|
# Set up a goto for when the test fails
|
|
1817
|
-
fail = self.
|
|
1829
|
+
fail = self.getCodeSize()
|
|
1818
1830
|
cmd = {}
|
|
1819
1831
|
cmd['lino'] = command['lino']
|
|
1820
1832
|
cmd['domain'] = 'core'
|
|
@@ -1835,7 +1847,7 @@ class Core(Handler):
|
|
|
1835
1847
|
cmd['debug'] = False
|
|
1836
1848
|
self.add(cmd)
|
|
1837
1849
|
# Fixup the 'goto' on completion
|
|
1838
|
-
self.getCommandAt(fail)['goto'] = self.
|
|
1850
|
+
self.getCommandAt(fail)['goto'] = self.getCodeSize()
|
|
1839
1851
|
return True
|
|
1840
1852
|
|
|
1841
1853
|
def r_while(self, command):
|
|
@@ -2108,14 +2120,24 @@ class Core(Handler):
|
|
|
2108
2120
|
return value
|
|
2109
2121
|
|
|
2110
2122
|
if token == 'error':
|
|
2111
|
-
|
|
2123
|
+
token = self.peek()
|
|
2124
|
+
if token == 'code':
|
|
2112
2125
|
self.nextToken()
|
|
2113
2126
|
value['item'] = 'errorCode'
|
|
2114
2127
|
return value
|
|
2115
|
-
|
|
2128
|
+
elif token == 'reason':
|
|
2116
2129
|
self.nextToken()
|
|
2117
2130
|
value['item'] = 'errorReason'
|
|
2118
2131
|
return value
|
|
2132
|
+
elif token in ['in', 'of']:
|
|
2133
|
+
self.nextToken()
|
|
2134
|
+
if self.nextIsSymbol():
|
|
2135
|
+
record = self.getSymbolRecord()
|
|
2136
|
+
if record['keyword'] == 'ssh':
|
|
2137
|
+
value['item'] = 'sshError'
|
|
2138
|
+
value['name'] = record['name']
|
|
2139
|
+
return value
|
|
2140
|
+
return None
|
|
2119
2141
|
|
|
2120
2142
|
if token == 'type':
|
|
2121
2143
|
if self.nextIs('of'):
|
|
@@ -2279,6 +2301,10 @@ class Core(Handler):
|
|
|
2279
2301
|
elif v['item'] == 'errorReason':
|
|
2280
2302
|
value['type'] = 'text'
|
|
2281
2303
|
value['content'] = errorReason
|
|
2304
|
+
elif v['item'] == 'sshError':
|
|
2305
|
+
record = self.getVariable(v['name'])
|
|
2306
|
+
value['type'] = 'text'
|
|
2307
|
+
value['content'] = record['error'] if 'error' in record else ''
|
|
2282
2308
|
return value
|
|
2283
2309
|
|
|
2284
2310
|
def v_files(self, v):
|
|
@@ -2430,7 +2456,7 @@ class Core(Handler):
|
|
|
2430
2456
|
def v_now(self, v):
|
|
2431
2457
|
value = {}
|
|
2432
2458
|
value['type'] = 'int'
|
|
2433
|
-
value['content'] =
|
|
2459
|
+
value['content'] = int(time.time())
|
|
2434
2460
|
return value
|
|
2435
2461
|
|
|
2436
2462
|
def v_position(self, v):
|
|
@@ -2510,7 +2536,7 @@ class Core(Handler):
|
|
|
2510
2536
|
elif keyword == 'ssh':
|
|
2511
2537
|
v = {}
|
|
2512
2538
|
v['type'] = 'boolean'
|
|
2513
|
-
v['content'] = True if 'ssh' in symbolRecord else False
|
|
2539
|
+
v['content'] = True if 'ssh' in symbolRecord and symbolRecord['ssh'] != None else False
|
|
2514
2540
|
return v
|
|
2515
2541
|
else:
|
|
2516
2542
|
return None
|
|
@@ -2611,18 +2637,39 @@ class Core(Handler):
|
|
|
2611
2637
|
#############################################################################
|
|
2612
2638
|
# Compile a condition
|
|
2613
2639
|
def compileCondition(self):
|
|
2614
|
-
condition =
|
|
2640
|
+
condition = Object()
|
|
2641
|
+
condition.negate = False
|
|
2642
|
+
|
|
2643
|
+
token = self.getToken()
|
|
2615
2644
|
|
|
2616
|
-
if
|
|
2645
|
+
if token == 'not':
|
|
2617
2646
|
condition.type = 'not'
|
|
2618
2647
|
condition.value = self.nextValue()
|
|
2619
2648
|
return condition
|
|
2620
2649
|
|
|
2621
|
-
|
|
2650
|
+
elif token == 'error':
|
|
2651
|
+
self.nextToken()
|
|
2652
|
+
self.skip('in')
|
|
2653
|
+
if self.nextIsSymbol():
|
|
2654
|
+
record = self.getSymbolRecord()
|
|
2655
|
+
if record['keyword'] == 'ssh':
|
|
2656
|
+
condition.type = 'sshError'
|
|
2657
|
+
condition.target = record['name']
|
|
2658
|
+
return condition
|
|
2659
|
+
return None
|
|
2660
|
+
|
|
2661
|
+
elif token == 'file':
|
|
2622
2662
|
path = self.nextValue()
|
|
2623
2663
|
condition.path = path
|
|
2624
2664
|
condition.type = 'exists'
|
|
2625
|
-
|
|
2665
|
+
self.skip('on')
|
|
2666
|
+
if self.nextIsSymbol():
|
|
2667
|
+
record = self.getSymbolRecord()
|
|
2668
|
+
if record['keyword'] == 'ssh':
|
|
2669
|
+
condition.type = 'sshExists'
|
|
2670
|
+
condition.target = record['name']
|
|
2671
|
+
token = self.nextToken()
|
|
2672
|
+
else: token = self.getToken()
|
|
2626
2673
|
if token == 'exists':
|
|
2627
2674
|
return condition
|
|
2628
2675
|
elif token == 'does':
|
|
@@ -2798,6 +2845,24 @@ class Core(Handler):
|
|
|
2798
2845
|
|
|
2799
2846
|
def c_odd(self, condition):
|
|
2800
2847
|
return self.getRuntimeValue(condition.value1) % 2 == 1
|
|
2848
|
+
|
|
2849
|
+
def c_sshError(self, condition):
|
|
2850
|
+
target = self.getVariable(condition.target)
|
|
2851
|
+
errormsg = target['error'] if 'error' in target else None
|
|
2852
|
+
condition.errormsg = errormsg
|
|
2853
|
+
test = errormsg != None
|
|
2854
|
+
return not test if condition.negate else test
|
|
2855
|
+
|
|
2856
|
+
def c_sshExists(self, condition):
|
|
2857
|
+
path = self.getRuntimeValue(condition.path)
|
|
2858
|
+
ssh = self.getVariable(condition.target)
|
|
2859
|
+
sftp = ssh['sftp']
|
|
2860
|
+
try:
|
|
2861
|
+
with sftp.open(path, 'r') as remote_file: remote_file.read().decode()
|
|
2862
|
+
comparison = True
|
|
2863
|
+
except:
|
|
2864
|
+
comparison = False
|
|
2865
|
+
return not comparison if condition.negate else comparison
|
|
2801
2866
|
|
|
2802
2867
|
def c_starts(self, condition):
|
|
2803
2868
|
value1 = self.getRuntimeValue(condition.value1)
|
easycoder/ec_handler.py
CHANGED
|
@@ -22,8 +22,8 @@ class Handler:
|
|
|
22
22
|
self.compileVariable = compiler.compileVariable
|
|
23
23
|
self.rewindTo = compiler.rewindTo
|
|
24
24
|
self.warning = compiler.warning
|
|
25
|
-
self.
|
|
26
|
-
self.add = compiler.
|
|
25
|
+
self.getCodeSize = compiler.getCodeSize
|
|
26
|
+
self.add = compiler.addCommand
|
|
27
27
|
self.getCommandAt = compiler.getCommandAt
|
|
28
28
|
self.compileOne = compiler.compileOne
|
|
29
29
|
self.compileFromHere = compiler.compileFromHere
|
easycoder/ec_keyboard.py
CHANGED
|
@@ -158,6 +158,8 @@ class KeyboardView(QVBoxLayout):
|
|
|
158
158
|
for row in rows:
|
|
159
159
|
self.addLayout(row)
|
|
160
160
|
|
|
161
|
+
###############################################################################
|
|
162
|
+
# VirtualKeyboard Class
|
|
161
163
|
class VirtualKeyboard(QStackedWidget):
|
|
162
164
|
def __init__(self, keyboardType, buttonHeight, receiver, onFinished):
|
|
163
165
|
super().__init__()
|
|
@@ -173,6 +175,8 @@ class VirtualKeyboard(QStackedWidget):
|
|
|
173
175
|
self.addKeyboardLayout2()
|
|
174
176
|
self.addKeyboardLayout3()
|
|
175
177
|
|
|
178
|
+
###########################################################################
|
|
179
|
+
# Add the first keyboard layout (lowercase letters)
|
|
176
180
|
def addKeyboardLayout0(self):
|
|
177
181
|
rowList = []
|
|
178
182
|
|
|
@@ -214,7 +218,7 @@ class VirtualKeyboard(QStackedWidget):
|
|
|
214
218
|
KeyboardButton(self.buttonHeight * 1.5, self.buttonHeight, self.onClickNumbers, None, 'img/numbers.png'),
|
|
215
219
|
QSpacerItem(self.buttonHeight * 0.05, 0, QSizePolicy.Fixed, QSizePolicy.Minimum),
|
|
216
220
|
KeyboardButton(self.buttonHeight, self.buttonHeight, self.onClickChar, ","),
|
|
217
|
-
KeyboardButton(self.buttonHeight * 5, self.buttonHeight, self.onClickSpace, None, '
|
|
221
|
+
KeyboardButton(self.buttonHeight * 5, self.buttonHeight, self.onClickSpace, None, 'keyboard/space.png'),
|
|
218
222
|
KeyboardButton(self.buttonHeight, self.buttonHeight, self.onClickChar, "."),
|
|
219
223
|
QSpacerItem(self.buttonHeight * 0.05, 0, QSizePolicy.Fixed, QSizePolicy.Minimum),
|
|
220
224
|
KeyboardButton(self.buttonHeight * 1.5, self.buttonHeight, self.onClickEnter, None, 'img/enter.png'),
|
|
@@ -228,6 +232,8 @@ class VirtualKeyboard(QStackedWidget):
|
|
|
228
232
|
container.setLayout(keyboardView)
|
|
229
233
|
self.addWidget(container)
|
|
230
234
|
|
|
235
|
+
###########################################################################
|
|
236
|
+
# Add the second keyboard layout (uppercase letters)
|
|
231
237
|
def addKeyboardLayout1(self):
|
|
232
238
|
rowList = []
|
|
233
239
|
|
|
@@ -283,6 +289,8 @@ class VirtualKeyboard(QStackedWidget):
|
|
|
283
289
|
container.setLayout(keyboardView)
|
|
284
290
|
self.addWidget(container)
|
|
285
291
|
|
|
292
|
+
###########################################################################
|
|
293
|
+
# Add the third keyboard layout (numbers and symbols)
|
|
286
294
|
def addKeyboardLayout2(self):
|
|
287
295
|
rowList = []
|
|
288
296
|
|
|
@@ -320,11 +328,11 @@ class VirtualKeyboard(QStackedWidget):
|
|
|
320
328
|
KeyboardButton(self.buttonHeight * 1.5, self.buttonHeight, self.onClickLetters, None, 'img/letters.png'),
|
|
321
329
|
QSpacerItem(self.buttonHeight * 0.05, 0, QSizePolicy.Fixed, QSizePolicy.Minimum),
|
|
322
330
|
KeyboardButton(self.buttonHeight, self.buttonHeight, self.onClickChar, ","),
|
|
323
|
-
KeyboardButton(self.buttonHeight *
|
|
331
|
+
KeyboardButton(self.buttonHeight * 5.2, self.buttonHeight, self.onClickSpace, None, 'keyboard/space.png'),
|
|
324
332
|
KeyboardButton(self.buttonHeight, self.buttonHeight, self.onClickChar, "."),
|
|
325
333
|
QSpacerItem(self.buttonHeight * 0.05, 0, QSizePolicy.Fixed, QSizePolicy.Minimum),
|
|
326
334
|
KeyboardButton(self.buttonHeight * 1.5, self.buttonHeight, self.onClickEnter, None, 'img/enter.png'),
|
|
327
|
-
QSpacerItem(
|
|
335
|
+
QSpacerItem(10, 40, QSizePolicy.Expanding, QSizePolicy.Minimum)
|
|
328
336
|
])
|
|
329
337
|
rowList.append(row4)
|
|
330
338
|
|
|
@@ -334,6 +342,8 @@ class VirtualKeyboard(QStackedWidget):
|
|
|
334
342
|
container.setLayout(keyboardView)
|
|
335
343
|
self.addWidget(container)
|
|
336
344
|
|
|
345
|
+
###########################################################################
|
|
346
|
+
# Add the fourth keyboard layout (additional symbols)
|
|
337
347
|
def addKeyboardLayout3(self):
|
|
338
348
|
rowList = []
|
|
339
349
|
|