easycoder 251104.2__py2.py3-none-any.whl → 260110.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.

Potentially problematic release.


This version of easycoder might be problematic. Click here for more details.

Files changed (60) hide show
  1. easycoder/__init__.py +5 -3
  2. easycoder/debugger/__init__.py +5 -0
  3. easycoder/debugger/ec_dbg_value_display copy.py +195 -0
  4. easycoder/debugger/ec_dbg_value_display.py +24 -0
  5. easycoder/debugger/ec_dbg_watch_list copy.py +219 -0
  6. easycoder/debugger/ec_dbg_watchlist.py +293 -0
  7. easycoder/debugger/ec_debug.py +1025 -0
  8. easycoder/ec_border.py +15 -11
  9. easycoder/ec_classes.py +487 -11
  10. easycoder/ec_compiler.py +81 -44
  11. easycoder/ec_condition.py +1 -1
  12. easycoder/ec_core.py +1044 -1090
  13. easycoder/ec_gclasses.py +236 -0
  14. easycoder/ec_graphics.py +1683 -0
  15. easycoder/ec_handler.py +18 -13
  16. easycoder/ec_keyboard.py +50 -50
  17. easycoder/ec_program.py +299 -156
  18. easycoder/ec_psutil.py +48 -0
  19. easycoder/ec_timestamp.py +2 -1
  20. easycoder/ec_value.py +65 -47
  21. easycoder/icons/exit.png +0 -0
  22. easycoder/icons/run.png +0 -0
  23. easycoder/icons/step.png +0 -0
  24. easycoder/icons/stop.png +0 -0
  25. easycoder/pre/README.md +3 -0
  26. easycoder/pre/__init__.py +17 -0
  27. easycoder/pre/debugger/__init__.py +5 -0
  28. easycoder/pre/debugger/ec_dbg_value_display copy.py +195 -0
  29. easycoder/pre/debugger/ec_dbg_value_display.py +24 -0
  30. easycoder/pre/debugger/ec_dbg_watch_list copy.py +219 -0
  31. easycoder/pre/debugger/ec_dbg_watchlist.py +293 -0
  32. easycoder/pre/debugger/ec_debug.py +1014 -0
  33. easycoder/pre/ec_border.py +67 -0
  34. easycoder/pre/ec_classes.py +470 -0
  35. easycoder/pre/ec_compiler.py +291 -0
  36. easycoder/pre/ec_condition.py +27 -0
  37. easycoder/pre/ec_core.py +2772 -0
  38. easycoder/pre/ec_gclasses.py +230 -0
  39. easycoder/{ec_pyside.py → pre/ec_graphics.py} +631 -496
  40. easycoder/pre/ec_handler.py +79 -0
  41. easycoder/pre/ec_keyboard.py +439 -0
  42. easycoder/pre/ec_program.py +557 -0
  43. easycoder/pre/ec_psutil.py +48 -0
  44. easycoder/pre/ec_timestamp.py +11 -0
  45. easycoder/pre/ec_value.py +124 -0
  46. easycoder/pre/icons/close.png +0 -0
  47. easycoder/pre/icons/exit.png +0 -0
  48. easycoder/pre/icons/run.png +0 -0
  49. easycoder/pre/icons/step.png +0 -0
  50. easycoder/pre/icons/stop.png +0 -0
  51. easycoder/pre/icons/tick.png +0 -0
  52. {easycoder-251104.2.dist-info → easycoder-260110.1.dist-info}/METADATA +11 -1
  53. easycoder-260110.1.dist-info/RECORD +58 -0
  54. easycoder/ec_debug.py +0 -464
  55. easycoder-251104.2.dist-info/RECORD +0 -20
  56. /easycoder/{close.png → icons/close.png} +0 -0
  57. /easycoder/{tick.png → icons/tick.png} +0 -0
  58. {easycoder-251104.2.dist-info → easycoder-260110.1.dist-info}/WHEEL +0 -0
  59. {easycoder-251104.2.dist-info → easycoder-260110.1.dist-info}/entry_points.txt +0 -0
  60. {easycoder-251104.2.dist-info → easycoder-260110.1.dist-info}/licenses/LICENSE +0 -0
