1
# Copyright 2007, Sjoerd de Vries
2
# This file is part of the Spyder main program (a.k.a the Spyder kernel)
3
# For licensing information, see LICENSE.txt
5
import os, zlib, re, sys, imp, compiler
6
from copy import copy, deepcopy
7
from Spydercompile import Spydercompile, validvar
9
commentmatch = re.compile(r'(?:^(?:.*?)##(?:.*?)$)', re.MULTILINE)
10
brackmatch = re.compile(r'\[[^\[\]]*?\]')
11
commamatch = re.compile(r'[ \n]*,[ \n]*([^ \n]|$)')
12
quotematch = re.compile(r'(?<![\\])(([\"\']).*?(?<![\\])\2)')
17
def changetempdir(tempdir):
18
if not os.path.exists(tempdir):
19
dirs = [a for a in os.path.abspath(tempdir).split(os.sep) if len(a) > 0]
21
if dirs[0].endswith(":"):
26
if not os.path.exists(currdir): os.mkdir(currdir)
29
def dictparse(s,mask): #adapted from core/parse.py
30
if len(s) == 0: return {}
34
p = brackmatch.finditer(mask0)
38
mask2 += mask0[pos:pp.start()] + "!" * (pp.end()-pp.start())
43
#split; we can't use split() because of the mask (we need start/end)
45
p = commamatch.finditer(mask2)
48
elements.append( [s[pos:pp.start()], mask[pos:pp.start()], mask2[pos:pp.start()]] )
51
if len(s[pos:].strip()) > 0: elements.append([s[pos:], mask[pos:len(s)], mask2[pos:len(s)]])
55
if e[0].startswith('\n'):
56
e[0] = e[0][len('\n'):].lstrip()
57
e[1] = e[1][len(e[1])-len(e[0]):]
58
e[2] = e[2][len(e[2])-len(e[0]):]
59
if len(e[0]) == 0: continue
65
m2 = m2[len(m2)-len(v):]
75
if (k[0] != "\"" or k[-1] != "\"") and (k[0] != "'" or k[-1] != "'"):
76
raise SyntaxError("Malformed dictionary key %s" % k)
79
raise SyntaxError("Double key %s" % k)
83
if v[0] in ('[','('): #list
86
pairs[k] = listparse(v,m)
87
elif v[0] == '{': #dict
90
pairs[k] = dictparse(v,m)
91
elif bm > -1: #function + args
96
assert (v[0] == v[-1] == "'") or (v[0] == v[-1] == '"')
97
pairs[k] = eval("str(%s)" % v)
99
raise SyntaxError("Malformed dictionary pair %s" % e[0])
102
def listparse(s,mask): #adapted from core/parse.py
103
if len(s) == 0: return []
107
p = brackmatch.finditer(mask0)
111
mask2 += mask0[pos:pp.start()] + "!" * (pp.end()-pp.start())
116
#split; we can't use split() because of the mask (we need start/end)
118
p = commamatch.finditer(mask2)
121
elements.append( [s[pos:pp.start()], mask[pos:pp.start()], mask2[pos:pp.start()]] )
124
if len(s[pos:].strip()) > 0: elements.append([s[pos:], mask[pos:len(s)], mask2[pos:len(s)]])
128
if e[0].startswith('\n'):
129
e[0] = e[0][len('\n'):].lstrip()
130
e[1] = e[1][len(e[1])-len(e[0]):]
131
if len(e[0]) == 0: continue
135
m = m[len(m)-len(v):]
138
if v[0] in ('[','('): #list
141
values.append(listparse(v,m))
142
elif v[0] == '{': #dict
145
values.append(dictparse(v,m))
146
elif bm > -1: #function + args
150
assert v[0] in ( "'", '"')
151
values.append(eval("str(%s)" % v))
158
self.definition = None
161
class general(object):
173
global unimethods, unimethodlist, macros, statements, inheritedtypes, Spyder, corechecksum
174
global converters, concatenators
186
def defineunimethod(name, pointer):
187
if name in unimethods:
188
raise Exception("system error: duplicate definition of unimethod %s" % name)
189
unimethods[name] = pointer
190
unimethodlist.append(name)
191
def definemacro(pointer):
193
def definestatement(name, pointer):
194
if name in statements:
195
raise Exception("system error: duplicate definition of statement %s" % name)
196
statements[name] = pointer
198
def parse(lines, switches, switchlist,spyderdir):
207
metavars = {"nocripple":"off"}
208
if spyderdir != None: tmpvars[-1]["spyderdir"] = spyderdir
210
while len(lines) > 0:
211
l, lines = lines[0], lines[1:]
212
l = l.replace('\r\n', "")
213
l = l.replace('\n', "")
215
if l.strip().startswith("@"):
216
ll = l.strip()[1:].split("=")
218
metavars[ll[0].strip()] = ll[1].strip()
220
raise Exception("Invalid metavariable statement: " + l)
221
comment = l.find("#")
224
if metavars["nocripple"] == "on":
226
indent = len(l) - len(ll)
227
if ll.startswith("##"):
229
if ll.startswith("NOCRIPPLED"):
230
header = " " * indent
234
l = header + ll[len("NOCRIPPLED"):].strip()
237
if len(l.lstrip()) == 0: continue
240
dollar = l.find("$",dollarstart)
241
if dollar == -1: break
242
for endvar in range(dollar+1,len(l)):
243
if l[endvar].isalnum() == False or l[endvar] == " ":
245
else: endvar = len(l)
246
varnam = l[dollar+1:endvar]
247
if varnam not in tmpvars[-1]:
248
raise Exception("Unknown variable: '%s'" % varnam)
249
l = l[:dollar] + tmpvars[-1][varnam] + l[endvar:]
250
dollarstart = dollar + len(tmpvars[-1][varnam])
251
currspacing = len(l) - len(l.lstrip())
253
if currspacing < spacing[-1]:
254
raise Exception("Indentation error in line %d" % linenr)
255
elif currspacing == spacing[-1]:
256
spacing.append(999999)
259
spacing.append(currspacing)
265
if currspacing > spacing[-1]:
266
raise Exception("Indentation error in line %d" % linenr)
267
if currspacing < spacing[-1]:
269
for n in range(len(spacing)-2,-1,-1):
270
if currspacing == spacing[n]:
271
counter = len(spacing) - 2 - n
273
if counter == -1: raise Exception("Indentation error in line %d" % linenr)
274
for n in range(counter+1):
275
if currnamespace != "":
276
switches[currswitch].append("**")
278
elif currswitch != "":
281
for k in tmpvars[-1]:
282
if k not in tmpvars[-2]: tmpvars[-2][k] = tmpvars[-1][k]
286
if l[0] != "*" and l[-1] == ":" :
287
if currnamespace != "": raise Exception("System error: %s:\n Modules may not be nested" % l)
288
currnamespace = l[:-1].rstrip()
289
tmpvars.append(dict(tmpvars[-1]))
291
switches[currswitch].append(l)
296
for com in ("*path", "*delpath", "*delfile", "*replacefile", "*include", "*import", "*export"):
298
if currnamespace == "": raise Exception("System error: %s:\n %s only allowed in modules" % (l, ll[0]))
300
for com in ("*enable", "*disable", "*select", "*deselect"):
305
if ll[0] == "*patch" :
306
if currnamespace != "": raise Exception("System error: %s:\n %s only allowed outside modules" % (l, ll[0]))
307
currnamespace = l[len(ll[0]):].rstrip()
308
if currnamespace[-1] == ":": currnamespace = currnamespace[:-1]
309
tmpvars.append(dict(tmpvars[-1]))
311
elif ll[0] == "*switch":
312
if currswitch != "": raise Exception("System error: %s:\switches cannot be nested" % l)
313
if currnamespace != "": raise Exception("System error: %s:\n %s only allowed outside modules" % (l, ll[0]))
314
currswitch = l[len(ll[0]):].lstrip().upper()
315
if currswitch[-1] == ":": currswitch = currswitch[:-1]
316
if currswitch in reservedswitches: raise Exception("System error: switchname %s has been reserved" % currswitch)
317
if currswitch not in switches:
318
switches[currswitch] = []
319
switchlist.append(currswitch)
323
raise Exception("unknown command %s" % l)
324
switches[currswitch].append(l)
327
varstat = l.split('=')
328
varnam=varstat[0].strip()
329
varval=varstat[1].strip()
330
if len(varnam.split()) > 1:
331
raise Exception("system error: invalid command\n%s" % l)
332
tmpvars[-1][varnam] = varval
333
switchvars.append((currswitch,varnam,varval))
335
if len(l.split()) > 1:
336
raise Exception("system error: invalid command\n%s" % l)
337
if currnamespace == "":
338
if l.upper().endswith(".FLY"):
340
dat = open(l).readlines()
342
raise Exception("Cannot read %s" % l)
343
flydir = os.path.dirname(os.path.abspath(l))
345
lines = ["installdir = %s\n" % flydir] + lines
347
toplevelfiles.append(l)
349
switches[currswitch].append(l)
351
for n in range(len(spacing)):
352
if currnamespace != "":
353
switches[currswitch].append("**")
355
elif currswitch != "":
357
return toplevelfiles, switchvars
359
def assess_enabling(a, spyderdir, has_command_tempdir = None):
360
global var, has_tempdir, systempdir
361
if spyderdir != None: var["spyderdir"] = spyderdir
362
if has_command_tempdir == None:
363
has_command_tempdir = has_tempdir
364
first = (len(a.checked) == 0)
365
for swvar in a.switchvars:
366
sw,varnam,varval = swvar
367
if sw == a.currswitch:
369
if varnam.lower() == "tempdir":
370
if not has_command_tempdir:
372
changetempdir(systempdir)
375
for l in a.switches[a.currswitch]:
378
if ll[0] == "*enable":
380
switch = l[len(ll[0]):].lstrip().upper()
381
if switch in a.switches: #No checking if switch is defined!
382
a.enabled.add(switch)
383
if ll[0] == "*disable":
385
switch = l[len(ll[0]):].lstrip().upper()
386
if switch in a.enabled: #No checking if switch is defined!
387
a.enabled.remove(switch)
388
a.checked.add(a.currswitch)
391
while change == True:
393
for switch in a.switchlist:
394
if switch not in a.checked and switch in a.enabled:
396
a.currswitch = switch
397
assess_enabling(a,spyderdir,has_command_tempdir)
399
def assemble(namespaces, lines):
403
while len(lines) > 0:
407
if l[0] != "*" and l[-1] == ":" :
408
if currnamespace != "": raise Exception("System error: %s:\n Modules may not be nested" % l)
409
currnamespace = l[:-1].rstrip()
410
if currnamespace in namespaces:
411
raise Exception("System error: Module %s already defined" % (currnamespace))
412
if currnamespace not in disabled:
413
namespaces[currnamespace] = general()
414
nam = namespaces[currnamespace]
415
nam.order = len(namespaces)
416
nam.name = currnamespace
421
nam.dependent = set()
423
nam.supported = set()
425
nam.precompiled = None
428
nam.checksum_verified = False
431
nam.id = len(namespaces)
435
if ignore == True and ll[0] != "**": continue
441
elif ll[0] == "*path":
442
if currnamespace == "": raise Exception("System error: %s:\n %s only allowed in modules" % (l, ll[0]))
443
p = l[len(ll[0]):].lstrip()
445
elif ll[0] == "*import":
446
if currnamespace == "": raise Exception("System error: %s:\n %s only allowed in modules" % (l, ll[0]))
447
p = l[len(ll[0]):].lstrip()
448
nam.imports.append(p)
449
elif ll[0] == "*export":
450
if currnamespace == "": raise Exception("System error: %s:\n %s only allowed in modules" % (l, ll[0]))
451
p = l[len(ll[0]):].lstrip()
452
nam.exports.append(p)
453
elif ll[0] == "*delpath":
454
if currnamespace == "": raise Exception("System error: %s:\n %s only allowed in modules" % (l, ll[0]))
455
p = l[len(ll[0]):].lstrip()
458
elif ll[0] == "*delfile":
459
if currnamespace == "": raise Exception("System error: %s:\n %s only allowed in modules" % (l, ll[0]))
460
p = l[len(ll[0]):].lstrip()
463
elif ll[0] == "*replacefile":
464
if currnamespace == "": raise Exception("System error: %s:\n %s only allowed in modules" % (l, ll[0]))
465
p = l[len(ll[0]):].lstrip()
468
raise Exception("System error: Malformed *replacefile: %s" % (l))
469
pp[0] = pp[0].strip()
470
pp[1] = pp[1].strip()
471
if pp[0] in nam.files:
472
nam.files[nam.files.index(pp[0])] = pp[1]
473
elif ll[0] == "*include":
474
if currnamespace == "": raise Exception("System error: %s:\n %s only allowed in modules" % (l, ll[0]))
475
nam.included.add(ll[1])
476
elif ll[0] == "*patch" :
477
if currnamespace != "": raise Exception("System error: %s:\n %s only allowed outside modules" % (l, ll[0]))
478
currnamespace = l[len(ll[0]):].lstrip()
479
if currnamespace[-1] == ":": currnamespace = currnamespace[:-1]
480
if currnamespace not in namespaces:
481
if currnamespace in disabled:
484
raise Exception("System error: Module %s cannot be patched since it is undefined" % (currnamespace))
485
nam = namespaces[currnamespace]
486
elif ll[0] == "*select": #modules that are defined later are still added!
488
for nam in namespaces:
489
if nam not in ll[1:]:
491
delspaces.append(nam)
492
for nam in delspaces: namespaces.pop(nam)
493
elif ll[0] == "*deselect":
495
for nam in namespaces:
498
delspaces.append(nam)
499
for nam in delspaces: namespaces.pop(nam)
500
elif ll[0] == "*enable" :
502
elif ll[0] == "*disable" :
505
raise Exception("unknown command %s" % l)
507
if currnamespace == "": raise Exception
508
psplit = l.split(".")
509
if len(psplit) != 2: raise Exception("System error: file name %s should contain exactly one dot" % l)
510
ext = psplit[1].upper()
511
if ext == "SPY" or ext == "PY":
514
if not os.path.exists(l):
515
raise Exception("System error: file name %s does not exist" % l)
516
lines = open(l).readlines() + lines
518
raise Exception("System error: file name %s must be Spyder or Python file" % l)
522
def analyze_python_file(system, fil, lines, namespace, iscompiled, make_definitions=True):
525
if len(l) < 2: continue
526
if l[0] != "#": break
527
if l[:2] != "##": continue
529
l1 = l.split()[0].rstrip()
530
l2 = l[len(l1):].lstrip()
532
for n in range(0,len(l2)): l2[n] = l2[n].strip()
534
if namespace.iscore == True:
535
raise Exception("System error in %s: module may not contain core files and DEFINE metastatements" % (namespace.name))
536
namespace.iscore = False
539
raise Exception("System error in file %s: defined type %s must start with a capital" % (fil,ll))
540
if ll == "Spyder" or ll == "Delete": raise Exception("System error in file %s: defined type may not be 'Spyder'" % (fil))
541
if ll in system and system[ll].definition != None and system[ll].definition != namespace.name:
542
raise Exception("System error in file %s: type %s already defined in %s" % (fil, ll, system[ll].definition))
543
if ll not in system: system[ll] = SystemType()
544
if make_definitions == True: system[ll].definition = namespace.name
545
namespace.defined[ll] = ""
546
elif l1 == "SUPPORT":
547
if namespace.iscore == True:
548
raise Exception("System error in %s: module may not contain core files and SUPPORT metastatements" % (namespace.name))
549
namespace.iscore = False
551
if ll == "None": continue
553
raise Exception("System error in file %s: supported type %s must start with a capital" % (fil,ll))
554
if ll == "Spyder" or ll == "Delete": raise Exception("System error in file %s: defined type may not be 'Spyder' or 'Delete'" % (fil))
555
if ll not in system: system[ll] = SystemType()
556
system[ll].support.add(namespace.name)
557
namespace.supported.add(ll)
558
elif l1 == "CHECKSUM":
559
if iscompiled == False:
560
raise Exception("System error in file %s: only compiled file may contain CHECKSUM metastatement" % (fil))
562
raise Exception("System error in file %s: malformed CHECKSUM metastatement" % (fil))
563
checksum = l[len(l1):].lstrip()
564
namespace.checksum = checksum #checksum of the SOURCE plus CORE SOURCE, not of the file itself!
566
if namespace.iscore == True:
567
raise Exception("System error in %s: module may not contain core files and NEEDED metastatements" % (namespace.name))
568
namespace.iscore = False
571
raise Exception("System error in file %s: needed type %s must start with a capital" % (fil,ll))
572
if ll == "Spyder" or ll == "Delete": raise Exception("System error in file %s: needed type may not be 'Spyder'" % (fil))
573
namespace.neededtypes.add(ll)
574
elif l1 == "DEPENDENT":
575
if iscompiled == False:
576
raise Exception("System error in file %s: only compiled file may contain NEEDED metastatement" % (fil))
577
if namespace.iscore == True:
578
raise Exception("System error in %s: module may not contain core files and DEPENDENT metastatements" % (namespace.name))
579
namespace.iscore = False
580
l2 = l[len(l1):].split()
582
raise Exception("System error in file %s: malformed DEPENDENT metastatement" % (fil))
583
checksum = l2[1].strip()
584
namespace.dependent.add((l2[0], checksum))
586
if namespace.iscore == False:
587
raise Exception("System error in %s: module may not contain core files and Spyder files/meta statements" % (namespace.name))
588
namespace.iscore = True
589
else: raise Exception("System error in file %s:\n Unrecognized metacommand %s" % (fil, l1))
590
if iscompiled == True and namespace.iscore != True: namespace.iscore = False
593
def compile_core_namespace(system, namespace):
594
global corechecksum, anyfound
597
if len(namespace.paths) > 0: path = namespace.paths[0]
598
if has_tempdir: fil = namespace.name
599
else: fil = os.path.join(path, namespace.name)
600
fil += "_MODULE_spy.py"
601
namespace.compiledfile = fil
602
namespace.precompiled = False
603
namespace.neededtypes = set()
604
if os.path.exists(fil):
606
d = f.read().replace('\r\n','\n').rstrip('\n')
607
lines = d.split("\n")
610
analyze_python_file(system, fil, lines, namespace, True, False)
611
namespace.precompiled = None
613
for filename in namespace.files:
615
for p in namespace.paths:
616
fil = os.path.join(p, filename)
617
if os.path.exists(fil):
619
d = f.read().replace('\r\n','\n').rstrip('\n')
620
lines = d.split('\n')
622
namespace.codefiles.append(fil)
625
if filename.upper().endswith("SPY"):
626
if namespace.iscore == True:
627
raise Exception("System error in %s: module may not contain core files and Spyder files" % (namespace.name))
628
namespace.iscore = False
629
elif filename.upper().endswith("PY"):
630
if namespace.precompiled == False:
631
analyze_python_file(system, fil,lines, namespace, False)
633
raise Exception("Only .spy and .py files can be present in modules")
636
if anyfound == False:
637
raise Exception("Spyder could not locate its core functions. Your Spyder install seems to be broken")
638
else: raise Exception("System error: cannot find %s in module %s" % (filename,namespace.name))
640
if namespace.iscore == True:
641
checksum = hex(zlib.adler32(source))
642
if namespace.precompiled == None:
643
namespace.precompiled = True
644
if checksum != namespace.checksum:
645
namespace.precompiled = False
646
corechecksum = zlib.adler32(source, corechecksum)
647
if namespace.precompiled == False:
649
#print >> sys.stderr, "compiling core module '%s'..." % namespace.name
650
f = open(namespace.compiledfile, "w")
652
f.write("## CHECKSUM %s\n\n" % checksum)
653
for fil in namespace.codefiles:
654
l = "execfile(r\"%s\")\n" % os.path.abspath(fil)
660
filelist = namespace.compiledfile[:-3] + "_file.list"
661
f = open(filelist, "w")
662
for l in namespace.codefiles:
666
namespace.codefiles = []
667
f = open(namespace.compiledfile[:-3] + "_file.list")
671
namespace.codefiles.append(ll)
675
#print >> sys.stderr, "executing core module '%s'..." % namespace.name
676
shell = {'Spyder':Spyder}
677
Spyder.__currpaths__ = namespace.paths
678
head, tail = headtailcode(namespace.name, namespace.paths, namespace.imports,namespace.exports)
679
#source = head + '\n' + source + tail + '\n'
681
exec(head % dict(shell="shell"))
683
exec(tail % dict(shell="shell"))
685
#dump = open("dump.py", "w")
690
if validvar(var) and var != 'Spyder':
691
inheritedtypes[var] = {}
692
namespace.source = source
693
namespace.compiled = True
694
namespace.calledtypes = set()
695
else: namespace.defined = {}
697
def compile_namespace(system, namespaces, namespace):
698
if namespace.checksum_verified == False:
699
compiledfiles = set()
700
fil = namespace.compiledfile
701
if not (os.path.exists(fil[:-3] + "_called.types") and os.path.exists(fil[:-3] + "_defined.types") and os.path.exists(fil[:-3] + "_file.list")):
702
namespace.precompiled = False
703
namespace.supported = set()
704
namespace.defined = {}
705
namespace.source = ""
706
namespace.dependent = set()
708
f = open(fil[:-3] + "_file.list")
712
if l.strip().endswith("_spy.py") and not os.path.exists(l.strip()):
713
namespace.precompiled = False
714
namespace.supported = set()
715
namespace.defined = {}
716
namespace.source = ""
717
namespace.dependent = set()
722
compiledfiles.add(ll)
725
for n in range(0,len(namespace.files)):
726
filename = namespace.files[n]
728
for p in namespace.paths:
729
fil = os.path.join(p, filename)
730
if os.path.exists(fil):
732
if filename.upper().endswith("SPY"):
734
mdir = namespace.name
735
if not os.path.exists(mdir):
737
foundfiles.add(mdir + os.sep + os.path.basename(fil[:-4])+"_spy.py")
739
foundfiles.add(fil[:-4]+"_spy.py")
741
d = f.read().replace('\r\n','\n').rstrip('\n')
747
d = f.read().replace('\r\n','\n').rstrip('\n')
749
lines = d.split('\n')
751
namespace.files[n] = fil
753
if ok == False: raise Exception("System error: cannot find %s" % filename)
754
checksum = hex(zlib.adler32(source, corechecksum))
755
if namespace.precompiled == None:
756
if checksum != namespace.checksum or len(foundfiles ^ compiledfiles) > 0:
757
namespace.precompiled = False
758
namespace.supported = set()
759
namespace.defined = {}
760
namespace.source = ""
761
namespace.dependent = set()
762
else: namespace.precompiled = True
763
namespace.checksum = checksum
764
namespace.checksum_verified = True
766
if namespace.precompiled == True:
767
if not hasattr(namespace,"dependent_copy"):
768
namespace.dependent_copy = namespace.dependent
769
#check if the dependency namespaces are in the system, and identical in checksum
770
dep = list(namespace.dependent_copy)
771
namespace.dependent_copy = set()
772
for n in range(0, len(dep)):
775
if d[0] not in namespaces:
777
elif namespaces[d[0]].compiled == False:
778
namespace.dependent_copy.add(d)
779
elif namespaces[d[0]].checksum != d[1]:
782
namespace.precompiled = False
783
namespace.supported = set()
784
namespace.defined = {}
785
namespace.neededtypes = set()
786
namespace.dependent = set()
787
namespace.source = ""
789
if ok == True: namespace.dependent = namespace.dependent_copy
790
if namespace.precompiled == True and len(namespace.dependent) == 0: #every test has been passed
791
analyze_python_file(system, namespace.compiledfile, namespace.source.splitlines(), namespace, True)
792
namespace.compiled = True
794
f = open(namespace.compiledfile[:-3] + "_defined.types")
795
d = f.read().replace('\r\n','\n')
797
for l in d.splitlines():
799
typ, s = l[:sep], l[sep+1:]
800
namespace.defined[typ] = {}
803
p = quotematch.finditer(s)
805
mask += s[pos:pp.start()] + "*" * (pp.end()-pp.start())
808
mask = mask.replace('{', '[').replace('}',']')
809
mask = mask.replace('(', '[').replace(')',']')
810
mask = mask.replace(r'\\', '**')
818
namespace.defined[typ] = dictparse(s,m)
819
f = open(namespace.compiledfile[:-3] + "_called.types")
820
d = f.read().replace('\r\n','\n')
822
namespace.calledtypes = set(d.splitlines())
824
namespace.codefiles = []
825
f = open(namespace.compiledfile[:-3] + "_file.list")
829
namespace.codefiles.append(ll)
831
for var in namespace.defined:
832
if var not in system:
833
system[var] = SystemType()
834
if system[var].definition != namespace.name and system[var].definition != None:
835
raise Exception("compile error: type %s twice defined in modules %s and %s" % (var, namespace.name, system[var].definition))
836
system[var].definition = namespace.name
837
if namespace.precompiled == False:
843
newnt = copy(namespace.neededtypes)
844
for nt in namespace.neededtypes:
846
system[nt] = SystemType()
847
if system[nt].definition != None:
848
depnam = namespaces[system[nt].definition]
849
if depnam.id > namespace.id:
850
raise Exception("ERROR: Module %s defines type %s, which is dependent on module %s, which is defined later in system.fly\nChange the order of modules" %(namespace.name, nt, depnam.name))
851
if depnam.compiled == True:
852
namespace.dependent.add((depnam.name, depnam.checksum))
854
elif depnam.name == namespace.name:
856
namespace.neededtypes = newnt
857
if len(namespace.files) == 0:
858
namespace.calledtypes = set()
859
namespace.compiled = True
860
elif len(namespace.neededtypes) == 0:
861
filename = namespace.files[namespace.filecompiled]
863
s = f.read().replace('\r\n','\n')
865
if filename.upper().endswith(".SPY"):
866
#print "NAMESPACE", namespace.name
867
#print "FILE", filename
868
inheritedtypes0 = inheritedtypes.copy()
869
for v in namespace.defined:
870
inheritedtypes0[v] = namespace.defined[v]
871
result, neededtypes, definedtypes, supportedtypes = Spydercompile(Spyder, s, unimethodlist, unimethods, macros, statements, inheritedtypes0, namespace.name, filename)
872
#print "RESULT", result
873
#print "NEEDEDTYPES", neededtypes
874
#print "DEFINEDTYPES", definedtypes
875
#print "SUPPORTEDTYPES", supportedtypes
877
namespace.neededtypes = neededtypes
879
result = result.lstrip('\n') + '\n'
880
linenr = len(result.splitlines())
882
mdir = namespace.name
883
if not os.path.exists(mdir):
885
spynam = mdir + os.sep + os.path.basename(filename)[:-4]+"_spy.py"
886
else: spynam = filename[:-4]+"_spy.py"
887
spyfile = open(spynam, "w")
888
spyfile.write(result)
890
namespace.codefiles[namespace.filecompiled] = spynam
891
namespace.source += result
892
namespace.supported = namespace.supported.union(supportedtypes)
893
for var in definedtypes:
894
if var in namespace.defined:
895
raise Exception("compile error: type %s twice defined in module %s" % (var, namespace.name))
896
if var not in system:
897
system[var] = SystemType()
898
if system[var].definition != namespace.name and system[var].definition != None:
899
raise Exception("compile error: type %s twice defined in modules %s and %s" % (var, namespace.name, system[var].definition))
900
system[var].definition = namespace.name
901
namespace.defined[var] = definedtypes[var]
903
namespace.filecompiled += 1
905
#if filename not in filedefined:
906
s = s.lstrip('\n') + '\n\n'
907
namespace.source += s
908
lines = s.split("\n")
909
tmpnamespace = general()
910
tmpnamespace.name = namespace.name
911
tmpnamespace.defined = {}
912
tmpnamespace.neededtypes = set()
913
tmpnamespace.supported = set()
914
tmpnamespace.iscore = False
915
analyze_python_file(system, filename,lines, tmpnamespace, False)
916
#filedefined[filename] = tmpnamespace.defined
917
namespace.supported = namespace.supported.union(tmpnamespace.supported)
918
if len(tmpnamespace.neededtypes) > 0:
919
namespace.neededtypes = tmpnamespace.neededtypes
922
#if filedefined[filename] > 0:
923
#if filename.upper().endswith(".SPY"):
924
#shell = {'Spyder':Spyder}
925
#dump = open("dump.py", "w")
926
#dump.write(namespace.source)
928
#exec(namespace.source, shell)
930
for var in tmpnamespace.defined:
931
if var in namespace.defined:
932
raise Exception("compile error: type %s twice defined in module %s" % (var, namespace.name))
933
namespace.defined[var] = {}
934
if var not in system:
935
system[var] = SystemType()
936
if system[var].definition != namespace.name and system[var].definition != None:
937
raise Exception("compile error: type %s twice defined in modules %s and %s" % (var, namespace.name, system[var].definition))
938
system[var].definition = namespace.name
939
#namespace.defined[var] = definedtypes[var]
940
namespace.defined[var] = tmpnamespace.defined[var]
944
namespace.filecompiled += 1
945
if namespace.filecompiled == len(namespace.files) and len(namespace.neededtypes) == 0:
946
if "SILENT" not in assesspar.enabled: print >> sys.stderr, "compiling module '%s'" % namespace.name
947
#filteredsource0 = commentmatch.split(namespace.source)
949
#for f in filteredsource0: filteredsource += f
950
filteredsource = namespace.source
951
f = open(namespace.compiledfile, "w")
952
f.write("\n## CHECKSUM %s\n\n" % namespace.checksum)
953
for v in namespace.defined:
954
f.write("## DEFINE %s\n" % v)
955
for v in namespace.supported:
956
if v not in namespace.defined:
957
f.write("## SUPPORT %s\n" % v)
958
for v in namespace.dependent:
959
f.write("## DEPENDENT %s %s\n" % (v[0], v[1]))
960
f.write("\n" + filteredsource)
962
definedtypes = namespace.compiledfile[:-3] + "_defined.types"
963
f = open(definedtypes, "w")
964
#f.write(repr(namespace.defined))
965
for t in namespace.defined:
966
print >>f, t, repr(namespace.defined[t])
969
filelist = namespace.compiledfile[:-3] + "_file.list"
970
f = open(filelist, "w")
971
for l in namespace.codefiles:
974
namespace.calledtypes = get_called_types(namespace.source)
975
calledtypes = namespace.compiledfile[:-3] + "_called.types"
976
f = open(calledtypes, "w")
977
for t in namespace.calledtypes:
981
namespace.compiled = True
984
if namespace.compiled == True:
985
for v in namespace.defined:
986
inheritedtypes[v] = namespace.defined[v]
987
Spyder.core.__defined[v] = namespace.defined[v]
989
def visit_node(node, ret):
990
nodetype = node.__class__.__name__
991
if nodetype == "Name":
992
name = node.getChildren()[0]
994
while name0.endswith("Array"): name0 = name0[:-len("Array")]
997
for child in node.getChildNodes():
998
visit_node(child, ret)
1000
def get_called_types(code, raise_syntaxerror = True):
1003
ast = compiler.parse(code)
1005
#at any point, it will crash, just depends if we want to let it crash now or later...
1009
if raise_syntaxerror == False: return set()
1014
#print "Compilation error, check dump.py to fix it"
1015
#dump = open("dump.py", "w")
1020
visit_node(ast, ret)
1023
def determine_called_namespaces(system, namespaces, name):
1024
namespace = namespaces[name]
1025
if hasattr(namespace, "called"): return
1026
namespace.called = []
1027
for t in namespace.calledtypes:
1028
while t.endswith("Array"): t = t[:-len("Array")]
1029
if t not in system or system[t].definition not in namespaces:
1030
raise Exception("System error: module %s needs Spyder type %s and no system module can provide it" % (name,t))
1032
if namespaces[tt.definition].id > namespace.id:
1033
raise Exception("System error: module %s needs Spyder type %s and the defining system module %s is later in system.fly\nPlease change the order of modules" % (name,t,tt.definition))
1034
newnames = set((tt.definition,))
1035
if hasattr(tt, "supported") and tt.supported != None: newnames = newnames.union(set(tt.supported))
1038
determine_called_namespaces(system, namespaces, n)
1039
if n not in namespace.called:
1040
for nn in namespaces[n].called:
1041
if nn not in namespace.called: namespace.called.append(nn)
1042
namespace.called.append(name)
1043
for i in namespace.included:
1044
if i not in namespace.called: namespace.called.append(i)
1046
def headtailcode(modulename, paths, imports, exports):
1047
ret1 = "Spyder.core.__currpaths = %s\n" % repr(paths)
1048
ret1 += "if \"%s\" not in Spyder.__dict__: Spyder.%s = Spyder.core.namespace()\n" % (modulename, modulename)
1050
txt = "\""+ i + "\",\"" + i + "\""
1055
if (len(ii) != 1 and (len(ii) != 3 or ii[1] != "as")) or validvar(ii[0]):
1056
raise Exception("Malformed import statement in %s: *import %s" % (modulename,i))
1058
txt = "\"" + ii[0] + "\",\"" + ii[2] + "\""
1060
if val.find(".") > -1:
1061
val = val[:val.index(".")]
1062
ret1 += "Spyder.core_init.__fullimport(%s, %%(shell)s)\n" % (txt)
1063
ret1 += "Spyder.%s.%s = %%(shell)s[\"%s\"]\n" % (modulename, val, val)
1069
if (len(ii) != 1 and (len(ii) != 3 or ii[1] != "as")) or validvar(ii[0]):
1070
raise Exception("Malformed export statement in %s: *export %s" % (modulename,i))
1073
if nam.find(".") > -1:
1074
raise Exception("Malformed export statement in %s: *export %s" % (modulename,i))
1075
ret2 += "Spyder.%s.%s = %%(shell)s[\"%s\"]\n" % (modulename, val, nam)
1078
def import_namespace(modulename,files, paths,imports,exports,deftypes):
1080
head, tail = headtailcode(modulename, paths, imports, exports)
1081
ret = "__subshell = globals().copy()\n"
1082
ret += head % dict(shell="__subshell") + "\n"
1084
ret += "execfile(r\"%s\", __subshell)\n" % os.path.abspath(f)
1085
for typ in deftypes:
1086
ret += "%s = __subshell[\"%s\"]\n" % (typ, typ)
1087
for n in range(Spyder.core.__arraycount[typ]):
1088
typ2 = typ + (n+1) * "Array"
1089
ret += "%s = __subshell[\"%s\"]\n" % (typ2, typ2)
1090
ret += tail % dict(shell="__subshell") + "\n"
1093
def systemcompile(lines, enabledswitches=set(),spyderdir=None,has_tempdir0=False):
1094
global has_tempdir, systempdir, namespaces, namespacelist, assesspar
1096
has_tempdir = has_tempdir0
1101
toplevelfiles, switchvars = parse(lines, switches, switchlist,spyderdir)
1102
assesspar = general()
1103
assesspar.switches = switches
1104
assesspar.switchvars = switchvars
1105
assesspar.switchlist = switchlist
1106
assesspar.currswitch = ""
1107
assesspar.enabled = enabledswitches
1108
assesspar.checked = set()
1109
assess_enabling(assesspar, spyderdir)
1112
for s in switchlist:
1113
if s in assesspar.enabled: l += switches[s]
1114
for s in enabledswitches:
1115
if s not in switchlist and s != "NOCOMPILE" and s != "SILENT":
1116
print >> sys.stderr, "WARNING: unknown switch %s" % s
1117
assemble(namespaces, l)
1119
for nr in range(len(namespaces)):
1122
for n in namespaces:
1123
if n not in namespacelist and namespaces[n].order < minnr:
1124
minnr = namespaces[n].order
1126
namespacelist.append(minn)
1127
#assert len(namespacelist) == len(namespaces)
1128
for n in namespacelist:
1129
compile_core_namespace(system, namespaces[n])
1133
for n in namespacelist:
1134
if namespaces[n].compiled == False:
1135
compile_namespace(system, namespaces, namespaces[n])
1136
if namespaces[n].compiled == True:
1138
for n in namespacelist:
1139
if namespaces[n].compiled == False:
1140
raise Exception("System error: cannot compile module %s due to the following undefined types:" % namespaces[n].name, list(namespaces[n].neededtypes))
1142
for n in namespacelist:
1143
if namespaces[n].iscore and len(namespaces[n].codefiles) > 0:
1144
corecode += import_namespace(n, namespaces[n].codefiles, namespaces[n].paths, namespaces[n].imports, namespaces[n].exports, namespaces[n].defined) % dict(shell="currnamespace")
1146
determine_called_namespaces(system, namespaces, n)
1148
type_to_namespaces = {}
1151
if system[t].definition == None: directspaces = []
1152
else: directspaces = [system[t].definition,]
1153
if hasattr(system[t], "support"):
1154
directspaces += system[t].support
1155
for space in directspaces:
1156
for nam in namespaces[space].called:
1157
nr = namespacelist.index(nam)
1158
if (nam, nr) not in n:
1160
type_to_namespaces[t] = n
1161
return corecode, type_to_namespaces, namespaces, toplevelfiles, systempdir
1165
#- EXECORE and METACORE (METACORE to exec during compilation (Python),
1166
# EXECORE to exec during runtime (target language)
1167
# std CORE to do both (Python)
1168
# this is a FILE attribute not a MODULE attribute
1169
#- SWITCH to assume that the system did not change (no recompile)