D7net
Home
Console
Upload
information
Create File
Create Folder
About
Tools
:
/
proc
/
self
/
root
/
proc
/
self
/
root
/
opt
/
cloudlinux
/
venv
/
lib
/
python3.11
/
site-packages
/
guppy
/
gsl
/
Filename :
Main.py
back
Copy
from guppy.etc.Descriptor import property_nondata from guppy.gsl.Exceptions import * class SpecEnv: def __init__(self, mod): self.mod = mod self.imported_packages = {} self.importing_packages = {} self.error_reports = [] self.num_errors = 0 self.num_warnings = 0 def errmsg_context(self, context): linetext = '' filename = '<unknown file>' if context is not None: node = context # Assume it's a node - that's all we use for now lineno = node.index + 1 src = node.src if src is not None: filename = src.filename linetext = src.get_line(index=context.index) print('%s:%s:' % (filename, lineno)) if linetext: print(' %r' % linetext) def error(self, message, context=None, exception=ReportedError, more=(), harmless=0): self.error_reports.append( (message, context, exception, more, harmless)) if harmless: self.num_warnings += 1 else: self.num_errors += 1 self.errmsg_context(context) if harmless: print('* %s' % message) else: print('*** %s' % message) print() for msg, ctx in more: self.errmsg_context(ctx) print(' %s' % msg) print() if self.debug: import pdb pdb.set_trace() else: if self.num_errors >= self.max_errors: raise TooManyErrors('Too many errors, giving up') if exception is not None: raise exception def get_filers(self, documents): filers = [] for d in documents: filers.extend(d.get_filers(self.output_dir)) return filers def import_package(self, name, context): pac = self.imported_packages.get(name) if pac is None: if name in self.importing_packages: self.error('Invalid mutual import involving packages %r' % ( list(self.importing_packages.keys()),), context) self.importing_packages[name] = 1 filename = name.replace('.', self.mod.IO.path.sep)+'.gsl' ip = self.package_of_filename(filename, name) pac = self.mkPackage(ip) self.imported_packages[name] = pac del self.importing_packages[name] return pac def link_documents(self, documents): defines = {} links = {} def walk(node): t = node.tag if t == 'link_to': name = node.arg.strip() links.setdefault(name, []).append((d, node)) elif t == 'define': name = node.arg.strip() defines.setdefault(name, []).append((d, node)) elif t == 'to_tester_only': return for ch in node.children: walk(ch) for d in documents: node = d.get_result() walk(node) for name, ds in list(defines.items()): if len(ds) > 1: print('Duplicate definition of name %r, defined in:' % name) for (d, node) in ds: print(' %s line %s' % (d.get_doc_name(), node.index+1)) print('Will use the first one.') nodefs = [] for name, ds in list(links.items()): if name not in defines: used = {} for (d, node) in ds: used[d.get_doc_name()] = 1 node.tag = 'link_to_unresolved' used = list(used.keys()) used.sort() used = ', '.join(used) nodefs.append('%s used in %s' % (name, used)) else: defd, defnode = defines[name][0] for (d, node) in ds: if d is defd: node.tag = 'link_to_local' else: node.tag = 'link_to_extern' node.children = (defd.doc_name_node,)+node.children if nodefs: nodefs.sort() print('Unresolved links:') for nd in nodefs: print(' ', nd) def mkPackage(self, sub): pac = PackageDescription(self, sub, sub) pac.output_dir = self.output_dir pac.resolve_all() return pac def package_of_filename(self, filename, packname=None, nostrip=1, input_string=None): mod = self.mod if packname is None: if filename.endswith('.gsl'): packname = filename[:-4] else: packname = filename packname = packname.replace(mod.IO.path.sep, '.') if self.input_dir: filename = mod.IO.path.join(self.input_dir, filename) else: filename = mod.IO.path.abspath(filename) if input_string is not None: data = input_string else: data = mod.IO.read_file(filename) md5 = mod.md5() md5.update(b'.filename: %s\n' % filename.encode('utf-8')) md5.update(b'.packname: : %s\n' % packname.encode('utf-8')) md5.update(data.encode('utf-8')) digest = md5.digest() if digest in mod.package_cache: return mod.package_cache[digest] node = mod.SpecNodes.node_of_string(data, filename, nostrip=nostrip) numerr = self.num_errors print('Making package subject %r' % packname) package = PackageSubject(mod, self, node, packname, filename) if numerr == self.num_errors: mod.package_cache[digest] = package return package def process_main(self, filename, input_dir=None, output_dir=None, debug=False, max_errors=None, process_despite_errors=False, raise_at_errors=False, input_string=None ): if input_dir is None: input_dir = self.mod.input_dir self.input_dir = input_dir if output_dir is None: output_dir = '/tmp' self.output_dir = output_dir self.debug = debug if max_errors is None: max_errors = self.mod.max_errors self.max_errors = max_errors try: pac = self.mkPackage(self.package_of_filename( filename, input_string=input_string)) documents = pac.get_documents() if not documents: self.error('No documents specified.', exception=None, harmless=1) if not self.num_errors or process_despite_errors: print('Linking') self.link_documents(documents) if not self.num_errors or process_despite_errors: filers = self.get_filers(documents) except TooManyErrors: giving_up = ' giving up --' else: giving_up = '' if not self.num_errors: for filer in filers: f = self.mod.Filer.filer(filer) print('Writing: ', ', '.join(list(f.writefile_names))) f.write() if self.num_warnings: print('* %d warning%s reported.' % ( self.num_warnings, 's'[:self.num_warnings > 1])) if self.num_errors: print('*** %d error%s reported --%s no files written.' % ( self.num_errors, 's'[:self.num_errors > 1], giving_up)) if raise_at_errors: raise HadReportedError('Some error has been reported.') class UntypedDescription: def __init__(self, env, tgt, src): self.env = env self.pac = env.pac self.mod = env.mod self.tgt = tgt self.src = src def combine_with_subject(self, subject): self.combined_subjects.append(subject) def resolve_all(self): self.resolve_primary() self.resolve_lookuped() def resolve_primary(self): self.resolve_type() self.resolve_tgt() def resolve_type(self): dc = self.tgt.description_class if not hasattr(dc, 'd_tag'): self.d_tag = self.tgt.tag self.tgtfullname = self.mod.tgt_prefix+self.tgt.fullname self.tgtnode = self.tgt.node self.tgtlastname = self.tgt.lastname self.srcnode = self.tgt.node self.srcfullname = self.src.fullname self.srclastname = self.tgt.lastname self.__class__ = dc class Description: d_max_occur = None # Max occurence as an aspect if a number d_sub = () # Tags of allowed sub-aspects d_type = 'other' d_is_def = 0 is_lookuped = False is_synthetic = False # Set if it was made not to correspond with a user node the_less_specific_descr = None args = () def aspects_extend(self, as_): for asp in as_: try: k = asp.src.definame # k = asp.tgt.definame # Humm if k: w = self.localview.get(k) if w: if w is asp: # May happen eg as in test16, for a product # But it is somewhat mystical. continue self.error('Duplicate aspect %r (may be correct in future).' % (k,), w.src.node, DuplicateError) self.localview[k] = asp bn = self.aspects_by_tag.setdefault(asp.d_tag, []) oc = asp.d_max_occur if oc is not None: if len(bn) + 1 > oc: self.error('More than %d %r aspects.' % ( oc, asp.d_tag), asp.src.node) bn.append(asp) self.aspects.append(asp) except ReportedError: pass def aspects_extend_by_subjects(self, subjects): for v in subjects: try: asp = UntypedDescription(self, v, v) asp.resolve_primary() self.aspects_extend((asp,)) except ReportedError: pass def deftgt(self, forme=None): if forme is None: forme = self try: tgtview = self.tgtview except AttributeError: self.env.deftgt(forme) else: if forme.tgtfullname in tgtview: self.error('Duplicate definition of %r' % forme.tgtfullname, forme.src.node) tgtview[forme.tgtfullname] = forme def error(self, msg, node=None, exception=ReportedError, **kwds): return self.pac.env.error(msg, node, exception, **kwds) def resolve_lookuped(self): if not self.is_lookuped: self.is_lookuped = 1 self.resolve_aspects() def resolve_tgt(self): self.deftgt() def find_aspects(self, tag='*', *tags): al = [] tag = tag.replace(' ', '_') if tag in ('*', 'arg'): for a in self.args: a.resolve_lookuped() al.append(a) if tag == '*': for a in self.aspects: a.resolve_lookuped() al.append(a) return al tags = (tag,) + tags for a in self.aspects: if a.d_tag in tags: a.resolve_lookuped() al.append(a) return al def find_arg_aspects(self): al = [] for a in self.args: a.resolve_lookuped() al.append(a) for a in self.aspects: if a.d_tag in ('arg', 'seq', 'repeat', 'alt', 'args', 'optionals', 'key_arg', 'draw', 'no_arg'): a.resolve_lookuped() al.append(a) return al def find_kind_aspects(self): kas = [] for asp in self.find_aspects('*'): if asp.d_tag in ('attribute', 'mapping', 'kind', 'either', 'kind_of', 'superkind', 'superkind_of'): kas.append(asp) else: pass return kas def merge_policy(self, descrs): return descrs def get_descr_for_aspect(self, aspect): if not self.aspects and self.the_less_specific_descr is not None: return self.the_less_specific_descr.get_descr_for_aspect(aspect) return self def get_atom_beams(self): aspects = self.find_aspects('*') aks = [] for asp in aspects: if asp.d_tag in ('attribute', 'mapping', 'either', 'operator', 'inplace_operator', 'reverse_operator', 'function_operator', 'delitem', 'getitem', 'setitem', ): aks.append(beam(self, asp)) elif asp.d_tag in ('kind', 'kind_of', 'subkind_of') and asp is not self: a = beam(self, asp) for b in asp.get_atom_beams(): aks.append(a + b) return aks def get_aspects_kind(self, aspects=None): if aspects is None: aspects = self.find_aspects('*') aks = [] for asp in aspects: if asp.d_tag in ('attribute', 'mapping', 'either', 'operator', 'inplace_operator', 'reverse_operator', 'function_operator', 'delitem', 'getitem', 'setitem', ): aks.append(asp) elif asp.d_tag in ('kind', 'kind_of', 'subkind_of') and asp is not self: aks.extend(asp.get_atom_kinds()) return aks def get_atom_kinds(self): return self.get_aspects_kind([self] + self.find_aspects('*')) def get_examples(self, get_all=False): examples = [] exs = self.find_aspects('example') for ex in exs: examples.extend(ex.get_examples()) return examples def get_re(self, opt): if opt.get('get_examples'): exres = [self.mod.RE.Single(x) for x in self.get_examples()] if not exres: self.error('Test coverage error: no examples specified.', self.tgt.node, CoverageError) return self.mod.RE.Union(*exres) else: return self.mod.RE.Single(self) def get_most_specific_descrs(self, descrs): nds = [] for d in descrs: nds = [x for x in nds if not d.is_more_specific_than(x)] for x in nds: if x is d: break if x.is_more_specific_than(d): break else: nds.append(d) return nds def get_package(self): return self.pac def is_more_specific_than(self, d): r = self.the_less_specific_descr return r is d or (r is not None and r.is_more_specific_than(d)) def get_self_name(self): def find(e): sa = e.find_aspects('self') if sa: # length = 1, has been checked assert len(sa) == 1 return sa[0].src.node.arg.strip() if e.d_tag != 'package': return find(e.env) return None return find(self) def gen_description_doc(self, out): ds = self.find_aspects('description') if not ds: out.gen_text('<NO DESCRIPTION OF %r>' % self.tgtfullname) else: for d in ds: d.gen_doc(out) def get_id_name(self): return self.tgtfullname def get_link_name(self): return self.tgtfullname def get_local_name(self): return self.srclastname def get_test_name(self): return self.tgtfullname def get_name(self): return self.tgtfullname def get_Name(self): # To be used in Name of doc. n = self.find_aspects('name') if not n: name = self.tgtlastname else: name = n.tgt.node.arg.strip() return name def get_descr_by_subject(self, subject): return self.pac.get_descr_by_subject(subject) def init_localview(self, only_vars=0): self.localview = {} self.aspects = [] self.aspects_by_tag = {} if not only_vars: self.aspects_extend_by_subjects(self.tgt.aspects) def resolve_aspects(self): self.init_localview() if self.src.args: self.args = [self.env.get_descr_by_subject( arg) for arg in self.src.args] self.resolve_special() def resolve_special(self): # To be overridden with special checks etc. pass def get_the_one_argument(self): arg = self.src.node.arg.strip() if self.aspects: 'No children expected for %r' % self.node.tag return arg def make_and_test_kind(self, kinds): ks = [] def flatten(k): if k.d_tag == 'kind': for k1 in k.find_kind_aspects(): flatten(k1) else: ks.append(k) if (len(kinds) == 1 and kinds[0].d_tag == 'kind'): return kinds[0] for k in kinds: flatten(k) kinds = ks k = Kind() k.d_tag = 'kind' k.aspects = kinds k.tgtfullname = '(%s)' % ('&'.join([x.tgtfullname for x in kinds])) k.is_lookuped = 1 return k def make_and_kind(self, kinds): if (len(kinds) == 1 and kinds[0].d_tag in('kind', 'kind_of')): return kinds[0] k = Kind() k.d_tag = 'kind' k.aspects = kinds k.tgtfullname = '(%s)' % ('&'.join([x.tgtfullname for x in kinds])) k.is_lookuped = True k.is_synthetic = True return k def make_or_kind(self, kinds): if len(kinds) == 1: return kinds[0] else: k = Superkind() k.d_tag = 'kind' k.aspects = kinds k.tgtfullname = '(%s)' % ('|'.join([x.tgtfullname for x in kinds])) k.is_lookuped = True k.is_synthetic = True return k class Definition(Description): d_is_def = 1 d_type = 'definition' def export_aspects(self, src): src.__class__ = self.__class__ if src.d_tag == 'import': src.d_tag = self.d_tag else: if src.d_tag != self.d_tag: # Can't think of how this would happen - # so not yet converted to .error() raise ImportError('Different description tag') src.aspects_extend(self.aspects) class DescriptionDescription(Description): d_sub = ('text', ) d_tag = 'description' def gen_doc(self, out): self.srcnode.arg_accept(out) class Default(DescriptionDescription): def gen_doc(self, out): arglines = self.srcnode.arg.strip().split('\n') default = arglines[0] rest = '\n'.join(arglines[1:]) out.open('dl') out.open('dt') out.open('strong') out.gen_text('Default: ') out.close() out.gen_text(default) out.close() out.open('dd') out.gen_text(rest) self.srcnode.children_accept(out) out.close() out.close('dl') class DescriptionWithHeader(DescriptionDescription): def gen_doc(self, out): arglines = self.srcnode.arg.strip().split('\n') header = arglines[0] rest = '\n'.join(arglines[1:]) out.open('dl') out.gen_outer_dt(header) out.open('dd') out.gen_text(rest) self.srcnode.children_accept(out) out.close() out.close() class Comment(DescriptionDescription): d_tag = 'comment' pass class Either(Description): d_type = 'with_args' def get_atom_beams(self): return [beam(self)] def get_atom_kinds(self): return [self] def get_alt_kinds(self): return self.find_kind_aspects() class Import(Definition): d_sub = ('from', 'resolve_by', 'using', 'attribute', 'condition', 'description', 'comment', 'constructor', 'mapping', 'method', 'operator', 'inplace_operator', 'reverse_operator', 'function_operator', 'delitem', 'getitem', 'setitem', 'self', 'subkind_of', ) def resolve_tgt(self): self.is_lookuped = 1 using_name, using_node = self.src.imp_using_map.get( self.src.definame, (self.src.definame, self.src.node)) import_node = self.src.node ds = [self.pac.import_package(from_name, from_node). get_descr_by_name(using_name, using_node) for (from_name, from_node) in self.src.imp_froms] if len(ds) == 1: d = ds[0] else: d = Product(self, ds, ProductSubject([x.src for x in ds]), self.src.imp_resolve_mode) self.tgt = d.tgt self.tgtfullname = self.mod.tgt_prefix+self.tgt.fullname self.the_less_specific_descr = d self.init_localview(only_vars=1) d.export_aspects(self) self.aspects_extend_by_subjects(self.src.aspects) self.deftgt() def resolve_aspects(self): pass class Product(Description): def __init__(self, env, ds, src, mode): self.env = env self.mod = env.mod self.src = src self.mode = mode self.pac = env.pac tgt = ds[0].tgt for d in ds[1:]: if d.tgt is not tgt: self.error('Import error when importing from multiple packages:\n' + ' Can not make a product of %r (tgt = %r) with %r (tgt = %r)\n' % ( d.src.fullname, d.tgt.fullname, ds[0].src.fullname, ds[0].tgt.fullname) + ' because of different targets.', d.src.node) self.tgt = tgt self.ds = ds def export_aspects(self, src): for d in self.ds: d.export_aspects(src) def is_more_specific_than(self, d): for x in self.ds: if x is d or x.is_more_specific_than(d): return True return False class PackageDescription(UntypedDescription): def __init__(self, env, tgt, src): self.env = env self.pac = self self.mod = env.mod self.tgt = tgt self.src = src class ErrorDescription: d_tag = 'error' def __init__(self, env): self.env = env def get_id_name(self): return '<error>.<error>' class Package(Description): d_sub = ('and', 'comment', 'condition', 'document', 'import', 'kind', 'macro', 'superkind', ) def get_tgtdicts(self): seen = {id(self.tgtview): 1} tgtdicts = [self.tgtview] for p in list(self.imported_packages.values()): sds = p.get_tgtdicts() for sd in sds: if id(sd) not in seen: seen[id(sd)] = 1 tgtdicts.append(sd) return tgtdicts def get_descr_by_name(self, name, context=None): if name.startswith(self.mod.tgt_prefix): return self.get_descr_by_tgt_name(name, context) e = self parts = name.split('.') for part in parts: try: e = e.localview[part] except KeyError: assert context self.env.error( 'Undefined: %r in %r.' % (part, e.get_id_name()), context, exception=UndefinedError) e.resolve_lookuped() return e def get_descr_by_subject(self, subject): name = subject.fullname if name.startswith(self.srcfullname+'.'): name = name[len(self.srcfullname)+1:].strip() else: self.error('Undefined: %r' % name, subject.node) return self.get_descr_by_name(name, subject.node) def get_descr_by_tgt_name(self, name, context=None): tgtdicts = self.get_tgtdicts() descrs = [] for tgtdict in tgtdicts: if name in tgtdict: d = tgtdict[name] d.resolve_lookuped() d = d.get_descr_for_aspect('*') descrs.append(d) if not descrs: self.error('No definition of tgt %r' % name, context, UndefinedError) descrs = self.get_most_specific_descrs(descrs) if len(descrs) > 1: descrs = self.merge_policy(descrs) if len(descrs) > 1: self.error('Conflicting descriptions of %r:%r' % ( name, [d.src.fullname for d in descrs]), context, DuplicateError) return descrs[0] def get_filename(self): return self.src.filename def get_package(self): return self def resolve_tgt(self): self.tgtview = {} def resolve_aspects(self): self.imported_packages = {} self.init_localview() def import_package(self, name, context): pac = self.imported_packages.get(name) if pac is None: pac = self.env.import_package(name, context) self.imported_packages[name] = pac return pac def get_documents(self): documents = [] for doc in self.src.documents: node = doc.node doc = self.mod.Document.document(node, self) documents.append(doc) return documents class Attribute(Definition): d_sub = ('attribute', 'comment', 'description', 'description_with_header', 'either', 'kind_of', 'mapping', 'method', 'self') def export_aspects(self, src): src.__class__ = self.__class__ src.aspects_extend(self.aspects) def get_attr_name(self): return self.tgtlastname def get_name(self): return self.tgtlastname def get_kind(self): kas = self.find_kind_aspects() return self.make_and_kind(kas) def get_kind_name(self): k = self.get_kind() if k.d_tag == 'kind_of': kas = k.find_kind_aspects() if len(kas) == 1: k = kas[0] else: raise ValueError("Don't know how to name this kind, %r" % self) return k.tgtfullname def get_link_name(self): # xxx needs smoother logic s = '%s.%s' % (self.get_descr_by_subject( self.tgt.parent).get_link_name(), self.tgt.lastname) return s def get_test_kind(self): kas = self.find_kind_aspects() return self.make_and_test_kind(kas) def is_method(self): return (self.find_aspects('mapping') and not self.find_aspects('kind_of')) def get_op_name(self): return self.get_attr_name() class KindOf(Description): d_type = 'with_args' d_sub = () class SubkindOf(Description): d_type = 'with_args' d_sub = ('description',) class Kind(Definition): d_sub = ('attribute', 'condition', 'description', 'comment', 'constructor', 'example', 'mapping', 'method', 'operator', 'inplace_operator', 'reverse_operator', 'function_operator', 'self', 'subkind_of', 'delitem', 'getitem', 'setitem', ) def get_attributes(self): return self.find_aspects('attribute') def get_mappings(self): return self.find_aspects('mapping') class Superkind(Definition): d_sub = ('comment', 'description', 'example', 'superkind_of') def get_local_name(self): return self.srclastname class SuperkindOf(Description): d_type = 'with_args' def get_examples(self, enough=1): examples = Description.get_examples(self, enough) if len(examples) < enough: for ka in self.find_kind_aspects(): if ka is self: continue examples.extend(ka.get_examples(enough-len(examples))) if len(examples) >= enough: break return examples class Example(Description): d_sub = ('comment', 'description', 'in_context') partab = {"'''": "'''", '"""': '"""', '(': ')', '[': ']', '{': '}' } def get_ex_text(self): return self.src.ex_text def get_examples(self, get_all=False): return [self] def get_ctx_text(self): asp = self.find_aspects('in_context') if not asp: return '' # It is of length 1, has been checked. return asp[0].tgt.node.arg.strip() def get_use_text(self, x): return x class InContext(Description): d_max_occur = 1 class Defines(Description): d_type = 'with_args' def get_defined_tgt_names(self): return [x.tgtfullname for x in self.find_aspects('arg')] class Macro(Definition): def export_aspects(self, src): src.__class__ = self.__class__ src.tgtnode = self.tgtnode def use(self, options): return self.mod.SpecNodes.node_of_taci( 'block', '', self.tgtnode.children, self.tgtnode.index) class Self(Description): d_max_occur = 1 class Mapping(Description): d_type = 'other' d_sub = ('alt', 'arg', 'args', 'comment', 'description', 'description_with_header', 'equation', 'draw', 'key_arg', 'optionals', 'precondition', 'postcondition', 'repeat', 'returns', 'self', 'seq', ) def chk_num_args(self, min, max): re = self.get_args_re({}) xs = re.sequni() for x in xs: try: if min is not None and min == max and len(x) != min: self.error( '%s requires %d argument%s specified, got %d.' % ( self.d_tag, min, 's'[min == 1:], len(x)), self.src.node) elif min is not None and len(x) < min: self.error( '%s requires at least %d argument%s specified, got %d.' % ( self.d_tag, min, 's'[min == 1:], len(x)), self.src.node) elif max is not None and len(x) > min: self.error( '%s can take at most %d argument%s specified, got %d.' % ( self.d_tag, max, 's'[max == 1:], len(x)), self.src.node) except ReportedError: pass def get_arg_kinds(self): ak = [] for a in self.find_aspects('args'): ak.extend(list(a.args)) return ak def get_args_examples(self, mapname, top_kind): # Get arguments example, esp. for test purposes try: opt = {'get_examples': True} re = self.get_args_re(opt) coverage = 1 try: xs = re.sequni() except self.mod.RE.InfiniteError: print('Infinitely long args example for %s' % self.srcfullname) print( 'Limiting by expanding each Cleene closure 0 up to %d times.' % coverage) re = re.limited(coverage) xs = re.sequni() examples = [ArgsExample(self, tuple( x), mapname, top_kind) for x in xs] except CoverageError: return [] else: return examples def get_args_for_args(self, args, match): arglist = [] for a in self.find_arg_aspects(): t = a.d_tag if t == 'arg': name = a.get_name() if name in match: v = args.get_arg_value(match[name]) else: ex = a.get_examples() if not ex: # I have been able to cause this to happen in test67. self.error( 'Test coverage error: Can not create precondition for %r\n -- no examples specified for the argument above.' % args.mapping.tgtfullname, a.src.node ) v = ex[0] arglist.append(v) else: assert 0 # raise ConditionError, 'Can not match this precondition' return ArgsExample(self, tuple(arglist), args.mapname, args.top_kind) def get_args_re(self, opt): re = self.mod.RE.Epsilon for a in self.find_arg_aspects(): re += a.get_re(opt) return re def get_arguments(self): # Get the arguments subjects, for doc description purposes return self.find_arg_aspects() def get_return_kind(self): return self.make_and_kind([x.get_kind() for x in self.find_aspects('returns')]) def get_return_test_kind(self): return self.make_and_test_kind([x.get_test_kind() for x in self.find_aspects('returns')]) class ArgsExample: def __init__(self, mapping, egs, mapname, top_kind): self.mapping = mapping self.egs = egs self.mapname = mapname self.top_kind = top_kind self.negs = [mapname(x) for x in egs] def __str__(self): return ', '.join(self.negs) def get_arg_value(self, name): i = 0 for a in self.mapping.find_arg_aspects(): t = a.d_tag if t == 'arg': if a.get_name() == name: return self.egs[i] else: raise ConditionError('No argument matches: %r' % name) i += 1 def get_preconditions(self): return self.mapping.find_aspects('precondition') def get_postconditions(self): return self.mapping.find_aspects('postcondition') def get_setups_for_preconditions(self): pres = self.get_preconditions() if not pres: return [] kind = self.top_kind map = self.mapping pres = map.find_aspects('precondition') if pres: for a in kind.find_aspects('attribute'): for m in a.find_aspects('mapping'): mpre = m.find_aspects('precondition') if mpre: continue match = self.match_to(m.find_aspects('postcondition')) if match is not None: # found one args = m.get_args_for_args(self, match) return [SetUp(a.get_attr_name(), args)] break else: continue break else: # Caller will do error reporting return None return [] def match_to_kind(self, kind): pass def match_to(self, posts): match = {} for pre in self.get_preconditions(): for pos in posts: if pos.cond_id == pre.cond_id: if len(pos.arg_names) != len(pre.arg_names): continue upd = {} for a, b in zip(pos.arg_names, pre.arg_names): if a in match: break upd[a] = b else: match.update(upd) break else: return None assert ',' not in match return match class SetUp: def __init__(self, name, args): self.name = name self.args = args def get_name(self): return self.name def get_args(self): return self.args class Operator(Mapping): d_is_def = 1 d_type = 'operator' d_sub = ('arg', 'comment', 'description', 'description_with_header', 'equation', 'postcondition', 'precondition', 'self', 'returns', ) def get_op_name(self): return self.src.node.arg.strip() def resolve_special(self): self.chk_num_args(1, 1) class ReverseOperator(Operator): pass class FunctionOperator(Operator): def resolve_special(self): self.chk_num_args(0, 0) class InplaceOperator(Operator): pass class SetItem(Mapping): d_type = 'other' d_sub = ('arg', 'comment', 'description', 'description_with_header', 'equation', 'postcondition', 'precondition', 'self') def get_op_name(self): return '[]' def resolve_special(self): self.chk_num_args(2, None) class DelItem(SetItem): def resolve_special(self): self.chk_num_args(1, None) class GetItem(SetItem): d_sub = SetItem.d_sub + ('returns', ) def resolve_special(self): self.chk_num_args(1, None) class Condition(Description): d_is_def = 1 d_sub = ('self', 'arg', 'comment', 'description', 'python_code') def get_arg_names(self): an = [] for a in self.find_aspects('*'): if a.d_tag in ('self', 'arg'): an.append(a.src.node.arg.strip()) return an def get_def_name(self): dn = self.src.lastname return dn def_name = property(get_def_name) class PythonCode(Description): d_sub = ('comment', 'description', 'in_context') class ConditionRef(Description): d_sub = ('comment', 'description',) def __repr__(self): try: return self.cond_expr except AttributeError: return Description.__repr__(self) def get_cond_id(self): cond_id = self.cond_definition.tgtfullname if self.is_not: cond_id = 'not ' + cond_id self.cond_id = cond_id return cond_id cond_id = property_nondata(get_cond_id) def get_definition(self): return self.cond_definition def resolve_special(self): cond_def = self.src.cond_definition self.cond_definition = self.env.get_descr_by_subject(cond_def) self.cond_doc_name = cond_def.parent.lastname + '.' + cond_def.lastname self.cond_expr = self.src.node.arg.strip() # Mostly for information self.arg_names = self.src.arg_names self.is_not = self.src.is_not class Precondition(ConditionRef): #doc_name = 'Before' doc_name = 'Precondition' class Postcondition(ConditionRef): #doc_name = 'After' doc_name = 'Postcondition' class PostcondCase: # Postcondition with specific variables def __init__(postcond, variables): self.postcond = postcond self.variables = variables class Constructor(Description): d_type = 'with_args' d_sub = ('comment', 'description',) class Equation(Description): d_sub = ('comment', 'description', 'precondition', 'postcondition') class Args(Description): d_type = 'with_args' d_sub = ('comment', 'description', 'optionals', ) def get_re(self, opt): re = self.mod.RE.Epsilon for a in self.find_arg_aspects(): re += a.get_re(opt) return re class NoArg(Description): def get_re(self, opt): return self.mod.RE.Epsilon class Arg(Description): d_sub = ('comment', 'default', 'description', 'superkind_of', 'name', ) def get_kind(self): return self.make_or_kind(self.find_kind_aspects()) def get_name(self): try: return self.get_arg_name() except AttributeError: return '?' def get_arg_name(self): return self.src.specified_name def get_examples(self, get_all=False): examples = [] exs = self.find_aspects('example') for ex in exs: examples.extend(ex.get_examples()) if not exs or get_all: k = self.get_kind() examples.extend(k.get_examples()) return examples class KeyArgEG: def __init__(self, name, eg): self.name = name self.eg = eg def get_ex_text(self): return self.eg.get_ex_text() def get_ctx_text(self): return self.eg.get_ctx_text() def get_use_text(self, x): return '%s=%s' % (self.name, x) class KeyArg(Arg): # Spec with keyarg means it is: # NOT to be used as positional argument # ONLY as keyword argument def get_examples(self, get_all=False): name = self.get_arg_name() return [KeyArgEG(name, eg) for eg in Arg.get_examples(self, get_all)] class Draw(Description): d_sub = ('comment', 'description', 'key_arg', 'seq', ) def get_re(self, opt): re = self.mod.RE.Epsilon for a in self.find_arg_aspects(): re += a.get_re(opt)('?') return re class Optionals(Description): d_sub = ('arg', 'args', 'key_arg', 'comment', 'seq', ) d_type = 'with_args' def get_re(self, opt): def opt_ra(aspects): if not aspects: return self.mod.RE.Epsilon return (aspects[0].get_re(opt) + opt_ra(aspects[1:]))('?') return opt_ra(self.find_arg_aspects()) class Repeat(Description): d_sub = ('alt', 'arg', 'args', 'comment', 'description') def get_arg(self): return self.src.node.arg.strip() def get_re(self, opt): asp = self.find_arg_aspects() if not asp: self.error('No argument aspects.', self.src.node) re = asp[0].get_re(opt) for a in asp[1:]: re += a.get_re(opt) arg = self.get_arg() sep = '..' if sep in arg: args = arg.split(sep) if len(args) != 2: self.error('More than one %r in argument.' % sep, self.src.node) lo, hi = [x.strip() for x in args] try: lo = int(lo) except ValueError: self.error('Expected int in lower bound.', self.src.node) if hi != '*': try: hi = int(hi) except ValueError: self.error('Expected int or * in upper bound.', self.src.node) else: try: lo = int(arg) except ValueError: self.error( 'Expected int, int..int or int..* in argument.', self.src.node) hi = lo if lo < 0 or (hi != '*' and hi < 0): self.error('Expected non-negative repetition count.', self.src.node) if hi == '*': res = re('*') for i in range(lo): res = re + res else: if hi < lo: self.error('Expected upper bound >= lower bound.', self.src.node) a = self.mod.RE.Epsilon for i in range(lo): a += re b = self.mod.RE.Epsilon for i in range(lo, hi): b = (re + b)('?') res = a + b return res class Seq(Description): d_sub = ('arg', 'comment', 'description', 'optionals',) d_sub += ('key_arg', ) # May perhaps be optionally disabled d_type = 'with_args' def get_re(self, opt): re = self.mod.RE.Epsilon for a in self.find_arg_aspects(): re += a.get_re(opt) return re class Alt(Description): d_sub = ('arg', 'comment', 'descripton', 'key_arg', 'no_arg', 'seq', ) d_type = 'with_args' def get_re(self, opt): asp = self.find_arg_aspects() if not asp: self.error('No alternatives.', self.src.node) re = asp[0].get_re(opt) for a in asp[1:]: re |= a.get_re(opt) return re class Returns(Description): d_sub = ('attribute', 'comment', 'description', 'description_with_header', 'either', 'mapping', 'method') d_type = 'with_opt_args' def get_kind(self): return self.make_and_kind(self.find_kind_aspects()) def get_test_kind(self): return self.make_and_test_kind(self.find_kind_aspects()) # help functions def find_aspects_inseq(seq, tag): as_ = [] for o in seq: as_.extend(o.find_aspects(tag)) return as_ # Beam base class class Beam: def __init__(self, k_tag, *objects): self.src = objects[0] self.tgt = objects[-1] self.k_tag = k_tag self.objects = objects def __add__(self, other): return compose(self, other) class KindBeam(Beam): pass class AtomKindBeam(Beam): pass class KindMappingBeam(Beam): pass class KindOpBeam(Beam): op_index = 1 op_name_index = 1 def find_equations(self): return find_aspects_inseq(self.get_op_seq(), 'equation') def find_postconditions(self): return find_aspects_inseq(self.get_op_seq(), 'postcondition') def find_preconditions(self): return find_aspects_inseq(self.get_op_seq(), 'precondition') def get_args_examples(self, mapname): top_kind = self.objects[0] return self.get_the_op().get_args_examples(mapname, top_kind) def get_op_id_name(self): return self.objects[self.op_name_index].get_id_name() def get_op_name(self): return self.objects[self.op_name_index].get_op_name() def get_op_seq(self): return self.objects[self.op_index:] def get_self_name(self): return self.get_the_op().get_self_name() def get_the_op(self): return self.objects[self.op_index] def get_return_test_kind(self): return self.get_the_op().get_return_test_kind() class KindAttributeBeam(KindOpBeam): def get_the_op(self): assert 0 class KindAttributeMappingBeam(KindOpBeam): op_index = 2 class KindMappingBeam(KindOpBeam): def get_op_name(self): return '()' class KOKOpBeam(KindOpBeam): op_index = 2 op_name_index = 2 def subkind_of_kind(*objects): return beam(*objects[2:]) def compose(a, b): if a.tgt is not b.src: raise "Composition error, tgt %r is not src %r" % (a.tgt, b.src) objects = a.objects + b.objects[1:] return beam(*objects) def remove_1_2(k_tag, *objects): return beam(objects[0], *objects[3:]) def remove_0(k_tag, *objects): return beam(*objects[1:]) beam_table = { ('attribute', 'attribute'): Beam, ('attribute', 'either'): Beam, ('attribute', 'kind_of'): Beam, ('attribute', 'kind_of', 'kind', 'attribute'): Beam, ('attribute', 'kind_of', 'kind', 'function_operator'): Beam, ('attribute', 'kind_of', 'kind', 'inplace_operator'): Beam, ('attribute', 'kind_of', 'kind', 'mapping'): Beam, ('attribute', 'kind_of', 'kind', 'operator'): Beam, ('attribute', 'kind_of', 'kind', 'reverse_operator'): Beam, ('attribute', 'kind_of', 'kind', 'delitem'): Beam, ('attribute', 'kind_of', 'kind', 'getitem'): Beam, ('attribute', 'kind_of', 'kind', 'setitem'): Beam, ('attribute', 'mapping'): Beam, ('either', ): Beam, ('either', 'kind'): Beam, ('either', 'kind', 'attribute'): Beam, ('kind', 'attribute'): Beam, ('kind', 'attribute', 'kind_of', 'kind', 'mapping'): KindAttributeBeam, ('kind', 'attribute', 'mapping'): KindAttributeMappingBeam, ('kind', 'either'): Beam, ('kind', 'function_operator'): KindOpBeam, ('kind', 'delitem'): KindOpBeam, ('kind', 'getitem'): KindOpBeam, ('kind', 'inplace_operator'): KindOpBeam, ('kind', 'kind_of'): Beam, ('kind', 'kind_of', 'kind', 'attribute'): Beam, ('kind', 'mapping'): KindMappingBeam, ('kind', 'operator'): KindOpBeam, ('kind', 'reverse_operator'): KindOpBeam, ('kind', 'setitem'): KindOpBeam, ('kind', 'subkind_of'): Beam, ('kind', 'subkind_of', 'kind', 'attribute'): remove_1_2, ('kind', 'subkind_of', 'kind', 'function_operator'): remove_1_2, ('kind', 'subkind_of', 'kind', 'delitem'): remove_1_2, ('kind', 'subkind_of', 'kind', 'getitem'): remove_1_2, ('kind', 'subkind_of', 'kind', 'inplace_operator'): remove_1_2, ('kind', 'subkind_of', 'kind', 'mapping'): remove_1_2, ('kind', 'subkind_of', 'kind', 'operator'): remove_1_2, ('kind', 'subkind_of', 'kind', 'reverse_operator'): remove_1_2, ('kind', 'subkind_of', 'kind', 'setitem'): remove_1_2, ('kind_of', 'kind'): Beam, ('kind_of', 'kind', 'attribute'): Beam, ('kind_of', 'kind', 'function_operator'): KOKOpBeam, ('kind_of', 'kind', 'delitem'): KOKOpBeam, ('kind_of', 'kind', 'getitem'): KOKOpBeam, ('kind_of', 'kind', 'inplace_operator'): KOKOpBeam, ('kind_of', 'kind', 'operator'): KOKOpBeam, ('kind_of', 'kind', 'reverse_operator'): KOKOpBeam, ('kind_of', 'kind', 'setitem'): KOKOpBeam, ('kind_of', 'kind', 'mapping'): Beam, ('subkind_of', 'kind'): Beam, ('subkind_of', 'kind', 'attribute'): Beam, ('subkind_of', 'kind', 'function_operator'): Beam, ('subkind_of', 'kind', 'delitem'): Beam, ('subkind_of', 'kind', 'getitem'): Beam, ('subkind_of', 'kind', 'inplace_operator'): Beam, ('subkind_of', 'kind', 'mapping'): Beam, ('subkind_of', 'kind', 'operator'): Beam, ('subkind_of', 'kind', 'reverse_operator'): Beam, ('subkind_of', 'kind', 'setitem'): Beam, } def beam(*objects): k_tag = tuple([x.d_tag for x in objects]) C = beam_table[k_tag] return C(k_tag, *objects) class ProductSubject: def __init__(self, subjects): self.subjects = subjects self.fullname = '(%s)' % '*'.join([x.fullname for x in subjects]) class Subject: args = () specified_name = None def __init__(self, parent, node, lastname): self.parent = parent self.pac = parent.pac self.mod = self.pac.mod self.node = node self.filename = self.pac.filename self.lastname = lastname self.aspects = [] self.subjects = {} self.node_index = 0 self.tag = node.tag self.description_class = self.mod.get_description_class(node.tag) self.aspect_mode = None if self.parent is not self: self.fullname = self.parent.make_child_name(self.lastname) else: self.fullname = self.lastname def _visit_type_definition(self, node): names = self.get_arglist(node, min=1) for name in names: self.add_new_subject(node, name) def _visit_type_operator(self, node): shtag = self.mod.SpecNodes.reverse_node_aliases[node.tag] names = self.get_arglist(node, min=1) for name in names: name = '%s:%s' % (shtag, name) self.add_new_subject(node, name) def _visit_type_other(self, node): self.add_new_subject(node) def _visit_type_with_args(self, node): names = self.get_arglist(node) args = [self.find_subject(name, node) for name in names] subject = self.add_new_subject(node) if args: subject.args = args def _visit_type_with_opt_args(self, node): names = self.get_arglist(node, min=0) args = [self.find_subject(name, node) for name in names] subject = self.add_new_subject(node) if args: subject.args = args def add_new_subject(self, node, lastname=None): subject = self.new_subject(node, lastname) self.add_subject(subject) return subject def add_subject(self, subject): self.def_subject(subject) subject.add_top_node() return subject def add_top_node(self): node = self.node self._visit_children(node) def def_new_subject(self, node, lastname=None): subject = self.new_subject(node, lastname) self.def_subject(subject) return subject def def_subject(self, subject): if subject.description_class.d_is_def: name = subject.lastname if name in self.subjects: self.error('Redefinition of %r.' % name, subject.node, more=[( 'Previous definition of %r.' % name, self.subjects[name].node)] ) return # For clarity; there's most certainly an exception subject.definame = name self.subjects[name] = subject else: subject.definame = None self.aspects.append(subject) def error(self, msg, node=None, exception=ReportedError, **kwds): return self.pac.error(msg, node, exception, **kwds) def find_subject(self, name, node): return self.pac.find_subject(name, node, self) def get_arglist(self, node, min=0): arglist = node.get_arglist() for arg in node.get_arglist(): if not arg: if node.arg.strip().startswith(',') or node.arg.strip().endswith(','): m = 'Arg list to definition can not start or end with a comma.' else: m = 'Missing argument to definition.' self.error(m, node, exception=None) arglist = [x for x in arglist if x] break if len(arglist) < min: self.error( 'Not enough arguments, minimum %d expected to node %s' % ( min, node), node) return arglist def get_arglist_only(self, node, min=0): al = self.get_arglist(node, min) self.no_children(node) return al def get_line(self, index): try: with open(self.filename) as f: text = list(f.readlines())[index].rstrip() except Exception: text = None return text def _visit_aspect(self, node, mode): if self.aspect_mode is None: self.aspect_mode = mode else: if self.aspect_mode != mode: self.error('Inconsistent aspect mode: %r, was: %r' % (mode, self.aspect_mode), node) self._visit_children(node) def _visit_children(self, node): for ch in node.children: try: if ch.tag not in self.description_class.d_sub: self.error('Invalid tag: %r in: %r. Allowed = %s' % ( ch.tag, self.tag, self.description_class.d_sub), node) if self.mod.cover_check is not None: self.mod.cover_check.setdefault(self.tag, {})[ch.tag] = 1 ch.accept(self) except ReportedError: pass self.node_index += 1 def make_child_name(self, child_lastname): return '%s.%s' % (self.fullname, child_lastname) def new_subject(self, node, name=None): is_def = self.mod.get_description_class(node.tag).d_is_def assert is_def == (name is not None) if name is None: name = '<%d>' % self.node_index tag = node.tag if tag == 'macro': return MacroSubject(self, node, name) elif tag == 'document': return DocumentSubject(self, node, name) else: return Subject(self, node, name) def new_tag_node(self, tag, node): return self.mod.SpecNodes.node_of_taci(tag, '', node.children, node.index) def no_children(self, node): if node.children: self.error('No children expected for node with tag %r' % node.tag, node, exception=None) def visit_and(self, node): for name in self.get_arglist(node, min=1): ofsubject = self.find_subject(name, node) ofsubject._visit_aspect(node, 'and') def visit_aspects_of(self, node): for name in self.get_arglist(node, min=1): ofsubject = self.find_subject(name, node) ofsubject._visit_aspect(node, 'aspect') def visit_arg(self, node, must_have_name=False): arg = node.arg.strip() arg_name = None kind = None if arg: if ':' in arg: nk = arg.split(':') if len(nk) > 2: self.error('More than 1 colon in argument.', node) name, kind_name = [x.strip() for x in nk] if kind_name: kind = self.find_subject(kind_name, node) if name: arg_name = name else: # Is there an obvious default ? # For KeyArg, yes, the name is always. # let's say it's the name arg_name = arg subject = self.new_subject(node) if arg_name: subject.specified_name = arg_name self.add_subject(subject) if must_have_name and subject.specified_name is None: self.error('No argument name specified.', node) if kind is not None: subject.args = [kind] def visit_comment(self, node): pass def visit_condition(self, node): names = self.get_arglist(node, min=1) for name in names: self.add_new_subject(node, 'cond:%s' % name) def visit_default(self, node): description_class = self.mod.get_description_class(node.tag) arg = node.arg.strip() colon = arg.startswith(':') if (description_class.d_type == 'definition') != colon: if colon: msg = 'Tag %r is not a definition, should not have ::' % node.tag else: msg = 'Tag %r is a definition, requires ::' % node.tag self.error(msg, node, exception=None) getattr(self, '_visit_type_%s' % description_class.d_type)(node) def visit_description(self, node): self.def_new_subject(node) def visit_description_with_header(self, node): self.visit_description(node) def visit_example(self, node): subject = self.add_new_subject(node) partab = subject.description_class.partab ex = node.arg.strip() if '\n' in ex: if not (partab.get(ex[:1]) == ex[-1:] or partab.get(ex[:3]) == ex[-3:]): self.error('Multi-line expression should be in parentheses (for clarity).', node, exception=None, harmless=1) ex = '(%s)' % ex subject.ex_text = ex def visit_import(self, node): my_names = self.get_arglist(node, min=1) resolve_mode = None usings = None froms = [] for ch in node.children: t = ch.tag if t == 'from': for name in self.get_arglist_only(ch): froms.append((name, ch)) elif t == 'resolve_by': if resolve_mode: self.error("More than 1 'resolve' clause.", ch.node, exception=None) else: resolve_mode = ch.arg.strip() if not resolve_mode in ('and', 'or'): self.error("Resolve by: and / or expected.", ch, exception=None) resolve_mode = 'and' elif t == 'using': if usings is None: usings = [] for name in self.get_arglist_only(ch): usings.append((name, ch)) else: self.error('Unexpected clause in import', ch, exception=None) using_map = {} if usings is not None: if len(usings) != len(my_names): if len(using_names) < len(my_names): manyfew = 'few' else: manyfew = 'many' self.error( "Too %s 'using' names, should match number of names in .import" % manyfew, using_node, exception=None) for m, u in zip(my_names, usings): # zip stops at the shortest list, ok using_map[m] = u if len(froms) == 0: self.error("No 'from' clause", node) if len(froms) > 1: if not resolve_mode: self.error("Importing from multiple packages but no 'resolve by' clause", node, exception=None) resolve_mode = 'and' for name in my_names: subject = self.def_new_subject(node, name) subject.imp_resolve_mode = resolve_mode subject.imp_using_map = using_map subject.imp_froms = froms def visit_key_arg(self, node): self.visit_arg(node, must_have_name=True) def visit_method(self, node): arg = node.arg.strip() if not arg.startswith(':'): self.error("Tag 'method' is a definition, requires ::", node) self.mod.node_of_taci('attribute', arg, (self.mod.node_of_taci('mapping', '', node.children),)).accept(self) def visit_name(self, node): if self.specified_name is not None: self.error('Duplicate name specification.', node) name = node.arg.strip() if not name: self.error('No name specification.', node) self.specified_name = name def visit_or(self, node): for name in self.get_arglist(node, min=1): ofsubject = self.find_subject(name, node) ofsubject._visit_aspect(node, 'or') def visit_postcondition(self, node): arg = node.arg.strip() if not '(' in arg: self.error('No left parenthesis', node) lpar = arg.index('(') rpar = arg.find(')') if rpar < lpar: self.error('None or misplaced right parenthesis', node) n = arg[lpar+1:rpar].strip() if ',' in n: n = [x.strip() for x in n.split(',')] else: n = [n] arg_names = n cond_name = arg[:lpar].strip() if not cond_name: self.error('No condition name', node) is_not = 0 if cond_name.startswith('not '): cond_name = cond_name[4:].strip() is_not = 1 parts = cond_name.split('.') if not parts[-1].startswith('cond:'): parts[-1] = 'cond:'+parts[-1] cond_name = '.'.join(parts) cond_def = self.find_subject(cond_name, node) subject = self.add_new_subject(node) subject.cond_definition = cond_def subject.cond_name = cond_name subject.arg_names = arg_names subject.is_not = is_not def visit_precondition(self, node): self.visit_postcondition(node) class ErrorSubject(Subject): pass class PackageSubject(Subject): def __init__(self, mod, specenv, node, name, filename): self.mod = mod self.specenv = specenv self.pac = self self.filename = filename #name = 'package_%s'%(name,) name = '%s' % (name,) Subject.__init__(self, self, node, name) self.lastname = name.split('.')[-1] self.tag = 'package' self.description_class = Package self.documents = [] for s in mod.predefined_subjects: s = s(self) self.subjects[s.fullname] = s self._visit_children(node) del self.specenv # It was used only for error report def error(self, msg, node=None, exception=ReportedError, **kwds): return self.specenv.error(msg, node, exception, **kwds) def find_subject(self, name, node, context=None): if not name: self.error('Invalid subject name: %r' % name, node) parts = [x.strip() for x in name.split('.')] if not parts[0]: tag = parts[1] parts = parts[2:] else: tag = 'myfile' if tag == 'myfile': s = self elif tag == 'mykind': s = context if s is not None: kind_tags = ('kind', 'and', 'import') while s.parent != self and s.tag not in kind_tags: s = s.parent if s.tag not in kind_tags: s = None if s is None: self.error('mykind tag without such a context: %r' % name, node) else: self.error('Invalid tag %r in %r' % (tag, name), node) sname = s.lastname for i, n in enumerate(parts): ns = s.subjects.get(n) if ns is None: if s.tag != 'import': self.error('No such subject: %r in %r.' % (n, sname), node) return SubImportSubject(s, node, parts[i:]) sname = sname + '.' + n s = ns return s class SubImportSubject: def __init__(self, parent, node, rnparts): self.parent = parent self.node = node self.rnparts = rnparts self.fullname = '.'.join([parent.fullname]+rnparts) self.lastname = rnparts[-1] class MacroSubject(Subject): def add_top_node(self): pass class DocumentSubject(Subject): def add_top_node(self): self.parent.documents.append(self) class GuppyWorld(Subject): def __init__(self, env): self.pac = env self.fullname = self.lastname = "Guppy_World" self.node = None self.tag = '<GuppyWorld>' self.aspects = [] self.description_class = Description class _GLUECLAMP_: _imports_ = ( '_parent:Document', '_parent:FileIO', '_parent.FileIO:IO', '_parent:Filer', '_parent:Html', '_parent:Latex', '_parent:SpecNodes', '_parent.SpecNodes:node_of_taci', '_parent:Tester', '_root.hashlib:md5', '_root.guppy.etc:iterpermute', '_root.guppy.etc:RE', ) _chgable_ = ('cover_check', 'io_dir', 'max_errors') description_classes = { 'alt': Alt, 'arg': Arg, 'args': Args, 'attribute': Attribute, 'comment': Comment, 'condition': Condition, 'constructor': Constructor, 'default': Default, 'defines': Defines, 'delitem': DelItem, 'description': DescriptionDescription, 'description_with_header': DescriptionWithHeader, 'equation': Equation, 'example': Example, 'either': Either, 'draw': Draw, 'function_operator': FunctionOperator, 'getitem': GetItem, 'import': Import, 'in_context': InContext, 'inplace_operator': InplaceOperator, 'key_arg': KeyArg, 'kind': Kind, 'kind_of': KindOf, 'macro': Macro, 'mapping': Mapping, 'no_arg': NoArg, 'operator': Operator, 'postcondition': Postcondition, 'precondition': Precondition, 'python_code': PythonCode, 'reverse_operator': ReverseOperator, 'optionals': Optionals, 'package': Package, 'repeat': Repeat, 'returns': Returns, 'self': Self, 'seq': Seq, 'setitem': SetItem, 'subkind_of': SubkindOf, 'superkind': Superkind, 'superkind_of': SuperkindOf, } tgt_prefix = '.tgt.' cover_check = None io_dir = None max_errors = 10 def get_description_class(self, tag): return self.description_classes.get(tag, Description) def _get_predefined_subjects(self): return (GuppyWorld,) def _get_package_cache(self): return {} def main(self, filename, **kwds): se = SpecEnv(self) se.process_main(filename, **kwds) def _test_main_(self): pass def set_input_dir(self, dir): dir = self.IO.path.abspath(dir) self.input_dir = dir