easycoder/ec_program.py CHANGED
@@ -1,7 +1,16 @@
1
- import time, json, sys
1
+ import time, sys, json
2
2
  from copy import deepcopy
3
3
  from collections import deque
4
- from .ec_classes import Script, Token, FatalError, RuntimeError, Object
4
+ from .ec_classes import (
5
+ Script,
6
+ Token,
7
+ FatalError,
8
+ RuntimeError,
9
+ NoValueRuntimeError,
10
+ ECObject,
11
+ ECValue,
12
+ normalize_type
13
+ )
5
14
  from .ec_compiler import Compiler
6
15
  from .ec_core import Core
7
16
  import importlib
@@ -16,20 +25,25 @@ def flush():
16
25
 
17
26
  class Program:
18
27
 
19
- def __init__(self, argv):
28
+ def __init__(self, arg):
20
29
  global queue
21
30
  print(f'EasyCoder version {version("easycoder")}')
22
- if len(argv) == 0:
31
+ if len(arg) == 0:
23
32
  print('No script supplied')
24
33
  exit()
25
- if argv in ['-v', '--version']: return
26
- scriptName = argv
34
+ if arg in ['-v', '--version']: return
35
+ if arg[0:6] == 'debug ':
36
+ print('Debug mode requested')
37
+ self.scriptName = arg[6:]
38
+ self.debugging = True
39
+ else:
40
+ self.scriptName = arg
41
+ self.debugging = False
27
42
 
28
- f = open(scriptName, 'r')
43
+ f = open(self.scriptName, 'r')
29
44
  source = f.read()
30
45
  f.close()
31
46
  queue = deque()
32
- self.argv = argv
33
47
  self.domains = []
34
48
  self.domainIndex = {}
35
49
  self.name = '<anon>'
@@ -38,28 +52,35 @@ class Program:
38
52
  self.symbols = {}
39
53
  self.onError = 0
40
54
  self.debugStep = False
55
+ self.debugSkip = False
41
56
  self.stack = []
42
57
  self.script = Script(source)
43
58
  self.compiler = Compiler(self)
59
+ self.object = ECObject()
44
60
  self.value = self.compiler.value
45
61
  self.condition = self.compiler.condition
46
62
  self.graphics = None
63
+ self.psutil = None
47
64
  self.useClass(Core)
48
- self.externalControl = False
49
65
  self.ticker = 0
50
- self.usingGraphics = False
51
- self.debugging = False
66
+ self.graphicsRunning = False
52
67
  self.debugger = None
53
- self.running = True
68
+ self.running = False
69
+ self.parent = None
70
+ self.message = None
71
+ self.onMessagePC = 0
72
+ self.breakpoint = False
54
73
 
55
74
  # This is called at 10msec intervals by the GUI code
56
75
  def flushCB(self):
57
76
  self.ticker += 1
77
+ # if self.ticker % 1000 == 0: print(f'GUI Tick {self.ticker}')
58
78
  flush()
59
79
 
60
80
  def start(self, parent=None, module = None, exports=[]):
61
81
  self.parent = parent
62
82
  self.exports = exports
83
+ if self.debugging: self.useGraphics()
63
84
  if module != None:
64
85
  module['child'] = self
65
86
  startCompile = time.time()
@@ -72,7 +93,7 @@ class Program:
72
93
  f'{round((finishCompile - startCompile) * 1000)} ms')
73
94
  for name in self.symbols.keys():
74
95
  record = self.code[self.symbols[name]]
75
- if name[-1] != ':' and not record['used']:
96
+ if name[-1] != ':' and not 'used' in record:
76
97
  print(f'Variable "{name}" not used')
77
98
  else:
78
99
  print(f'Run {self.name}')
@@ -81,13 +102,35 @@ class Program:
81
102
  self.compiler.showWarnings()
82
103
 
83
104
  # If this is the main script and there's no graphics, run a main loop
84
- if parent == None and self.externalControl == False:
85
- while True:
105
+ if parent == None:
106
+ while not self.graphicsRunning:
86
107
  if self.running == True:
87
108
  flush()
88
109
  time.sleep(0.01)
89
110
  else:
90
111
  break
