PageRenderTime 59ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 1ms

/pypy/objspace/std/typeobject.py

https://bitbucket.org/kkris/pypy
Python | 971 lines | 867 code | 56 blank | 48 comment | 107 complexity | 2a5b3b3dd016ce19626a8818098aff4a MD5 | raw file
  1. from pypy.objspace.std.model import W_Object
  2. from pypy.objspace.std.register_all import register_all
  3. from pypy.interpreter.function import Function, StaticMethod
  4. from pypy.interpreter import gateway
  5. from pypy.interpreter.error import OperationError, operationerrfmt
  6. from pypy.interpreter.typedef import weakref_descr
  7. from pypy.interpreter.baseobjspace import W_Root
  8. from pypy.objspace.std.stdtypedef import std_dict_descr, issubtypedef, Member
  9. from pypy.objspace.std.objecttype import object_typedef
  10. from pypy.objspace.std import identitydict
  11. from rpython.rlib.objectmodel import we_are_translated
  12. from rpython.rlib.objectmodel import current_object_addr_as_int, compute_hash
  13. from rpython.rlib.jit import promote, elidable_promote, we_are_jitted,\
  14. promote_string
  15. from rpython.rlib.jit import elidable, dont_look_inside, unroll_safe
  16. from rpython.rlib.rarithmetic import intmask, r_uint
  17. class TypeCell(W_Root):
  18. def __init__(self, w_value=None):
  19. self.w_value = w_value
  20. def unwrap_cell(space, w_value):
  21. if (space.config.objspace.std.withtypeversion and
  22. isinstance(w_value, TypeCell)):
  23. return w_value.w_value
  24. return w_value
  25. # from compiler/misc.py
  26. MANGLE_LEN = 256 # magic constant from compile.c
  27. def _mangle(name, klass):
  28. if not name.startswith('__'):
  29. return name
  30. if len(name) + 2 >= MANGLE_LEN:
  31. return name
  32. if name.endswith('__'):
  33. return name
  34. try:
  35. i = 0
  36. while klass[i] == '_':
  37. i = i + 1
  38. except IndexError:
  39. return name
  40. klass = klass[i:]
  41. tlen = len(klass) + len(name)
  42. if tlen > MANGLE_LEN:
  43. end = len(klass) + MANGLE_LEN-tlen
  44. if end < 0:
  45. klass = '' # annotator hint
  46. else:
  47. klass = klass[:end]
  48. return "_%s%s" % (klass, name)
  49. class VersionTag(object):
  50. pass
  51. class MethodCache(object):
  52. def __init__(self, space):
  53. assert space.config.objspace.std.withmethodcache
  54. SIZE = 1 << space.config.objspace.std.methodcachesizeexp
  55. self.versions = [None] * SIZE
  56. self.names = [None] * SIZE
  57. self.lookup_where = [(None, None)] * SIZE
  58. if space.config.objspace.std.withmethodcachecounter:
  59. self.hits = {}
  60. self.misses = {}
  61. def clear(self):
  62. None_None = (None, None)
  63. for i in range(len(self.versions)):
  64. self.versions[i] = None
  65. for i in range(len(self.names)):
  66. self.names[i] = None
  67. for i in range(len(self.lookup_where)):
  68. self.lookup_where[i] = None_None
  69. # possible values of compares_by_identity_status
  70. UNKNOWN = 0
  71. COMPARES_BY_IDENTITY = 1
  72. OVERRIDES_EQ_CMP_OR_HASH = 2
  73. class W_TypeObject(W_Object):
  74. from pypy.objspace.std.typetype import type_typedef as typedef
  75. lazyloaders = {} # can be overridden by specific instances
  76. # the version_tag changes if the dict or the inheritance hierarchy changes
  77. # other changes to the type (e.g. the name) leave it unchanged
  78. _version_tag = None
  79. _immutable_fields_ = ["flag_heaptype",
  80. "flag_cpytype",
  81. "flag_abstract?",
  82. 'needsdel',
  83. 'weakrefable',
  84. 'hasdict',
  85. 'nslots',
  86. 'instancetypedef',
  87. 'terminator',
  88. '_version_tag?',
  89. 'name?',
  90. 'mro_w?[*]',
  91. ]
  92. # for config.objspace.std.getattributeshortcut
  93. # (False is a conservative default, fixed during real usage)
  94. uses_object_getattribute = False
  95. # for config.objspace.std.withidentitydict
  96. compares_by_identity_status = UNKNOWN
  97. # used to cache the type's __new__ function
  98. w_new_function = None
  99. @dont_look_inside
  100. def __init__(w_self, space, name, bases_w, dict_w,
  101. overridetypedef=None):
  102. w_self.space = space
  103. w_self.name = name
  104. w_self.bases_w = bases_w
  105. w_self.dict_w = dict_w
  106. w_self.nslots = 0
  107. w_self.hasdict = False
  108. w_self.needsdel = False
  109. w_self.weakrefable = False
  110. w_self.w_doc = space.w_None
  111. w_self.weak_subclasses = []
  112. w_self.flag_heaptype = False
  113. w_self.flag_cpytype = False
  114. w_self.flag_abstract = False
  115. w_self.instancetypedef = overridetypedef
  116. if overridetypedef is not None:
  117. setup_builtin_type(w_self)
  118. else:
  119. setup_user_defined_type(w_self)
  120. w_self.w_same_layout_as = get_parent_layout(w_self)
  121. if space.config.objspace.std.withtypeversion:
  122. if not is_mro_purely_of_types(w_self.mro_w):
  123. pass
  124. else:
  125. # the _version_tag should change, whenever the content of
  126. # dict_w of any of the types in the mro changes, or if the mro
  127. # itself changes
  128. w_self._version_tag = VersionTag()
  129. if space.config.objspace.std.withmapdict:
  130. from pypy.objspace.std.mapdict import DictTerminator, NoDictTerminator
  131. if w_self.hasdict:
  132. w_self.terminator = DictTerminator(space, w_self)
  133. else:
  134. w_self.terminator = NoDictTerminator(space, w_self)
  135. def mutated(w_self, key):
  136. """
  137. The type is being mutated. key is either the string containing the
  138. specific attribute which is being deleted/set or None to indicate a
  139. generic mutation.
  140. """
  141. space = w_self.space
  142. assert w_self.is_heaptype()
  143. if (not space.config.objspace.std.withtypeversion and
  144. not space.config.objspace.std.getattributeshortcut and
  145. not space.config.objspace.std.withidentitydict and
  146. not space.config.objspace.std.newshortcut):
  147. return
  148. if space.config.objspace.std.getattributeshortcut:
  149. w_self.uses_object_getattribute = False
  150. # ^^^ conservative default, fixed during real usage
  151. if space.config.objspace.std.withidentitydict:
  152. if (key is None or key == '__eq__' or
  153. key == '__cmp__' or key == '__hash__'):
  154. w_self.compares_by_identity_status = UNKNOWN
  155. if space.config.objspace.std.newshortcut:
  156. w_self.w_new_function = None
  157. if (space.config.objspace.std.withtypeversion
  158. and w_self._version_tag is not None):
  159. w_self._version_tag = VersionTag()
  160. subclasses_w = w_self.get_subclasses()
  161. for w_subclass in subclasses_w:
  162. assert isinstance(w_subclass, W_TypeObject)
  163. w_subclass.mutated(key)
  164. def version_tag(w_self):
  165. if not we_are_jitted() or w_self.is_heaptype():
  166. return w_self._version_tag
  167. # prebuilt objects cannot get their version_tag changed
  168. return w_self._pure_version_tag()
  169. @elidable_promote()
  170. def _pure_version_tag(w_self):
  171. return w_self._version_tag
  172. def getattribute_if_not_from_object(w_self):
  173. """ this method returns the applevel __getattribute__ if that is not
  174. the one from object, in which case it returns None """
  175. from pypy.objspace.descroperation import object_getattribute
  176. if not we_are_jitted():
  177. shortcut = w_self.space.config.objspace.std.getattributeshortcut
  178. if not shortcut or not w_self.uses_object_getattribute:
  179. # slow path: look for a custom __getattribute__ on the class
  180. w_descr = w_self.lookup('__getattribute__')
  181. # if it was not actually overriden in the class, we remember this
  182. # fact for the next time.
  183. if w_descr is object_getattribute(w_self.space):
  184. if shortcut:
  185. w_self.uses_object_getattribute = True
  186. else:
  187. return w_descr
  188. return None
  189. # in the JIT case, just use a lookup, because it is folded away
  190. # correctly using the version_tag
  191. w_descr = w_self.lookup('__getattribute__')
  192. if w_descr is not object_getattribute(w_self.space):
  193. return w_descr
  194. def has_object_getattribute(w_self):
  195. return w_self.getattribute_if_not_from_object() is None
  196. def compares_by_identity(w_self):
  197. from pypy.objspace.descroperation import object_hash, type_eq
  198. if not w_self.space.config.objspace.std.withidentitydict:
  199. return False # conservative
  200. #
  201. if w_self.compares_by_identity_status != UNKNOWN:
  202. # fast path
  203. return w_self.compares_by_identity_status == COMPARES_BY_IDENTITY
  204. #
  205. default_hash = object_hash(w_self.space)
  206. my_eq = w_self.lookup('__eq__')
  207. overrides_eq = (my_eq and my_eq is not type_eq(w_self.space))
  208. overrides_eq_cmp_or_hash = (overrides_eq or
  209. w_self.lookup('__cmp__') or
  210. w_self.lookup('__hash__') is not default_hash)
  211. if overrides_eq_cmp_or_hash:
  212. w_self.compares_by_identity_status = OVERRIDES_EQ_CMP_OR_HASH
  213. else:
  214. w_self.compares_by_identity_status = COMPARES_BY_IDENTITY
  215. return w_self.compares_by_identity_status == COMPARES_BY_IDENTITY
  216. def ready(w_self):
  217. for w_base in w_self.bases_w:
  218. if not isinstance(w_base, W_TypeObject):
  219. continue
  220. w_base.add_subclass(w_self)
  221. # compute a tuple that fully describes the instance layout
  222. def get_full_instance_layout(w_self):
  223. w_layout = w_self.w_same_layout_as or w_self
  224. return (w_layout, w_self.hasdict, w_self.needsdel, w_self.weakrefable)
  225. def compute_default_mro(w_self):
  226. return compute_C3_mro(w_self.space, w_self)
  227. def getdictvalue(w_self, space, attr):
  228. if space.config.objspace.std.withtypeversion:
  229. version_tag = w_self.version_tag()
  230. if version_tag is not None:
  231. return unwrap_cell(
  232. space,
  233. w_self._pure_getdictvalue_no_unwrapping(
  234. space, version_tag, attr))
  235. w_value = w_self._getdictvalue_no_unwrapping(space, attr)
  236. return unwrap_cell(space, w_value)
  237. def _getdictvalue_no_unwrapping(w_self, space, attr):
  238. w_value = w_self.dict_w.get(attr, None)
  239. if w_self.lazyloaders and w_value is None:
  240. if attr in w_self.lazyloaders:
  241. # very clever next line: it forces the attr string
  242. # to be interned.
  243. w_attr = space.new_interned_str(attr)
  244. loader = w_self.lazyloaders[attr]
  245. del w_self.lazyloaders[attr]
  246. w_value = loader()
  247. if w_value is not None: # None means no such attribute
  248. w_self.dict_w[attr] = w_value
  249. return w_value
  250. return w_value
  251. @elidable
  252. def _pure_getdictvalue_no_unwrapping(w_self, space, version_tag, attr):
  253. return w_self._getdictvalue_no_unwrapping(space, attr)
  254. def setdictvalue(w_self, space, name, w_value):
  255. if not w_self.is_heaptype():
  256. msg = "can't set attributes on type object '%s'"
  257. raise operationerrfmt(space.w_TypeError, msg, w_self.name)
  258. if name == "__del__" and name not in w_self.dict_w:
  259. msg = "a __del__ method added to an existing type will not be called"
  260. space.warn(msg, space.w_RuntimeWarning)
  261. if space.config.objspace.std.withtypeversion:
  262. version_tag = w_self.version_tag()
  263. if version_tag is not None:
  264. w_curr = w_self._pure_getdictvalue_no_unwrapping(
  265. space, version_tag, name)
  266. if w_curr is not None:
  267. if isinstance(w_curr, TypeCell):
  268. w_curr.w_value = w_value
  269. return True
  270. w_value = TypeCell(w_value)
  271. w_self.mutated(name)
  272. w_self.dict_w[name] = w_value
  273. return True
  274. def deldictvalue(w_self, space, key):
  275. if w_self.lazyloaders:
  276. w_self._cleanup_() # force un-lazification
  277. if not w_self.is_heaptype():
  278. msg = "can't delete attributes on type object '%s'"
  279. raise operationerrfmt(space.w_TypeError, msg, w_self.name)
  280. try:
  281. del w_self.dict_w[key]
  282. except KeyError:
  283. return False
  284. else:
  285. w_self.mutated(key)
  286. return True
  287. def lookup(w_self, name):
  288. # note that this doesn't call __get__ on the result at all
  289. space = w_self.space
  290. if space.config.objspace.std.withmethodcache:
  291. return w_self.lookup_where_with_method_cache(name)[1]
  292. return w_self._lookup(name)
  293. def lookup_where(w_self, name):
  294. space = w_self.space
  295. if space.config.objspace.std.withmethodcache:
  296. return w_self.lookup_where_with_method_cache(name)
  297. return w_self._lookup_where(name)
  298. @unroll_safe
  299. def lookup_starting_at(w_self, w_starttype, name):
  300. space = w_self.space
  301. look = False
  302. for w_class in w_self.mro_w:
  303. if w_class is w_starttype:
  304. look = True
  305. elif look:
  306. w_value = w_class.getdictvalue(space, name)
  307. if w_value is not None:
  308. return w_value
  309. return None
  310. @unroll_safe
  311. def _lookup(w_self, key):
  312. space = w_self.space
  313. for w_class in w_self.mro_w:
  314. w_value = w_class.getdictvalue(space, key)
  315. if w_value is not None:
  316. return w_value
  317. return None
  318. @unroll_safe
  319. def _lookup_where(w_self, key):
  320. # like lookup() but also returns the parent class in which the
  321. # attribute was found
  322. space = w_self.space
  323. for w_class in w_self.mro_w:
  324. w_value = w_class.getdictvalue(space, key)
  325. if w_value is not None:
  326. return w_class, w_value
  327. return None, None
  328. def _lookup_where_all_typeobjects(w_self, key):
  329. # like _lookup_where(), but when we know that w_self.mro_w only
  330. # contains W_TypeObjects. (It differs from _lookup_where() mostly
  331. # from a JIT point of view: it cannot invoke arbitrary Python code.)
  332. space = w_self.space
  333. for w_class in w_self.mro_w:
  334. assert isinstance(w_class, W_TypeObject)
  335. w_value = w_class._getdictvalue_no_unwrapping(space, key)
  336. if w_value is not None:
  337. return w_class, w_value
  338. return None, None
  339. def lookup_where_with_method_cache(w_self, name):
  340. space = w_self.space
  341. promote(w_self)
  342. assert space.config.objspace.std.withmethodcache
  343. version_tag = promote(w_self.version_tag())
  344. if version_tag is None:
  345. tup = w_self._lookup_where(name)
  346. return tup
  347. name = promote_string(name)
  348. w_class, w_value = w_self._pure_lookup_where_with_method_cache(name, version_tag)
  349. return w_class, unwrap_cell(space, w_value)
  350. @elidable
  351. def _pure_lookup_where_with_method_cache(w_self, name, version_tag):
  352. space = w_self.space
  353. cache = space.fromcache(MethodCache)
  354. SHIFT2 = r_uint.BITS - space.config.objspace.std.methodcachesizeexp
  355. SHIFT1 = SHIFT2 - 5
  356. version_tag_as_int = current_object_addr_as_int(version_tag)
  357. # ^^^Note: if the version_tag object is moved by a moving GC, the
  358. # existing method cache entries won't be found any more; new
  359. # entries will be created based on the new address. The
  360. # assumption is that the version_tag object won't keep moving all
  361. # the time - so using the fast current_object_addr_as_int() instead
  362. # of a slower solution like hash() is still a good trade-off.
  363. hash_name = compute_hash(name)
  364. product = intmask(version_tag_as_int * hash_name)
  365. method_hash = (r_uint(product) ^ (r_uint(product) << SHIFT1)) >> SHIFT2
  366. # ^^^Note2: we used to just take product>>SHIFT2, but on 64-bit
  367. # platforms SHIFT2 is really large, and we loose too much information
  368. # that way (as shown by failures of the tests that typically have
  369. # method names like 'f' who hash to a number that has only ~33 bits).
  370. cached_version_tag = cache.versions[method_hash]
  371. if cached_version_tag is version_tag:
  372. cached_name = cache.names[method_hash]
  373. if cached_name is name:
  374. tup = cache.lookup_where[method_hash]
  375. if space.config.objspace.std.withmethodcachecounter:
  376. cache.hits[name] = cache.hits.get(name, 0) + 1
  377. # print "hit", w_self, name
  378. return tup
  379. tup = w_self._lookup_where_all_typeobjects(name)
  380. cache.versions[method_hash] = version_tag
  381. cache.names[method_hash] = name
  382. cache.lookup_where[method_hash] = tup
  383. if space.config.objspace.std.withmethodcachecounter:
  384. cache.misses[name] = cache.misses.get(name, 0) + 1
  385. # print "miss", w_self, name
  386. return tup
  387. def check_user_subclass(w_self, w_subtype):
  388. space = w_self.space
  389. if not isinstance(w_subtype, W_TypeObject):
  390. raise operationerrfmt(space.w_TypeError,
  391. "X is not a type object ('%s')",
  392. space.type(w_subtype).getname(space))
  393. if not w_subtype.issubtype(w_self):
  394. raise operationerrfmt(space.w_TypeError,
  395. "%s.__new__(%s): %s is not a subtype of %s",
  396. w_self.name, w_subtype.name, w_subtype.name, w_self.name)
  397. if w_self.instancetypedef is not w_subtype.instancetypedef:
  398. raise operationerrfmt(space.w_TypeError,
  399. "%s.__new__(%s) is not safe, use %s.__new__()",
  400. w_self.name, w_subtype.name, w_subtype.name)
  401. return w_subtype
  402. def _cleanup_(w_self):
  403. "NOT_RPYTHON. Forces the lazy attributes to be computed."
  404. if 'lazyloaders' in w_self.__dict__:
  405. for attr in w_self.lazyloaders.keys():
  406. w_self.getdictvalue(w_self.space, attr)
  407. del w_self.lazyloaders
  408. def getdict(w_self, space): # returning a dict-proxy!
  409. from pypy.objspace.std.dictproxyobject import DictProxyStrategy
  410. from pypy.objspace.std.dictmultiobject import W_DictMultiObject
  411. if w_self.lazyloaders:
  412. w_self._cleanup_() # force un-lazification
  413. strategy = space.fromcache(DictProxyStrategy)
  414. storage = strategy.erase(w_self)
  415. return W_DictMultiObject(space, strategy, storage)
  416. def unwrap(w_self, space):
  417. from pypy.objspace.std.model import UnwrapError
  418. raise UnwrapError(w_self)
  419. def is_heaptype(w_self):
  420. return w_self.flag_heaptype
  421. def is_cpytype(w_self):
  422. return w_self.flag_cpytype
  423. def is_abstract(w_self):
  424. return w_self.flag_abstract
  425. def set_abstract(w_self, abstract):
  426. w_self.flag_abstract = bool(abstract)
  427. def issubtype(w_self, w_type):
  428. promote(w_self)
  429. promote(w_type)
  430. if w_self.space.config.objspace.std.withtypeversion and we_are_jitted():
  431. version_tag1 = w_self.version_tag()
  432. version_tag2 = w_type.version_tag()
  433. if version_tag1 is not None and version_tag2 is not None:
  434. res = _pure_issubtype(w_self, w_type, version_tag1, version_tag2)
  435. return res
  436. return _issubtype(w_self, w_type)
  437. def get_module(w_self):
  438. space = w_self.space
  439. if w_self.is_heaptype() and '__module__' in w_self.dict_w:
  440. return w_self.getdictvalue(space, '__module__')
  441. else:
  442. # for non-heap types, CPython checks for a module.name in the
  443. # type name. That's a hack, so we're allowed to use a different
  444. # hack...
  445. if ('__module__' in w_self.dict_w and
  446. space.isinstance_w(w_self.getdictvalue(space, '__module__'),
  447. space.w_str)):
  448. return w_self.getdictvalue(space, '__module__')
  449. return space.wrap('__builtin__')
  450. def get_module_type_name(w_self):
  451. space = w_self.space
  452. w_mod = w_self.get_module()
  453. if not space.isinstance_w(w_mod, space.w_str):
  454. mod = '__builtin__'
  455. else:
  456. mod = space.str_w(w_mod)
  457. if mod !='__builtin__':
  458. return '%s.%s' % (mod, w_self.name)
  459. else:
  460. return w_self.name
  461. def add_subclass(w_self, w_subclass):
  462. space = w_self.space
  463. if not space.config.translation.rweakref:
  464. return # no weakref support, don't keep track of subclasses
  465. import weakref
  466. assert isinstance(w_subclass, W_TypeObject)
  467. newref = weakref.ref(w_subclass)
  468. for i in range(len(w_self.weak_subclasses)):
  469. ref = w_self.weak_subclasses[i]
  470. if ref() is None:
  471. w_self.weak_subclasses[i] = newref
  472. return
  473. else:
  474. w_self.weak_subclasses.append(newref)
  475. def remove_subclass(w_self, w_subclass):
  476. space = w_self.space
  477. if not space.config.translation.rweakref:
  478. return # no weakref support, don't keep track of subclasses
  479. for i in range(len(w_self.weak_subclasses)):
  480. ref = w_self.weak_subclasses[i]
  481. if ref() is w_subclass:
  482. del w_self.weak_subclasses[i]
  483. return
  484. def get_subclasses(w_self):
  485. space = w_self.space
  486. if not space.config.translation.rweakref:
  487. msg = ("this feature requires weakrefs, "
  488. "which are not available in this build of PyPy")
  489. raise OperationError(space.w_RuntimeError,
  490. space.wrap(msg))
  491. subclasses_w = []
  492. for ref in w_self.weak_subclasses:
  493. w_ob = ref()
  494. if w_ob is not None:
  495. subclasses_w.append(w_ob)
  496. return subclasses_w
  497. # for now, weakref support for W_TypeObject is hard to get automatically
  498. _lifeline_ = None
  499. def getweakref(self):
  500. return self._lifeline_
  501. def setweakref(self, space, weakreflifeline):
  502. self._lifeline_ = weakreflifeline
  503. def delweakref(self):
  504. self._lifeline_ = None
  505. # ____________________________________________________________
  506. # Initialization of type objects
  507. def get_parent_layout(w_type):
  508. """Compute the most parent class of 'w_type' whose layout
  509. is the same as 'w_type', or None if all parents of 'w_type'
  510. have a different layout than 'w_type'.
  511. """
  512. w_starttype = w_type
  513. while len(w_type.bases_w) > 0:
  514. w_bestbase = find_best_base(w_type.space, w_type.bases_w)
  515. if w_type.instancetypedef is not w_bestbase.instancetypedef:
  516. break
  517. if w_type.nslots != w_bestbase.nslots:
  518. break
  519. w_type = w_bestbase
  520. if w_type is not w_starttype:
  521. return w_type
  522. else:
  523. return None
  524. def issublayout(w_layout1, w_layout2):
  525. space = w_layout2.space
  526. while w_layout1 is not w_layout2:
  527. w_layout1 = find_best_base(space, w_layout1.bases_w)
  528. if w_layout1 is None:
  529. return False
  530. w_layout1 = w_layout1.w_same_layout_as or w_layout1
  531. return True
  532. def find_best_base(space, bases_w):
  533. """The best base is one of the bases in the given list: the one
  534. whose layout a new type should use as a starting point.
  535. """
  536. w_bestbase = None
  537. for w_candidate in bases_w:
  538. if not isinstance(w_candidate, W_TypeObject):
  539. continue
  540. if w_bestbase is None:
  541. w_bestbase = w_candidate # for now
  542. continue
  543. candtypedef = w_candidate.instancetypedef
  544. besttypedef = w_bestbase.instancetypedef
  545. if candtypedef is besttypedef:
  546. # two candidates with the same typedef are equivalent unless
  547. # one has extra slots over the other
  548. if w_candidate.nslots > w_bestbase.nslots:
  549. w_bestbase = w_candidate
  550. elif issubtypedef(candtypedef, besttypedef):
  551. w_bestbase = w_candidate
  552. return w_bestbase
  553. def check_and_find_best_base(space, bases_w):
  554. """The best base is one of the bases in the given list: the one
  555. whose layout a new type should use as a starting point.
  556. This version checks that bases_w is an acceptable tuple of bases.
  557. """
  558. w_bestbase = find_best_base(space, bases_w)
  559. if w_bestbase is None:
  560. raise OperationError(space.w_TypeError,
  561. space.wrap("a new-style class can't have "
  562. "only classic bases"))
  563. if not w_bestbase.instancetypedef.acceptable_as_base_class:
  564. raise operationerrfmt(space.w_TypeError,
  565. "type '%s' is not an "
  566. "acceptable base class",
  567. w_bestbase.instancetypedef.name)
  568. # check that all other bases' layouts are superclasses of the bestbase
  569. w_bestlayout = w_bestbase.w_same_layout_as or w_bestbase
  570. for w_base in bases_w:
  571. if isinstance(w_base, W_TypeObject):
  572. w_layout = w_base.w_same_layout_as or w_base
  573. if not issublayout(w_bestlayout, w_layout):
  574. raise OperationError(space.w_TypeError,
  575. space.wrap("instance layout conflicts in "
  576. "multiple inheritance"))
  577. return w_bestbase
  578. def copy_flags_from_bases(w_self, w_bestbase):
  579. hasoldstylebase = False
  580. for w_base in w_self.bases_w:
  581. if not isinstance(w_base, W_TypeObject):
  582. hasoldstylebase = True
  583. continue
  584. w_self.hasdict = w_self.hasdict or w_base.hasdict
  585. w_self.needsdel = w_self.needsdel or w_base.needsdel
  586. w_self.weakrefable = w_self.weakrefable or w_base.weakrefable
  587. w_self.nslots = w_bestbase.nslots
  588. return hasoldstylebase
  589. def create_all_slots(w_self, hasoldstylebase):
  590. space = w_self.space
  591. dict_w = w_self.dict_w
  592. if '__slots__' not in dict_w:
  593. wantdict = True
  594. wantweakref = True
  595. else:
  596. wantdict = False
  597. wantweakref = False
  598. w_slots = dict_w['__slots__']
  599. if (space.isinstance_w(w_slots, space.w_str) or
  600. space.isinstance_w(w_slots, space.w_unicode)):
  601. slot_names_w = [w_slots]
  602. else:
  603. slot_names_w = space.unpackiterable(w_slots)
  604. for w_slot_name in slot_names_w:
  605. slot_name = space.str_w(w_slot_name)
  606. if slot_name == '__dict__':
  607. if wantdict or w_self.hasdict:
  608. raise OperationError(space.w_TypeError,
  609. space.wrap("__dict__ slot disallowed: "
  610. "we already got one"))
  611. wantdict = True
  612. elif slot_name == '__weakref__':
  613. if wantweakref or w_self.weakrefable:
  614. raise OperationError(space.w_TypeError,
  615. space.wrap("__weakref__ slot disallowed: "
  616. "we already got one"))
  617. wantweakref = True
  618. else:
  619. create_slot(w_self, slot_name)
  620. wantdict = wantdict or hasoldstylebase
  621. if wantdict: create_dict_slot(w_self)
  622. if wantweakref: create_weakref_slot(w_self)
  623. if '__del__' in dict_w: w_self.needsdel = True
  624. def create_slot(w_self, slot_name):
  625. space = w_self.space
  626. if not valid_slot_name(slot_name):
  627. raise OperationError(space.w_TypeError,
  628. space.wrap('__slots__ must be identifiers'))
  629. # create member
  630. slot_name = _mangle(slot_name, w_self.name)
  631. if slot_name not in w_self.dict_w:
  632. # Force interning of slot names.
  633. slot_name = space.str_w(space.new_interned_str(slot_name))
  634. # in cpython it is ignored less, but we probably don't care
  635. member = Member(w_self.nslots, slot_name, w_self)
  636. w_self.dict_w[slot_name] = space.wrap(member)
  637. w_self.nslots += 1
  638. def create_dict_slot(w_self):
  639. if not w_self.hasdict:
  640. w_self.dict_w.setdefault('__dict__',
  641. w_self.space.wrap(std_dict_descr))
  642. w_self.hasdict = True
  643. def create_weakref_slot(w_self):
  644. if not w_self.weakrefable:
  645. w_self.dict_w.setdefault('__weakref__',
  646. w_self.space.wrap(weakref_descr))
  647. w_self.weakrefable = True
  648. def valid_slot_name(slot_name):
  649. if len(slot_name) == 0 or slot_name[0].isdigit():
  650. return False
  651. for c in slot_name:
  652. if not c.isalnum() and c != '_':
  653. return False
  654. return True
  655. def setup_user_defined_type(w_self):
  656. if len(w_self.bases_w) == 0:
  657. w_self.bases_w = [w_self.space.w_object]
  658. w_bestbase = check_and_find_best_base(w_self.space, w_self.bases_w)
  659. w_self.instancetypedef = w_bestbase.instancetypedef
  660. w_self.flag_heaptype = True
  661. for w_base in w_self.bases_w:
  662. if not isinstance(w_base, W_TypeObject):
  663. continue
  664. w_self.flag_cpytype |= w_base.flag_cpytype
  665. w_self.flag_abstract |= w_base.flag_abstract
  666. hasoldstylebase = copy_flags_from_bases(w_self, w_bestbase)
  667. create_all_slots(w_self, hasoldstylebase)
  668. ensure_common_attributes(w_self)
  669. def setup_builtin_type(w_self):
  670. w_self.hasdict = w_self.instancetypedef.hasdict
  671. w_self.weakrefable = w_self.instancetypedef.weakrefable
  672. w_self.w_doc = w_self.space.wrap(w_self.instancetypedef.doc)
  673. ensure_common_attributes(w_self)
  674. def ensure_common_attributes(w_self):
  675. ensure_static_new(w_self)
  676. w_self.dict_w.setdefault('__doc__', w_self.w_doc)
  677. if w_self.is_heaptype():
  678. ensure_module_attr(w_self)
  679. w_self.mro_w = [] # temporarily
  680. compute_mro(w_self)
  681. def ensure_static_new(w_self):
  682. # special-case __new__, as in CPython:
  683. # if it is a Function, turn it into a static method
  684. if '__new__' in w_self.dict_w:
  685. w_new = w_self.dict_w['__new__']
  686. if isinstance(w_new, Function):
  687. w_self.dict_w['__new__'] = StaticMethod(w_new)
  688. def ensure_module_attr(w_self):
  689. # initialize __module__ in the dict (user-defined types only)
  690. if '__module__' not in w_self.dict_w:
  691. space = w_self.space
  692. caller = space.getexecutioncontext().gettopframe_nohidden()
  693. if caller is not None:
  694. w_globals = caller.w_globals
  695. w_name = space.finditem(w_globals, space.wrap('__name__'))
  696. if w_name is not None:
  697. w_self.dict_w['__module__'] = w_name
  698. def compute_mro(w_self):
  699. if w_self.is_heaptype():
  700. space = w_self.space
  701. w_metaclass = space.type(w_self)
  702. w_where, w_mro_func = space.lookup_in_type_where(w_metaclass, 'mro')
  703. if w_mro_func is not None and not space.is_w(w_where, space.w_type):
  704. w_mro_meth = space.get(w_mro_func, w_self)
  705. w_mro = space.call_function(w_mro_meth)
  706. mro_w = space.fixedview(w_mro)
  707. w_self.mro_w = validate_custom_mro(space, mro_w)
  708. return # done
  709. w_self.mro_w = w_self.compute_default_mro()[:]
  710. def validate_custom_mro(space, mro_w):
  711. # do some checking here. Note that unlike CPython, strange MROs
  712. # cannot really segfault PyPy. At a minimum, we check that all
  713. # the elements in the mro seem to be (old- or new-style) classes.
  714. for w_class in mro_w:
  715. if not space.abstract_isclass_w(w_class):
  716. raise OperationError(space.w_TypeError,
  717. space.wrap("mro() returned a non-class"))
  718. return mro_w
  719. def is_mro_purely_of_types(mro_w):
  720. for w_class in mro_w:
  721. if not isinstance(w_class, W_TypeObject):
  722. return False
  723. return True
  724. # ____________________________________________________________
  725. def call__Type(space, w_type, __args__):
  726. promote(w_type)
  727. # invoke the __new__ of the type
  728. if not we_are_jitted():
  729. # note that the annotator will figure out that w_type.w_new_function
  730. # can only be None if the newshortcut config option is not set
  731. w_newfunc = w_type.w_new_function
  732. else:
  733. # for the JIT it is better to take the slow path because normal lookup
  734. # is nicely optimized, but the w_type.w_new_function attribute is not
  735. # known to the JIT
  736. w_newfunc = None
  737. if w_newfunc is None:
  738. w_newtype, w_newdescr = w_type.lookup_where('__new__')
  739. w_newfunc = space.get(w_newdescr, w_type)
  740. if (space.config.objspace.std.newshortcut and
  741. not we_are_jitted() and
  742. isinstance(w_newtype, W_TypeObject)):
  743. w_type.w_new_function = w_newfunc
  744. w_newobject = space.call_obj_args(w_newfunc, w_type, __args__)
  745. call_init = space.isinstance_w(w_newobject, w_type)
  746. # maybe invoke the __init__ of the type
  747. if (call_init and not (space.is_w(w_type, space.w_type) and
  748. not __args__.keywords and len(__args__.arguments_w) == 1)):
  749. w_descr = space.lookup(w_newobject, '__init__')
  750. w_result = space.get_and_call_args(w_descr, w_newobject, __args__)
  751. if not space.is_w(w_result, space.w_None):
  752. raise OperationError(space.w_TypeError,
  753. space.wrap("__init__() should return None"))
  754. return w_newobject
  755. def _issubtype(w_sub, w_type):
  756. return w_type in w_sub.mro_w
  757. @elidable_promote()
  758. def _pure_issubtype(w_sub, w_type, version_tag1, version_tag2):
  759. return _issubtype(w_sub, w_type)
  760. def issubtype__Type_Type(space, w_type, w_sub):
  761. return space.newbool(w_sub.issubtype(w_type))
  762. def isinstance__Type_ANY(space, w_type, w_inst):
  763. return space.newbool(space.type(w_inst).issubtype(w_type))
  764. def repr__Type(space, w_obj):
  765. w_mod = w_obj.get_module()
  766. if not space.isinstance_w(w_mod, space.w_str):
  767. mod = None
  768. else:
  769. mod = space.str_w(w_mod)
  770. if not w_obj.is_heaptype():
  771. kind = 'type'
  772. else:
  773. kind = 'class'
  774. if mod is not None and mod !='__builtin__':
  775. return space.wrap("<%s '%s.%s'>" % (kind, mod, w_obj.name))
  776. else:
  777. return space.wrap("<%s '%s'>" % (kind, w_obj.name))
  778. def getattr__Type_ANY(space, w_type, w_name):
  779. name = space.str_w(w_name)
  780. w_descr = space.lookup(w_type, name)
  781. if w_descr is not None:
  782. if space.is_data_descr(w_descr):
  783. w_get = space.lookup(w_descr, "__get__")
  784. if w_get is not None:
  785. return space.get_and_call_function(w_get, w_descr, w_type,
  786. space.type(w_type))
  787. w_value = w_type.lookup(name)
  788. if w_value is not None:
  789. # __get__(None, type): turns e.g. functions into unbound methods
  790. return space.get(w_value, space.w_None, w_type)
  791. if w_descr is not None:
  792. return space.get(w_descr,w_type)
  793. raise operationerrfmt(space.w_AttributeError,
  794. "type object '%s' has no attribute '%s'",
  795. w_type.name, name)
  796. def eq__Type_Type(space, w_self, w_other):
  797. return space.is_(w_self, w_other)
  798. # ____________________________________________________________
  799. abstract_mro = gateway.applevel("""
  800. def abstract_mro(klass):
  801. # abstract/classic mro
  802. mro = []
  803. stack = [klass]
  804. while stack:
  805. klass = stack.pop()
  806. if klass not in mro:
  807. mro.append(klass)
  808. if not isinstance(klass.__bases__, tuple):
  809. raise TypeError, '__bases__ must be a tuple'
  810. stack += klass.__bases__[::-1]
  811. return mro
  812. """, filename=__file__).interphook("abstract_mro")
  813. def get_mro(space, klass):
  814. if isinstance(klass, W_TypeObject):
  815. return list(klass.mro_w)
  816. else:
  817. return space.unpackiterable(abstract_mro(space, klass))
  818. def compute_C3_mro(space, cls):
  819. order = []
  820. orderlists = [get_mro(space, base) for base in cls.bases_w]
  821. orderlists.append([cls] + cls.bases_w)
  822. while orderlists:
  823. for candidatelist in orderlists:
  824. candidate = candidatelist[0]
  825. if mro_blockinglist(candidate, orderlists) is None:
  826. break # good candidate
  827. else:
  828. return mro_error(space, orderlists) # no candidate found
  829. assert candidate not in order
  830. order.append(candidate)
  831. for i in range(len(orderlists)-1, -1, -1):
  832. if orderlists[i][0] is candidate:
  833. del orderlists[i][0]
  834. if len(orderlists[i]) == 0:
  835. del orderlists[i]
  836. return order
  837. def mro_blockinglist(candidate, orderlists):
  838. for lst in orderlists:
  839. if candidate in lst[1:]:
  840. return lst
  841. return None # good candidate
  842. def mro_error(space, orderlists):
  843. cycle = []
  844. candidate = orderlists[-1][0]
  845. if candidate in orderlists[-1][1:]:
  846. # explicit error message for this specific case
  847. raise operationerrfmt(space.w_TypeError,
  848. "duplicate base class '%s'",
  849. candidate.getname(space))
  850. while candidate not in cycle:
  851. cycle.append(candidate)
  852. nextblockinglist = mro_blockinglist(candidate, orderlists)
  853. candidate = nextblockinglist[0]
  854. del cycle[:cycle.index(candidate)]
  855. cycle.append(candidate)
  856. cycle.reverse()
  857. names = [cls.getname(space) for cls in cycle]
  858. raise OperationError(space.w_TypeError,
  859. space.wrap("cycle among base classes: " + ' < '.join(names)))
  860. # ____________________________________________________________
  861. register_all(vars())