Mini Shell
from guppy.etc.Descriptor import property_nondata
class Classifier:
def __init__(self, mod, name, cli=None, supers=(), depends=(), with_referrers=False):
self.mod = mod
self.name = name
if cli is not None:
self.cli = cli
# Set of all super-classifiers (including self).
# The partial order is defined in Notes Aug 30 2005.
self.super_classifiers = mod.ImpSet.immnodeset([self])
if supers:
for s in supers:
self.super_classifiers |= s.super_classifiers
else:
# The Unity classifier is super of all, but we must add it only
# if not supers specified; init of ByUnity itself depends on this.
self.super_classifiers |= [mod.Use.Unity.classifier]
# The classifiers that self depends on.
for d in depends:
if d.with_referrers:
with_referrers = True
break
# True if we need to setup referrers before calling (the) low-level classifier.
self.with_referrers = with_referrers
if with_referrers:
self.call_with_referrers = mod.View.call_with_referrers
def call_with_referrers(self, x, f):
# Default is to not use referrers.
return f(x)
# This is not redefined by subclass unless they set cli property.
def _get_cli(self):
# This may be defined by subclass w/o setting cli property.
return self.get_cli()
cli = property_nondata(_get_cli)
def get_alt(self, kind, alt):
# Get alternative kind for a kind with self as fam.classifier.
return self.mod.alt(kind, alt)
def get_dictof(self, kind):
name = '%s.dictof' % self.name
er = self.mod.mker_memoized(
name,
lambda:
self.mod._er_by_(ByDictOwner, self.mod, name, self))
return er.classifier.dictof(kind)
def get_kind(self, k):
# Make an equivalence class from low-level classification
return self.family(k)
def get_kindarg(self, kind):
# Inverse of get_kind
cla, ka, cmp = kind.get_ckc()
if cla is not self:
raise ValueError(
'get_kindarg: argument with classifier %r expected' % self)
return ka
def get_reprname(self):
return '%s%s' % (self.mod.Use.reprefix, self.name)
def get_sokind(self, er, *args, **kwds):
k = er(*args, **kwds)
return CallableSoKind(er, (k,))
def get_sokindrepr(self, sokind):
# Get the representation of a set of kinds
# from this classifier / eqv. relation.
return '%s.sokind%s' % (self.get_reprname(),
''.join(['(%s)' % self.get_userkindargrepr(k)
for k in sokind.kinds]))
def get_tabheader(self, ctx=''):
# If ctx = 'and', get the table header when used as a part of the 'and' classifier.
# It is sometimes a more compact or parenthesised version of the usual tab header.
return self.get_byname()
def get_tabrendering(self, cla, ctx=''):
# If ctx = 'and', get the table rendering when used as a part of the 'and' classifier
# sometimes we want to enclose something in parenthesises.
return cla.brief
def get_userkind(self, *args, **kwds):
# Make a kind from user-level arguments
return self.family(*args, **kwds)
def get_userkindarg(self, kind):
return kind.arg
def get_userkindargrepr(self, kind):
return repr(self.get_userkindarg(kind))
def partition(self, iterable):
items = []
for k, v in self.partition_cli(iterable):
k = self.get_kind(k)
v = self.mod.Use.idset(v, er=self.er)
items.append((k, v))
return items
def partition_cli(self, a):
ep = self.call_with_referrers(
a,
self.cli.epartition)
return [(k, ep[k]) for k in ep.get_domain()]
def relimg(self, X):
p = self.partition_cli(X)
kinds = [self.get_kind(k) for k, v in p] # could be more efficient
return self.mod.Use.union(kinds, maximized=1)
def select_cli(self, a, b, cmp='=='):
return self.call_with_referrers(
a,
lambda a: self.cli.select(a, b, cmp))
def select_ids(self, X, k, alt=None):
r = self.mod.Use.idset(self.select_cli(X.nodes, k, alt))
return r
class SoKind(object):
def __init__(self, er, kinds):
self.er = er
self.classifier = er.classifier
self.kinds = kinds
self.clikinds = self.classifier.mod.ImpSet.immnodeset(
[self.classifier.get_kindarg(kind) for kind in kinds])
def __eq__(self, other):
if not isinstance(other, SoKind):
return False
if self.classifier != other.classifier:
return False
a = self.classifier.mod.Use.union(self.kinds)
b = self.classifier.mod.Use.union(other.kinds)
return a == b
def __hash__(self):
return hash(repr(self))
def __repr__(self):
return self.classifier.get_sokindrepr(self)
def _get_refdby(self):
return self.er.refdby(self)
refdby = property(_get_refdby)
class CallableSoKind(SoKind):
def __call__(self, *args, **kwds):
k = self.er(*args, **kwds)
return self.__class__(self.er, self.kinds + (k,))
class SoNoKind(SoKind):
def __repr__(self):
return '%s%s' % (self.classifier.mod.Use.reprefix, 'sonokind')
class QuickSoKind(SoKind):
# Quicker to make than SoKind,
# when clikinds is available but not kinds.
__slots__ = 'classifier', 'clikinds'
def __init__(self, classifier, clikinds):
self.classifier = classifier
self.clikinds = clikinds
def _get_er(self):
return self.classifier.er
er = property(_get_er)
def _get_kinds(self):
return tuple([self.classifier.get_kind(k) for k in self.clikinds])
kinds = property(_get_kinds)
class IdentityFamily:
# Holds a single object node
def __init__(self, mod, classifier):
self.defrefining(mod.Use.Anything)
self.classifier = classifier
def _ge_ATOM(self, a, b):
# b is known to not be Nothing since its c_le doesn't call back
if self is b.fam:
return a.arg is b.arg
return b.fam.supercl is not None and b.fam.supercl <= a
def _le_ATOM(self, a, b):
# b is known to not be Nothing since its c_ge doesn't call back
if self is b.fam:
return a.arg is b.arg
return self.supercl is not None and self.supercl <= b
def c_contains(self, a, b):
return b is a.arg
def _and_ID(self, a, b):
# Just a possible optimization
return self.mod.Use.idset(b.nodes & [a.arg])
def c_get_brief(self, a):
return '<id %s>' % hex(id(a.arg))
def c_repr(self, a):
return '%s(%s)' % (self.classifier.get_reprname(), self.classifier.get_userkindargrepr(a))
class ByIdentity(Classifier):
def __init__(self, mod, name):
Classifier.__init__(self, mod, name, mod.hv.cli_id())
self.family = mod.fam_mixin_argatom(IdentityFamily, self)
# self.super_classifiers = mod.Use.Anything # Replace whatever Classifer had set it to
def get_byname(self):
return 'object identity'
def get_tabheader(self, ctx=''):
return 'Object Identity'
def get_userkind(self, address):
return self.get_kind(self.mod.View.obj_at(address))
def get_userkindarg(self, kind):
return id(kind.arg)
def get_userkindargrepr(self, kind):
return hex(self.get_userkindarg(kind))
class ByIdentitySet(Classifier):
# Classification is, conceptually, a singleton immnodeset of each object
# What this is used to is:
# to be able to use an iso() set as a kind
# combined with other classifiers eg in dictof, biper
# The ckc returned from an iso is then
# this classifier, nodes of iso, '<='
# The cmp indicates subset
# select thus selects every object for which it singleton is a subset of the set given
# which is optimized to select the object that are members of that set
# and may be optimized at higher levels to invoke the low-level set intersection
def __init__(self, mod, name):
Classifier.__init__(self, mod, name, mod.hv.cli_idset())
self.family = mod.Use.idset
# self.super_classifiers = mod.Use.Anything # Replace whatever Classifer had set it to
def get_byname(self):
return 'by identity set'
def get_userkind(self, node):
return self.family(self.mod.ImpSet.immnodeset([node]))
def relimg(self, X):
p = self.partition_cli(X)
k = self.mod.ImpSet.immnodeset_union([k for k, v in p])
return self.family(k)
class PyObjectFamily:
def __init__(self, mod, classifier):
self.classifier = classifier
def c_contains(self, a, b):
return True
def c_get_idpart_header(self, a):
return 'Kind: Name/Value/Address'
def c_get_idpart_label(self, a):
return ''
def c_get_idpart_render(self, a):
def render(x):
x = self.mod.Use.iso(x)
r = x.brief.lstrip('<1 ').rstrip('>')
return r
return render
def c_get_brief(self, a):
return '<Anything>'
def c_repr(self, a):
return '%s%s' % (self.mod.Use.reprefix, 'Anything')
def _and_ID(self, a, b):
# Optimization shortcut
# shcould be made in classifer.select
return b
class ByUnity(Classifier):
"""byunity
Classify by <unity>.
The classification returned for every object is <Anything>."""
def __init__(self, mod, name):
Classifier.__init__(self, mod, name, mod.hv.cli_none(),
# Must make it avoid referring to Unity !
supers=[self]
)
self.family = mod.fam_mixin_argatom(PyObjectFamily, self)
def get_byname(self):
return 'unity'
def get_tabheader(self, ctx=''):
return '<unclassified>'
def get_userkind(self, *args):
return self.mod.Use.Anything
def get_userkindarg(self, kind):
return None
class IndiSizeFamily:
def __init__(self, mod, classifier):
self.defrefining(mod.Use.Anything)
self.classifier = classifier
def __call__(self, a):
a = int(a)
return self.mod.AtomFamily.__call__(self, a)
def c_alt(self, a, alt):
return self.classifier.get_alt(a, alt)
def c_contains(self, a, b):
return a.arg == self.classifier.cli.classify(b)
def c_get_render(self, a):
return self.mod.summary_str(a.arg)
def c_get_brief(self, a):
return '<size = %d>' % a.arg
def c_get_brief_alt(self, a, alt):
return '<size %s %d>' % (alt, a.arg)
def c_repr(self, a):
return '%s(%s)' % (self.classifier.get_reprname(), a.arg)
class ByIndiSize(Classifier):
"""byindisize
Classify by <individual size>.
The classification will be individual memory size of the object."""
def __init__(self, mod, name):
Classifier.__init__(self, mod, name)
self.family = mod.fam_mixin_argatom(IndiSizeFamily, self)
def get_byname(self):
return 'individual size'
def get_cli(self):
return self.mod.hv.cli_indisize({})
def get_tabheader(self, ctx=''):
return 'Individual Size'
def get_tabrendering(self, cla, ctx=''):
if ctx:
return '%d' % cla.arg
else:
return '%9d' % cla.arg
class TypeFamily:
def __init__(self, mod, classifier):
self.defrefining(mod.Use.Anything)
self.classifier = classifier
self.range = mod.fam_Family(self)
def __call__(self, a):
if not isinstance(a, type):
raise TypeError("Argument should be a type.")
return self.Set(self, a)
def c_alt(self, a, alt):
return self.classifier.get_alt(a, alt)
def c_contains(self, a, b):
return type(b) is a.arg
def c_get_render(self, a):
return self.mod.summary_str(a.arg)
def c_get_brief(self, a):
return self.mod.summary_str(type(a.arg))(a.arg)
def c_get_brief_alt(self, a, alt):
x = {
'<': 'strict subtype',
'<=': 'subtype',
'>=': 'supertype',
'>': 'strict supertype'
}[alt]
return '<%s of %s>' % (x, self.c_get_brief(a))
def c_repr(self, a):
return self.classifier.get_repr(a)
class ByType(Classifier):
"""bytype
Classify by <type>.
The classification will be the type of the object."""
def __init__(self, mod, name):
Classifier.__init__(self, mod, name, mod.hv.cli_type())
self.family = mod.fam_mixin_argatom(TypeFamily, self)
def get_attr_for_er(self, name):
try:
ty = getattr(self.mod.types, name+'Type')
except AttributeError:
ty = getattr(self.mod.builtins, name.lower())
return self.get_userkind(ty)
def get_byname(self):
return 'type'
def get_repr(self, kind):
t = kind.arg
rn = self.get_reprname()
if t in self.mod.invtypemod:
return '%s.%s' % (rn, self.mod.invtypemod[t])
else:
return '%s(%r)' % (rn, self.get_userkindarg(kind))
def get_tabheader(self, ctx=''):
return 'Type'
def get_userkind(self, kind):
kind = self.mod.tc_adapt(kind)
return self.family(kind)
def get_userkindarg(self, kind):
# A representation that is a valid userkind arg.
return self.mod.Use.tc_repr(kind.arg)
class OwnedDictFamily:
def __init__(self, mod):
self.defrefidis(mod.Use.Type(dict))
def _get_ownerkind(self, a):
return a.arg
def c_alt(self, a, alt):
return self(a.arg.alt(alt))
def c_get_render(self, a):
ka = self._get_ownerkind(a)
if ka is self.mod.Use.Nothing:
return self.mod.Use.Type.Dict.get_render()
else:
ownrender = ka.get_render()
def render(x):
ret = ownrender(self.mod.Use.iso(x).owners.theone)
if '.' in ret:
ret = '..'+ret.split('.')[-1]
return ret
return render
if ka == self.mod.fam_Type(self.types.ModuleType):
modrender = self.mod.Use.Type.Module.get_render()
def render(x):
return modrender(self.mod.Use.iso(x).owners.theone)
return render
else:
return self.mod.Use.Type.Dict.get_render()
def c_get_brief(self, a):
ka = self._get_ownerkind(a)
if ka is self.mod.Use.Nothing:
return 'dict (no owner)'
else:
return 'dict of ' + ka.brief
def c_get_ckc(self, a):
cla, k, cmp = a.arg.get_ckc()
if cmp != '==':
cla, k, cmp = a.arg.biper(0).get_ckc()
docla = cla.er.dictof.classifier
if a.arg is self.mod.Use.Nothing:
k = docla.notownedtag
return docla, k, cmp
def c_get_str_for(self, a, b):
return self.c_get_brief(a)
def c_get_idpart_render(self, a):
ka = self._get_ownerkind(a)
if ka is not self.mod.Use.Nothing:
owner_render = ka.fam.c_get_idpart_render(ka)
def render(x):
return owner_render(self.mod.Use.iso(x).owners.theone)
return render
else:
b = self.mod._parent.Spec.Type.Dict
return b.fam.c_get_idpart_render(b)
def c_get_idpart_header(self, a):
ka = self._get_ownerkind(a)
if ka is self.mod.Use.Nothing:
return 'Address*Length'
else:
return 'Owner ' + ka.fam.c_get_idpart_header(ka)
def c_repr(self, a):
ka = self._get_ownerkind(a)
ra = repr(ka)
if ra.startswith('~'):
ra = '(%s)' % ra
return '%s.dictof' % ra
class ByDictOwner(Classifier):
def __init__(self, mod, name, ownerclassifier):
Classifier.__init__(self, mod, name, depends=[ownerclassifier])
self.ownerclassifier = ownerclassifier
self.hv = mod.View.hv
self.ownership = mod.View.dict_ownership
self.family = mod.dictof
self.notdict = mod.notdict
self.dictofnothing = mod.dictofnothing
# Hashable unique tags
# Using sets methods since I dont want our hiding tag here!
# Confuses heapg. Note feb 3 2006
self.notdicttag = mod.ImpSet.immnodeset([[]])
self.notownedtag = mod.ImpSet.immnodeset([[]])
def get_byname(self):
return '[dict of] %s' % self.ownerclassifier.get_byname()
def get_cli(self):
cli = self.hv.cli_dictof(self.ownership, self.ownerclassifier.cli, self.notdicttag,
self.notownedtag)
return cli
def get_kind(self, k):
if k is self.notdicttag:
return self.notdict
elif k is self.notownedtag:
return self.dictofnothing
else:
return self.family(self.ownerclassifier.get_kind(k))
def get_kindarg(self, kind):
if kind is self.notdict:
return self.notdicttag
elif kind is self.dictofnothing:
return self.notownedtag
else:
return self.ownerclassifier.get_kindarg(kind.arg)
def get_tabheader(self, ctx=''):
return 'Dict of %s' % self.ownerclassifier.get_tabheader(ctx)
def get_tabrendering(self, kind, ctx=''):
if kind is self.notdict:
r = kind.brief
elif kind is self.dictofnothing:
r = 'dict (no owner)'
else:
r = 'dict of ' + \
self.ownerclassifier.get_tabrendering(kind.arg, ctx)
return r
def get_userkind(self, k):
if k is None:
return self.notdict
elif k is self.mod.Use.Nothing:
return self.dictofnothing
else:
return self.family(k)
def get_userkindarg(self, kind):
if kind is self.notdict:
return None
elif kind is self.dictofnothing:
return self.mod.Use.Nothing
else:
return kind.arg
def owners(self, X):
p = self.partition_cli(X.nodes)
ns = self.mod.ImpSet.mutnodeset()
drg = self.ownership
for k in X.nodes:
t = drg[k]
if not t:
self.mod.hv.update_dictowners(drg)
t = drg[k]
if t:
v = t[0]
if v is not None:
ns.add(v)
return self.mod.Use.idset(ns)
class ByClassOrDictOwner(Classifier):
"""byclodo
Classify by <type or dict owner>.
The classification is performed as follows:
1. If the object is not a dictionary,
the classification will be the type of the object.
2. The object is a dictionary. The referrers of the
object are searched to find one that 'owns' the
dictionary. That is, typically, that the dict is
the __dict__ attribute of the owner. If no such
owner is found, the type 'dict' will be the
classification. If an owner is found, a special
object that indicates the classification of the owner
will be returned. The classification of the owner
will be done by class. (As byclass.)"""
def __init__(self, mod, name):
a = mod.Type
d = a.dictof
ad = (a & d).classifier
sup = a.classifier
Classifier.__init__(self, mod, name, cli=None,
supers=[sup], depends=[ad])
self.sup = sup
self.a = a.classifier
self.d = d.classifier
self.ad = ad
def get_byname(self):
return '[dict of] class'
def get_cli(self):
return self.ad.cli
def get_kind(self, xxx_todo_changeme):
(ka, kd) = xxx_todo_changeme
if kd is self.d.notdicttag:
return self.a.get_kind(ka)
else:
return self.d.get_kind(kd)
def get_kindarg(self, kind):
if kind.fam is self.d.family:
ka = dict
kd = self.d.get_kindarg(kind)
else:
ka = self.a.get_kindarg(kind)
kd = self.d.notdicttag
return (ka, kd)
def get_tabheader(self, ctx=''):
return 'Kind (class / dict of class)'
def get_userkind(self, kind=None, dictof=None):
try:
if kind is None and dictof is not None:
if dictof == ():
do = self.mod.UniSet.Nothing
else:
do = self.sup.get_userkind(dictof)
return self.d.get_userkind(do)
elif kind is not None and dictof is None:
kind = self.mod.tc_adapt(kind)
if kind is dict:
raise TypeError(
'dict is not an equivalence class of Clodo, use dictof=() etc')
return self.sup.get_kind(kind)
else:
raise TypeError
except TypeError:
raise TypeError("""\
Argument should be either
<type except dict>
dictof=<type>
dictof=()""")
def get_userkindargrepr(self, kind):
if kind.fam is self.d.family:
if kind.arg is self.mod.UniSet.Nothing:
d = '()'
else:
d = self.d.ownerclassifier.get_userkindargrepr(kind.arg)
return 'dictof=%s' % d
else:
return kind.fam.classifier.get_userkindargrepr(kind)
def owners(self, X):
return self.d.owners(X)
class RetClaSetFamily:
def __init__(self, mod, classifier):
self.defrefining(mod.Use.Anything)
self.classifier = classifier
def c_alt(self, a, alt):
return a.arg.classifier.er.refdby.classifier.get_alt(a, alt)
return self.classifier.get_alt(a, alt)
def _get_arg_brief(self, a):
return a.arg.er.refdby.classifier.get_tabrendering(a, False)
def c_get_brief(self, a):
return '<referred by: %s>' % self._get_arg_brief(a)
def c_get_brief_alt(self, a, alt):
x = {
'<': 'by less than',
'<=': 'by at most',
'>=': 'by at least',
'>': 'by more than',
}[alt]
return '<referred %s: %s>' % (x, self._get_arg_brief(a))
def c_get_ckc(self, a):
return self.classifier, a.arg.clikinds, '=='
def c_repr(self, a):
return '%r.refdby' % a.arg
# Public
def sokind(self, sok):
if not isinstance(sok, SoKind):
raise TypeError('SoKind expected')
er = sok.classifier.er.refdby
kinds = (self(sok),)
return CallableSoKind(er, kinds)
class ByRetClaSet(Classifier):
def __init__(self, mod, name, rg, referrer_classifier, doc):
Classifier.__init__(self, mod, name, with_referrers=True)
self.rg = rg
self.referrer_classifier = referrer_classifier
self.family = self.mod.fam_mixin_argatom(RetClaSetFamily, self)
self.__doc__ = doc
def get_byname(self):
return 'referrer kinds'
def get_cli(self):
memo = {}
return self.mod.hv.cli_rcs(self.rg, self.referrer_classifier.cli, memo)
def get_inverted_refkind(self, k):
if k.fam.opname == 'OR':
ks = k.arg
elif k is self.mod.Use.Nothing:
ks = ()
else:
ks = (k,)
rks = []
for k in ks:
rks.append(self.referrer_classifier.get_kindarg(k))
return self.mod.ImpSet.immnodeset(rks)
def get_kind(self, k):
if k:
return self.family(QuickSoKind(self.referrer_classifier, k))
else:
return self.mod.refdbynothing
def get_tabheader(self, ctx=''):
th = 'Referrers by %s' % self.referrer_classifier.get_tabheader(ctx)
if ctx:
th = '{%s}' % th
return th
def get_tabrendering(self, cla, ctx):
rs = [self.referrer_classifier.get_tabrendering(
x, ctx) for x in cla.arg.kinds]
rs.sort()
r = ', '.join(rs)
if ctx:
r = '{%s}' % r
elif not r:
r = '<Nothing>'
return r
def get_userkind(self, *args):
firstsok = None
clikinds = []
for arg in args:
if isinstance(arg, SoKind):
if not arg.classifier is self.referrer_classifier:
raise ValueError('Expected a SoKind with the %r classifier, argument had %r.' % (
self.referrer_classifier.name,
arg.classifier.name))
clikinds.extend(arg.clikinds)
if firstsok is None:
firstsok = arg
else:
# Assume we got a single kind
# get_kindarg takes care of classifier error checking
clikinds.append(self.referrer_classifier.get_kindarg(arg))
if len(args) > 1 or firstsok is None:
sok = QuickSoKind(self.referrer_classifier,
self.mod.ImpSet.immnodeset(clikinds))
else:
sok = firstsok
return self.family(sok)
class InRelFamily:
def __init__(self, mod, classifier):
self.classifier = classifier
self.defrefining(mod.Use.Anything)
def _eq_args(self, a, b):
# They are sequences (immnodesets) of relations.
# I have not memoized them since I was afraid they would last too long
# and I thought it not be worthwhile and hope this comparison is not done too often.
# So I will compare them as equality based sets.
a = dict([(x, ()) for x in a])
b = dict([(x, ()) for x in b])
return a == b
def _ge_ATOM(self, a, b):
# b is known to not be Nothing since its c_le doesn't call back
if self is b.fam:
return self._eq_args(a.arg, b.arg)
return b.fam.supercl is not None and b.fam.supercl <= a
def _le_ATOM(self, a, b):
# b is known to not be Nothing since its c_ge doesn't call back
if self is b.fam:
return self._eq_args(a.arg, b.arg)
return self.supercl is not None and self.supercl <= b
def c_alt(self, a, alt):
return self.classifier.get_alt(a, alt)
def c_get_brief(self, a):
return '<via %s>' % self.classifier.get_tabrendering(a, None)
def c_repr(self, a):
return '%s(%s)' % (self.classifier.get_reprname(),
self.classifier.get_userkindargrepr(a))
class ByInRel(Classifier):
def __init__(self, mod, name, rg):
Classifier.__init__(self, mod, name, with_referrers=True)
self.rg = rg
self.family = mod.fam_mixin_argatom(InRelFamily, self)
def _rel2str(self, r):
P = self.mod._parent.Path
t = P.rel_table
x = t[r.kind](r.relator)
s = x.stra('_', safe=False)
if s.startswith('_'):
s = s[1:]
return s
def _str2rel(self, s):
# Parse a string as generated by rel2str,
# to recreate the relation object.
P = self.mod._parent.Path
orgs = s
def mkrel(R, *args):
return self.mod.View.heapyc.Relation(R.code, *args)
if s.startswith('list(_)['):
s = s[8:].rstrip(']')
r = int(s)
rel = mkrel(P.R_INSET, r)
return rel
if s.startswith('_'):
s = s[1:]
if s.startswith('['):
s = s[1:].rstrip(']')
loc = {'hp': self.mod.Use}
r = eval(s, loc)
rel = mkrel(P.R_INDEXVAL, r)
elif s.startswith('.'):
s = s[1:]
if s.replace('_', 'x').isalnum():
rel = mkrel(P.R_ATTRIBUTE, s)
elif s.startswith('f_locals['):
s = s[9:].rstrip(']')
r = eval(s, {})
rel = mkrel(P.R_LOCAL_VAR, r)
elif s.startswith('f_locals ['):
s = s[10:].rstrip(']')
r = eval(s, {})
rel = mkrel(P.R_CELL, r)
elif s.startswith('keys()['):
s = s[7:].rstrip(']')
r = int(s)
rel = mkrel(P.R_INDEXKEY, r)
elif s.startswith('__dict__.keys()['):
s = s[16:].rstrip(']')
r = int(s)
rel = mkrel(P.R_HASATTR, r)
else:
raise SyntaxError('Cant make a relation of %r.' % orgs)
elif s.startswith('->'):
s = s[2:]
if s.startswith('f_valuestack['):
s = s[13:].rstrip(']')
r = int(s)
rel = mkrel(P.R_STACK, r)
else:
rel = mkrel(P.R_INTERATTR, s)
else:
raise SyntaxError('Cant make a relation of %r.' % orgs)
return rel
def get_byname(self):
return 'referred via'
def get_cli(self):
memokind = {}
memorel = {}
return self.mod.hv.cli_inrel(self.rg, memokind, memorel)
def get_kind(self, k):
return self.family(k)
def get_tabheader(self, ctx=''):
if not ctx:
return "Referred Via:"
else:
r = 'Referred Via'
if ctx == 'and':
r = '{%s}' % r
return r
def get_tabrendering(self, kind, ctx=''):
r = self.get_userkindargrepr(kind)
if ctx == 'and':
r = '{%s}' % r
return r
def get_userkind(self, *args):
return self.get_kind([self._str2rel(x) for x in args])
def get_userkindargrepr(self, kind):
a = [repr(self._rel2str(x)) for x in kind.arg]
a.sort()
return ', '.join(a)
class AndClassifier(Classifier):
def __init__(self, mod, name, args): # At least 2 args
if name is None:
name = '(%s)' % ' & '.join([x.name for x in args])
Classifier.__init__(self, mod, name, cli=None,
supers=args, depends=args)
self.args = args
def get_byname(self):
return '<%s>' % ' & '.join([x.get_byname() for x in self.args])
def get_cli(self):
memo = {}
return self.mod.hv.cli_and(tuple([x.cli for x in self.args]), memo)
def get_kind(self, k):
ks = []
for ki, ci in zip(k, self.args):
ks.append(ci.get_kind(ki))
return self.mod.UniSet.fam_And._cons(ks)
def get_reprname(self):
return '(%s)' % ' & '.join([x.get_reprname() for x in self.args])
def get_tabheader(self, ctx=''):
r = '%s' % ' & '.join([x.get_tabheader('and') for x in self.args])
if ctx == 'and':
r = '(%s)' % r
return r
def get_tabrendering(self, cla, ctx=''):
ss = []
for a, cl in zip(cla.arg, self.args):
s = cl.get_tabrendering(a, 'and')
ss.append(s)
r = ' & '.join(ss)
if ctx == 'and':
r = '(%s)' % r
return r
class ModuleFamily:
def __init__(self, mod, classifier):
self.defrefining(mod.Use.Anything)
self.classifier = classifier
self.range = mod.fam_Family(self)
def c_contains(self, a, b):
return b is a.arg
def c_get_render(self, a):
return self.mod.summary_str(a.arg)
def c_get_brief(self, a):
return self.mod.summary_str(type(a.arg))(a.arg)
def c_repr(self, a):
return '%s(%s)' % (self.classifier.get_reprname(),
self.classifier.get_userkindargrepr(a))
class ByModule(Classifier):
def __init__(self, mod, name):
def classify(x):
self.nc += 1
return x
cli = mod.hv.cli_user_defined(mod.Use.Type.classifier.cli,
mod.Use.Type.Module.arg,
classify,
None
)
Classifier.__init__(self, mod, name, cli)
self.not_module = ~mod.Use.Type.Module
self.nc = 0
self.family = mod.fam_mixin_argatom(ModuleFamily, self)
self.ModuleType = mod.types.ModuleType
def get_byname(self):
return 'module'
def get_kind(self, k):
if k is None:
return self.not_module
else:
return self.family(k)
def get_kindarg(self, kind):
if kind is self.not_module:
return None
else:
assert kind.fam is self.family
return kind.arg
def get_tabheader(self, ctx=''):
return 'Module'
def get_userkind(self, name=None, at=None):
if name is None and at is None:
return self.not_module
if at is None:
try:
m = self.mod.View.target.sys.modules[name]
except KeyError:
raise ValueError(
'No module %r in View.target.sys.modules.' % name)
else:
m = self.mod.View.obj_at(at)
if not isinstance(m, self.ModuleType):
raise TypeError(
'The specified object is not of module type, but %r.' % type(m))
if name is not None and m.__name__ != name:
raise ValueError(
'The specified module has not name %r but %r.' % (name, m.__name__))
return self.family(m)
def get_userkindargrepr(self, kind):
if kind is self.not_module:
return ''
else:
m = kind.arg
name = m.__name__
s = '%r' % name
if self.mod._root.sys.modules.get(name) is not m:
s += ', at=%s' % hex(id(m))
return s
class AltFamily:
def __init__(self, mod, altcode):
if altcode not in ('<', '<=', '==', '!=', '>', '>='):
raise ValueError('No such comparison symbol: %r' % altcode)
self.altcode = altcode
self.disjoints -= [self]
def c_get_brief(self, a):
return a.arg.fam.c_get_brief_alt(a.arg, self.altcode)
def c_get_ckc(self, a):
ckc = list(a.arg.get_ckc())
if ckc[-1] == '==':
ckc[-1] = self.altcode
else:
raise ValueError(
'Can not make alternative kind, non-equality comparison on underlying kind.')
return tuple(ckc)
def c_repr(self, a):
return '%s.alt(%r)' % (repr(a.arg), self.altcode)
class FindexFamily:
def __init__(self, mod, classifier):
self.defrefining(mod.Use.Anything)
self.classifier = classifier
self.range = mod.fam_Family(self)
def c_get_brief(self, a):
if not 0 <= a.arg < len(self.classifier.kinds):
return '<None>'
else:
return '%s / %d' % (self.classifier.kinds[a.arg].brief, a.arg)
def c_repr(self, a):
return '%s(%d)' % (self.classifier.get_reprname(), a.arg)
class ByFindex(Classifier):
def __init__(self, mod, name, kinds):
self.alts = [k.fam.c_get_ckc(k) for k in kinds]
depends = [ckc[0] for ckc in self.alts]
Classifier.__init__(self, mod, name, depends=depends)
self.kinds = kinds
self.family = mod.fam_mixin_argatom(FindexFamily, self)
def get_cli(self):
alts = tuple([(cla.cli, k, cmp) for (cla, k, cmp) in self.alts])
memo = {}
cli = self.mod.hv.cli_findex(alts, memo)
return cli
def get_byname(self):
return 'index of first matching kind of %s' % (self.kinds,)
def get_tabheader(self, ctx=''):
return 'First Matching Kind / Index'
class ProdFamily:
def __init__(self, mod, classifier):
self.defrefining(mod.Use.Anything)
self.classifier = classifier
self.range = mod.fam_Family(self)
def c_alt(self, a, alt):
return self.classifier.get_alt(a, alt)
def c_get_brief(self, a):
if a.arg is None:
return 'unknown'
else:
return '%s:%d' % a.arg
def c_repr(self, a):
return '%s(%s)' % (self.classifier.get_reprname(),
self.classifier.get_userkindargrepr(a))
class ByProd(Classifier):
def __init__(self, mod, name):
Classifier.__init__(self, mod, name)
self.family = mod.fam_mixin_argatom(ProdFamily, self)
def get_byname(self):
return 'producer'
def get_cli(self):
self.mod.Use._check_tracemalloc()
memo = {}
return self.mod.hv.cli_prod(memo)
def get_tabheader(self, ctx=''):
return 'Producer (line of allocation)'
def get_userkind(self, *args, **kwds):
if args and kwds:
raise TypeError(
'{}() takes either positional or keyword arguments'.format(
self.get_reprname()))
if kwds:
if set(kwds.keys()) != {'filename', 'lineno'}:
raise TypeError(
'{}() keyword arguments must be '
'"filename" and "lineno"'.format(
self.get_reprname()))
return self.family((kwds['filename'], kwds['lineno']))
if len(args) == 0:
return self.family(None)
elif len(args) == 1:
arg, = args
if isinstance(arg, str):
# filename
return self.family((arg, None)).alt('<')
filename = self.mod.inspect.getsourcefile(arg)
lines, lnum = self.mod.inspect.getsourcelines(arg)
lines, lnum = len(lines), max(lnum, 1)
return (
self.family((filename, None)).alt('<') &
self.family((None, lnum)).alt('>=') &
self.family((None, lnum + lines)).alt('<'))
elif len(args) == 2:
filename, lineno = args
if filename is not None and not isinstance(filename, str):
raise TypeError(
'{}() argument 1 must be string or None'.format(
self.get_reprname()))
if lineno is not None and not isinstance(lineno, int):
raise TypeError(
'{}() argument 2 must be integer or None'.format(
self.get_reprname()))
return self.family((filename, lineno))
else:
raise TypeError(
'{}() takes from 0 to 2 positional arguments '
'but {} were given'.format(
self.get_reprname(), len(args)))
def get_userkindargrepr(self, kind):
if kind.arg is None:
return ''
return '%r, %r' % kind.arg
class _GLUECLAMP_:
_imports_ = (
'_parent:ImpSet',
'_parent:View',
'_parent.View:hv',
'_parent:UniSet',
'_parent.UniSet:fam_mixin_argatom',
'_parent:Use',
'_root.guppy.etc.etc:str2int',
'_root:inspect',
'_root:re',
'_root:types',
'_root:builtins',
)
def _er_by_(self, constructor, *args, **kwds):
return self.UniSet.fam_EquivalenceRelation(constructor, *args, **kwds)
# Exported equivalence relations
def _get_Clodo(self):
return self._er_by_(ByClassOrDictOwner, self, name='Clodo')
def _get_Id(self):
return self._er_by_(ByIdentity, self, name='Id')
def _get_Idset(self):
return self._er_by_(ByIdentitySet, self, name='Idset')
def _get_Module(self):
return self._er_by_(ByModule, self, name='Module')
def _get_Prod(self):
return self._er_by_(ByProd, self, name='Prod')
def _get_Unity(self):
return self._er_by_(ByUnity, self, name='Unity')
def _get_Rcs(self):
return self.mker_refdby(self.Clodo)
def mker_and(self, ers):
if len(ers) == 0:
return self.Unity
classifiers = [er.classifier for er in ers]
name = None
return self.UniSet.fam_EquivalenceRelation(AndClassifier, self, name, classifiers)
def mker_dictof(self, er, name=None):
if name is None:
name = '%s.dictof' % er.classifier.name
return self.mker_memoized(
name,
lambda:
self._er_by_(ByDictOwner, self, name, er.classifier))
def _get_memo_er(self):
return {}
def mker_memoized(self, name, f):
v = self.memo_er.get(name)
if v is None:
self.memo_er[name] = v = f()
return v
def mker_refdby(self, er, name=None):
if name is None:
name = '%s.refdby' % er.classifier.name
return self.mker_memoized(
name,
lambda:
self._er_by_(
ByRetClaSet,
self,
name,
self.View.rg,
er.classifier,
"""%s
Classify by <%s> of referrers.
This classifier uses the %r classifier to classify the
referrers of the object. The classifications of the referrers
are collected in a set. This set becomes the classification of
the object.
""" % (name, er.classifier.get_byname(), er.classifier.name)))
def _get_Size(self):
return self._er_by_(ByIndiSize, self, 'Size')
def _get_Type(self):
return self._er_by_(ByType, self, 'Type')
def _get_Via(self):
View = self.View
return self._er_by_(
ByInRel,
self,
'Via',
View.rg)
def tc_adapt(self, k):
# Adapt to a type.
# Accepts a type object, or a string representation
# (at least as) by tc_repr.
if isinstance(k, type):
return k
if not isinstance(k, str):
raise TypeError('type, class or basestring expected')
err = ("String argument to tc_adapt should be of form\n"
"'<class MODULE.NAME at 0xADDR>' or\n"
"'<type MODULE.NAME at 0xADDR>' or\n"
"'<at 0xADDR>'. I got: %r" % k)
s = k
if not (s.startswith('<') and s.endswith('>')):
raise ValueError(err)
s = s.lstrip('<').rstrip('>')
s = s.split(' ')
if len(s) < 2:
raise ValueError(err)
t = s[0]
addr = self.str2int(s[-1])
kind = self.View.obj_at(addr)
if t == 'at':
if len(s) != 2:
raise ValueError(err)
ty = None
else:
if len(s) != 4:
raise ValueError(err)
if t not in ('type', 'class'):
raise ValueError(err)
try:
ty = getattr(self.types, t.capitalize()+'Type')
except AttributeError:
ty = getattr(self.builtins, t.lower())
if not isinstance(kind, ty):
raise TypeError('%s object expected' % t)
if not s[2] == 'at':
raise ValueError(err)
names = s[1].split('.')
if len(names) < 2:
raise ValueError(err)
modulename = '.'.join(names[:-1])
tcname = names[-1]
if kind.__module__ != modulename:
raise ValueError(
'The %s %r has wrong __module__, expected %r.' % (t, kind, modulename))
if kind.__name__ != tcname:
raise ValueError(
'The %s %r has wrong __name__, expected %r.' % (t, kind, tcname))
return kind
def tc_repr(self, k):
# Represent a type object as a string,
# so that it can converted back via tc_adapt,
# as long as it still exists in the heap.
# There is no absolute guarantee that it will always become the same object,
# but I hope it will work well enough in practice.
# See also Notes Sep 7 2005.
if isinstance(k, type):
t = 'type'
else:
raise TypeError('type expected')
return '<%s %s.%s at %s>' % (t, k.__module__, k.__name__, hex(id(k)))
# Convenience interfaces
def _get_alt(self):
altmemo = {
'==': lambda k: k,
'!=': lambda k: ~k,
}
def alt(kind, cmp):
a = altmemo.get(cmp)
if a is None:
a = self.fam_mixin_argatom(AltFamily, cmp)
altmemo[cmp] = a
return a(kind)
return alt
def biper(self, kind):
return self.findex(kind)
def _get_dictof(self):
return self.fam_mixin_argatom(OwnedDictFamily)
def _get_dictofnothing(self):
return self.dictof(self.Use.Nothing)
def _get_invtypemod(self):
invtypemod = {}
for k, v in list(self.types._module.__dict__.items()):
if k.endswith('Type'):
invtypemod[v] = k[:-4]
return invtypemod
def _get_notdict(self):
return ~self.Use.Type.Dict
def findex(self, *kinds):
return self._er_by_(
ByFindex,
self,
'findex(%s)' % ', '.join([repr(k) for k in kinds]),
kinds
)
def _get_refdbynothing(self):
return self.sonokind.refdby
def sokind(self, *kinds):
"""sokind(0..*:Kind+) -> SetOfKind
"""
cla = None
clikinds = []
if not kinds:
raise ValueError('At least one argument must be given.')
for kind in kinds:
ckc = kind.get_ckc()
if cla is None:
cla = ckc[0]
else:
if ckc[0] is not cla:
raise ValueError(
'Kind at index %d has wrong classifier.' % len(clikinds))
if ckc[-1] != '==':
raise ValueError(
'Kind at index %d has wrong comparision.' % len(clikinds))
clikinds.append(ckc[1])
return QuickSoKind(cla, self.ImpSet.immnodeset(clikinds))
def _get_sonokind(self):
return SoNoKind(self.Unity, ())
Zerion Mini Shell 1.0