112
+
113
+ # Use the graphics module
114
+ def useGraphics(self):
115
+ if self.graphics == None:
116
+ print('Loading graphics module')
117
+ from .ec_graphics import Graphics
118
+ self.graphics = Graphics
119
+ self.useClass(Graphics)
120
+ return True
121
+
122
+ # Use the psutil module
123
+ def usePSUtil(self):
124
+ if self.psutil == None:
125
+ print('Loading psutil module')
126
+ from .ec_psutil import PSUtil
127
+ self.psutil = PSUtil
128
+ self.useClass(PSUtil)
129
+ return True
130
+
131
+ # Indicate that graphics are running
132
+ def startGraphics(self):
133
+ self.graphicsRunning = True
91
134
 
92
135
  # Import a plugin
93
136
  def importPlugin(self, source):
@@ -112,122 +155,225 @@ class Program:
112
155
  self.domains.append(handler)
113
156
  self.domainIndex[handler.getName()] = handler
114
157
 
158
+ # This is the runtime callback for event handlers
159
+ def callback(self, item, record, goto):
160
+ object = self.getObject(record)
161
+ values = object.getValues() # type: ignore
162
+ for i, v in enumerate(values):
163
+ if isinstance(v, ECValue): v = v.getContent()
164
+ if v == item:
165
+ object.setIndex(i) # type: ignore
166
+ self.run(goto)
167
+ return
168
+
169
+ # Ensure the program is running
170
+ def ensureRunning(self):
171
+ if not self.running:
172
+ raise RuntimeError(self, 'Improper use of runtime function')
173
+
174
+ # Ensure the program is not running
175
+ def ensureNotRunning(self):
176
+ if self.running:
177
+ raise RuntimeError(self, 'Improper use of non-runtime function')
178
+
115
179
  # Get the domain list
116
180
  def getDomains(self):
117
181
  return self.domains
118
-
119
- def getSymbolRecord(self, name):
182
+
183
+ def isSymbol(self, name):
184
+ return name in self.symbols
185
+
186
+ # Get the symbol record for a given name
187
+ def getVariable(self, name):
188
+ self.ensureRunning()
189
+ if isinstance(name, dict): name = name['name']
120
190
  try:
121
191
  target = self.code[self.symbols[name]]
122
- if target['import'] != None:
192
+ if 'import' in target:
123
193
  target = target['import']
124
194
  return target
125
195
  except:
126
196
  RuntimeError(self, f'Unknown symbol \'{name}\'')
197
+
198
+ # Get the object represented by a symbol record
199
+ def getObject(self, record):
200
+ if isinstance(record, dict) and 'object' in record:
201
+ return record['object']
202
+ return record
203
+
204
+ # Check if an object is an instance of a given class
205
+ # This can either be variable record (a dict) or an instance of ECObject
206
+ def isObjectType(self, object, classes):
207
+ if isinstance(object, dict) and 'object' in object and isinstance(object['object'], ECObject):
208
+ object = object['object']
209
+ return isinstance(object, classes)
210
+
211
+ # Check if the object is an instance of one of a set of classes. Compile and runtime
212
+ def checkObjectType(self, object, classes):
213
+ if isinstance(object, dict): return
214
+ if not isinstance(object, classes):
215
+ if isinstance(classes, tuple):
216
+ class_names = ", ".join([c.__name__ for c in classes])
217
+ message = f"Variable {object.name} should be one of {class_names}"
218
+ else:
219
+ class_names = classes.__name__
220
+ message = f"Variable {object.name} should be {class_names}"
221
+ if self.running:
222
+ raise RuntimeError(self, message)
223
+ else:
224
+ raise FatalError(self.compiler, message)
225
+
226
+ # Get the inner (non-EC) object from a name, record or object
227
+ def getInnerObject(self, object):
228
+ if isinstance(object, dict): object = object['object']
229
+ elif isinstance(object, str):
230
+ record = self.getVariable(object) # type: ignore
231
+ object = self.getObject(record) # type: ignore
232
+ value = object.getValue() # type: ignore
233
+ if isinstance(value, ECValue) and value.getType() == 'object':
234
+ return value.getContent()
235
+ else: return value
127
236
 
