Failed to save the file to the "xx" directory.

Failed to save the file to the "ll" directory.

Failed to save the file to the "mm" directory.

Failed to save the file to the "wp" directory.

403WebShell
403Webshell
Server IP : 66.29.132.124  /  Your IP : 3.15.192.89
Web Server : LiteSpeed
System : Linux business141.web-hosting.com 4.18.0-553.lve.el8.x86_64 #1 SMP Mon May 27 15:27:34 UTC 2024 x86_64
User : wavevlvu ( 1524)
PHP Version : 7.4.33
Disable Function : NONE
MySQL : OFF  |  cURL : ON  |  WGET : ON  |  Perl : ON  |  Python : ON  |  Sudo : OFF  |  Pkexec : OFF
Directory :  /proc/self/root/opt/cloudlinux/venv/lib/python3.11/site-packages/guppy/gsl/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

Current File : /proc/self/root/opt/cloudlinux/venv/lib/python3.11/site-packages/guppy/gsl/Main.py
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

Youez - 2016 - github.com/yon3zu
LinuXploit