128
- def doValue(self, value):
129
- if value == None:
130
- RuntimeError(self, f'Undefined value (variable not initialized?)')
131
-
237
+ def constant(self, content, numeric):
132
238
  result = {}
133
- valType = value['type']
134
- if valType in ['boolean', 'int', 'text', 'object']:
135
- result = value
239
+ result['type'] = int if numeric else str
240
+ result['content'] = content
241
+ return result
242
+
243
+ # Test if an item is a string or a number
244
+ def getItemType(self, value):
245
+ return int if isinstance(value, int) else str
246
+
247
+ # Get the value of an item that may be an ECValue or a raw value. Return as an ECValue
248
+ def getValueOf(self, item):
249
+ value = ECValue()
250
+ if isinstance(item, ECValue):
251
+ if item.getType() == 'object':
252
+ return item.getContent()
253
+ else: value = item
254
+ else:
255
+ varType = type(item).__name__
256
+ if varType == 'int': value.setValue(type=int, content=item)
257
+ elif varType == 'str': value.setValue(type=str, content=item)
258
+ elif varType == 'bool': value.setValue(type=bool, content=item)
259
+ elif varType == 'float': value.setValue(type=str, content=str(item))
260
+ elif varType == 'list': value.setValue(type=list, content=item)
261
+ elif varType == 'dict': value.setValue(type=dict, content=item)
262
+ else: value.setValue(type=None, content=None)
263
+ return value
264
+
265
+ # Runtime function to evaluate an ECObject or ECValue. Returns another ECValue
266
+ # This function may be called recursively by value handlers.
267
+ def evaluate(self, item):
268
+ self.ensureRunning()
269
+ if isinstance(item, ECObject):
270
+ value = item.getValue()
271
+ if value == None:
272
+ raise RuntimeError(self, f'Symbol {item.getName()} not initialized')
273
+ else: value = item
274
+ try:
275
+ valType = normalize_type(value.getType()) # type: ignore
276
+ except:
277
+ RuntimeError(self, 'Value does not hold a valid ECValue')
278
+ result = ECValue(type=valType)
279
+
280
+ if valType in ('str', 'int', 'bool', 'list', 'dict', None):
281
+ # Simple value - just return the content
282
+ result.setContent(value.getContent()) # type: ignore
283
+
284
+ elif valType == 'object':
285
+ # Object other than ECVariable
286
+ record = self.getVariable(value.getName())
287
+ object = self.getObject(record) # type: ignore
288
+ result = object.getContent() # type: ignore
289
+
290
+ elif valType == 'symbol': # type: ignore
291
+ # If it's a symbol, get its value
292
+ record = self.getVariable(value.getContent()) # type: ignore
293
+ if not 'object' in record: return None # type: ignore
294
+ variable = self.getObject(record) # type: ignore
295
+ result = variable.getValue() # type: ignore
296
+ if isinstance(result, ECValue): return self.evaluate(result)
297
+ if isinstance(result, ECObject): return result.getValue()
298
+ if isinstance(result, dict) or isinstance(result, list):
299
+ return result
300
+ # See if one of the domains can handle this value
301
+ value = result
302
+ result = None
303
+ for domain in self.domains:
304
+ result = domain.getUnknownValue(value)
305
+ if result != None: break
306
+
136
307
  elif valType == 'cat':
308
+ # Handle concatenation
137
309
  content = ''
138
- for part in value['value']:
139
- val = self.doValue(part)
140
- if val == None:
141
- val = ''
142
- if val != '':
143
- val = str(val['content'])
144
- if val == None:
145
- val = ''
146
- content += val
147
- result['type'] = 'text'
148
- result['content'] = content
149
- elif valType == 'symbol':
150
- name = value['name']
151
- symbolRecord = self.getSymbolRecord(name)
152
- # if symbolRecord['hasValue']:
153
- if symbolRecord:
154
- handler = self.domainIndex[symbolRecord['domain']].valueHandler('symbol')
155
- result = handler(symbolRecord)
156
- # else:
157
- # # Call the given domain to handle a value
158
- # # domain = self.domainIndex[value['domain']]
159
- # handler = domain.valueHandler(value['type'])
160
- # if handler: result = handler(value)
310
+ for part in value.getContent(): # pyright: ignore[reportOptionalMemberAccess]
311
+ val = self.evaluate(part) # pyright: ignore[reportAttributeAccessIssue]
312
+ if val != None:
313
+ if isinstance(val, ECValue): val = str(val.getContent())
314
+ if val == None: val = ''
315
+ else: content += str(val)
316
+ result.setValue(type=str, content=content)
317
+
161
318
  else:
162
319
  # Call the given domain to handle a value
163
- domain = self.domainIndex[value['domain']]
164
- handler = domain.valueHandler(value['type'])
320
+ domainName = value.getDomain() # type: ignore
321
+ if domainName == None: domainName = 'core'
322
+ domain = self.domainIndex[domainName]
323
+ handler = domain.valueHandler(value.getType()) # type: ignore
165
324
  if handler: result = handler(value)
166
325
 
167
326
  return result
168
327
 
169
- def constant(self, content, numeric):
170
- result = {}
171
- result['type'] = 'int' if numeric else 'text'
172
- result['content'] = content
173
- return result
174
-
175
- def evaluate(self, value):
176
- if value == None:
177
- result = {}
178
- result['type'] = 'text'
179
- result['content'] = ''
180
- return result
181
-
182
- result = self.doValue(value)
183
- if result:
184
- return result
185
- return None
186
-
187
- def getValue(self, value):
188
- result = self.evaluate(value)
189
- if result:
190
- return result.get('content') # type: ignore[union-attr]
191
- return None
192
-
193
- def getRuntimeValue(self, value):
328
+ # Get the runtime value of a value object (as a string or integer)
329
+ def textify(self, value):
330
+ self.ensureRunning()
194
331
  if value is None:
195
332
  return None
196
- v = self.evaluate(value)
197
- if v != None:
198
- content = v['content']
199
- if v['type'] == 'boolean':
200
- return True if content else False
201
- if v['type'] in ['int', 'float', 'text', 'object']:
202
- return content
203
- return ''
204
- return None
205
-
206
- def getSymbolContent(self, symbolRecord):
207
- if len(symbolRecord['value']) == 0:
208
- return None
209
- try: return symbolRecord['value'][symbolRecord['index']]
210
- except: RuntimeError(self, f'Cannot get content of symbol "{symbolRecord["name"]}"')
211
-
212
- def getSymbolValue(self, symbolRecord):
213
- if len(symbolRecord['value']) == 0:
333
+
334
+ if isinstance(value, dict):
335
+ value = value['object']
336
+ if isinstance(value, ECObject):
337
+ value = value.getValue()
338
+ if isinstance(value, ECValue): # type: ignore
339
+ v = self.evaluate(value) # type: ignore
340
+ else:
341
+ v = value
342
+ if v is None: return None
343
+ if isinstance(v, ECValue):
344
+ if v.getType() == 'object':
345
+ return value.getContent() # type: ignore
346
+ return v.getContent()
347
+ if isinstance(v, (dict, list)):
348
+ return json.dumps(v)
349
+ return v
350
+
351
+ # Get the content of a symbol
352
+ def getSymbolContent(self, record):
353
+ if len(record['value']) == 0:
214
354
  return None
215
- try: value = symbolRecord['value'][symbolRecord['index']]
216
- except: RuntimeError(self, f'Cannot get value of symbol "{symbolRecord["name"]}"')
217
- copy = deepcopy(value)
355
+ try: return record['value'][record['index']]
356
+ except: raise RuntimeError(self, f'Cannot get content of symbol "{record["name"]}"')
357
+
358
+ # Get the value of a symbol as an ECValue
359
+ def getSymbolValue(self, record):
360
+ self.ensureRunning()
361
+ object = self.getObject(record)
362
+ self.checkObjectType(object, ECObject)
363
+ value = object.getValue() # type: ignore
364
+ if value is None:
365
+ raise NoValueRuntimeError(self, f'Symbol "{record["name"]}" has no value')
366
+ # copy = deepcopy(value)
367
+ copy = ECValue(domain=value.getDomain(),type=value.getType(),content=deepcopy(value.getContent()))
218
368
  return copy
219
369
 
220
- def putSymbolValue(self, symbolRecord, value):
221
- if symbolRecord['locked']:
222
- name = symbolRecord['name']
223
- RuntimeError(self, f'Symbol "{name}" is locked')
224
- if symbolRecord['value'] == None or symbolRecord['value'] == []:
225
- symbolRecord['value'] = [value]
226
- else:
227
- index = symbolRecord['index']
228
- if index == None:
229
- index = 0
230
- symbolRecord['value'][index] = value
370
+ # Set the value of a symbol to either an ECValue or a raw value
371
+ def putSymbolValue(self, record, value):
372
+ variable = self.getObject(record)
373
+ if variable.isLocked(): # type: ignore
374
+ name = record['name']
375
+ raise RuntimeError(self, f'Symbol "{name}" is locked')
376
+ variable.setValue(self.getValueOf(value)) # type: ignore
231
377
 
232
378
  def encode(self, value):
233
379
  return value
@@ -304,23 +450,35 @@ class Program:
304
450
  self.pc = pc
305
451
  while self.running:
306
452
  command = self.code[self.pc]
453
+
454
+ # Check if debugger wants to halt before executing this command
455
+ if self.debugger != None:
456
+ # pc==1 is the first real command (pc==0 is the debug loader)
457
+ is_first = (self.pc == 1)
458
+ if self.debugger.checkIfHalt(is_first):
459
+ # Debugger says halt - break out and wait for user
460
+ break
461
+
307
462
  domainName = command['domain']
308
463
  if domainName == None:
309
464
  self.pc += 1
310
465
  else:
311
466
  keyword = command['keyword']
312
- if self.debugStep and command['debug']:
467
+ if self.debugStep and not self.debugSkip and 'debug' in command:
313
468
  lino = command['lino'] + 1
314
469
  line = self.script.lines[command['lino']].strip()
315
470
  print(f'{self.name}: Line {lino}: {domainName}:{keyword}: {line}')
316
- if self.debugger != None:
317
- self.debugger.step()
318
471
  domain = self.domainIndex[domainName]
319
472
  handler = domain.runHandler(keyword)
320
473
  if handler:
321
474
  command = self.code[self.pc]
322
475
  command['program'] = self
323
- self.pc = handler(command)
476
+ try:
477
+ if self.breakpoint:
478
+ pass # Place a breakpoint here for a debugger to catch
479
+ self.pc = handler(command)
480
+ except Exception as e:
481
+ raise RuntimeError(self, f'Error during execution of {domainName}:{keyword}: {str(e)}')
324
482
  # Deal with 'exit'
325
483
  if self.pc == -1:
326
484
  queue = deque()
@@ -334,63 +492,48 @@ class Program:
334
492
  # Run the script at a given PC value
335
493
  def run(self, pc):
336
494
  global queue
337
- item = Object()
338
- item.program = self
339
- item.pc = pc
495
+ item = ECValue()
496
+ item.program = self # type: ignore
497
+ item.pc = pc # type: ignore
340
498
  queue.append(item)
499
+ self.running = True
341
500
 
342
501
  def kill(self):
343
502
  self.running = False
344
503
  if self.parent != None: self.parent.program.kill()
345
504
 
346
- def setExternalControl(self):
347
- self.externalControl = True
348
-
349
505
  def nonNumericValueError(self):
350
506
  FatalError(self.compiler, 'Non-numeric value')
351
507
 
352
- def variableDoesNotHoldAValueError(self, name):
353
- raise FatalError(self.compiler, f'Variable "{name}" does not hold a value')
354
-
355
- def noneValueError(self, name):
356
- raise FatalError(self.compiler, f'Value is None')
357
-
358
508
  def compare(self, value1, value2):
359
- val1 = self.evaluate(value1)
360
- val2 = self.evaluate(value2)
361
- if val1 == None or val2 == None:
509
+ if value1 == None or value2 == None:
510
+ RuntimeError(self, 'Cannot compare a value with None')
511
+ v1 = self.textify(value1)
512
+ v2 = self.textify(value2)
513
+ if v1 == None or v2 == None:
514
+ raise RuntimeError(self, 'Both items must have a value for comparison')
515
+ if type(v1) == str and type(v2) == str:
516
+ # String comparison
517
+ if v1 < v2: return -1
518
+ if v1 > v2: return 1
362
519
  return 0
363
- v1 = val1['content']
364
- v2 = val2['content']
365
- # if v1 == None and v2 != None or v1 != None and v2 == None:
366
- # return 0
367
- if v1 == None and v2 != None: return -1
368
- elif v2 == None and v1 != None: return 1
369
- if v1 != None and val1['type'] == 'int':
370
- if not val2['type'] == 'int':
371
- if type(v2) is str:
372
- try:
373
- v2 = int(v2)
374
- except:
375
- lino = self.code[self.pc]['lino'] + 1
376
- RuntimeError(None, f'Line {lino}: \'{v2}\' is not an integer')
377
- else:
378
- if v2 != None and val2['type'] == 'int':
379
- v2 = str(v2)
380
- if v1 == None:
381
- v1 = ''
382
- if v2 == None:
383
- v2 = ''
384
- if type(v1) == int:
385
- if type(v2) != int:
386
- v1 = f'{v1}'
387
- if type(v2) == int:
388
- if type(v1) != int:
389
- v2 = f'{v2}'
390
- if v1 > v2: # type: ignore[operator]
391
- return 1
520
+
521
+ if type(v1) is str:
522
+ try:
523
+ v1 = int(v1)
524
+ except:
525
+ print(f'{v1} is not an integer')
526
+ return None
527
+ if type(v2) is str:
528
+ try:
529
+ v2 = int(v2)
530
+ except:
531
+ print(f'{v2} is not an integer')
532
+ return None
392
533
  if v1 < v2: # type: ignore[operator]
393
534
  return -1
535
+ if v1 > v2: # type: ignore[operator]
536
+ return 1
394
537
  return 0
395
538
 
396
539
  # Set up a message handler
@@ -405,7 +548,7 @@ class Program:
405
548
  # This is the program launcher
406
549
  def Main():
407
550
  if (len(sys.argv) > 1):
408
- Program(sys.argv[1]).start()
551
+ Program(' '.join(sys.argv[1:])).start()
409
552
  else:
410
553
  Program('-v')
411
554
 
easycoder/ec_psutil.py ADDED
@@ -0,0 +1,48 @@
1
+ from easycoder import Handler, ECValue
2
+ import os
3
+ from psutil import Process
4
+
5
+ class PSUtil(Handler):
6
+
7
+ def __init__(self, compiler):
8
+ Handler.__init__(self, compiler)
9
+
10
+ def getName(self):
11
+ return 'psutil'
12
+
13
+ #############################################################################
14
+ # Keyword handlers
15
+
16
+ #############################################################################
17
+ # Compile a value in this domain
18
+ def compileValue(self):
19
+ value = ECValue(domain=self.getName())
20
+ if self.tokenIs('the'):
21
+ self.nextToken()
22
+ token = self.getToken()
23
+ if token in ['mem', 'memory']:
24
+ value.setType('memory')
25
+ return value
26
+ return None
27
+
28
+ #############################################################################
29
+ # Modify a value or leave it unchanged.
30
+ def modifyValue(self, value):
31
+ return value
32
+
33
+ #############################################################################
34
+ # Value handlers
35
+
36
+ def v_memory(self, v):
37
+ process: Process = Process(os.getpid())
38
+ megabytes: float = process.memory_info().rss / (1024 * 1024)
39
+ return ECValue(domain=self.getName(), type=float, content=megabytes)
40
+
41
+ #############################################################################
42
+ # Compile a condition
43
+ def compileCondition(self):
44
+ condition = {}
45
+ return condition
46
+
47
+ #############################################################################
48
+ # Condition handlers
easycoder/ec_timestamp.py CHANGED
@@ -5,6 +5,7 @@ def getTimestamp(t):
5
5
  tz = pytz.timezone('GB') # Localize this!
6
6
  dt = datetime.fromtimestamp(t)
7
7
  # print(f'{dt} + {tz.dst(dt).seconds}')
8
- return int(t) + tz.dst(dt).seconds
8
+ dst = tz.dst(dt)
9
+ return int(t) + (dst.seconds if dst else 0)
9
10
 
10
11
  # Usage: print(getTimestamp(time.time()))