further improvements in the meta layer

parent a9aa577f
......@@ -10,6 +10,7 @@ SOURCES = \
language/python/guilemod.scm \
oop/dict.scm \
oop/pf-objects.scm \
language/python/module/_collections_abc.scm \
language/python/persist.scm \
language/python/exceptions.scm \
language/python/hash.scm \
......@@ -151,7 +151,10 @@
(define-syntax-rule (with-exit code ...)
(with-fluids ((exit-fluid #t))
(call-with-prompt exit-prompt
(lambda () code ...)
(lambda ()
(catch #t
(lambda () code ...)
(lambda x (pk x) (values))))
(lambda (k val)
(unless (zero? val)
(format #t "exit with error ~a~%" val))))))
......@@ -315,6 +318,17 @@ empty list."
(fluid-ref %dont-warn-list))))
(lambda x (values))))
(define (dont-warn-l v)
(define (f a) (dont-warn (exp '() a)))
(lambda (x)
(match x
((a . #f)
(f a))
((a . b)
(f b))))
(define (dont-warn* v)
(catch #t
(lambda ()
......@@ -1187,13 +1201,15 @@ empty list."
'(m #:select ((bb . cc) ...)))))
(use #t () (m #:select ((b . c) ...)))))
(with-syntax ((((b . c) ...) (f l)))
#'(use #t () (m #:select ((b . c) ...)))))
#'((@ (guile) begin)
(use #t () (m #:select ((b . c) ...))))))
(if (pair? ll)
(with-syntax ((((bb . cc) ...) (f ll)))
#'(catch #t
(lambda ()
(set! cc (@@ m bb))
(lambda x
(raise ImportError '(m #:select ((bb . cc) ...))))))
......@@ -1517,6 +1533,7 @@ empty list."
;; Make sure to load the module in
(let* ((xl (map (lambda (nm) (exp vs nm)) nm))
(ll `(language python module ,@xl)))
(dont-warn-l l)
`(,(C '@@values) ,l ,ll ,xl)))
((_ (#:from (("." . nn) . nm) l))
......@@ -1525,6 +1542,7 @@ empty list."
(u (reverse (list-cdr-ref (reverse (u-it u)) (length nn))))
(xl (append u (map (lambda (nm) (exp vs nm)) (cdr nm))))
(ll `(language python module ,@xl)))
(dont-warn-l l)
`(,(C '@@values) ,l ,ll ,xl)))
((_ (#:from ("." . nn) l))
......@@ -1534,7 +1552,7 @@ empty list."
(u (reverse (list-cdr-ref (reverse (u-it u)) (length nn))))
(xl (append u (map (lambda (nm) (exp vs nm)) (cdr nm))))
(ll `(language python module ,@xl)))
(dont-warn-l l)
`(,(C 'use) #t ()
......@@ -2149,9 +2167,10 @@ empty list."
((_ x f n m)
`(,(G 'if)
(,(G 'not) (,(G 'and) ,@(map (lambda (x) `(,(C 'boolit) ,(exp vs x)))
(,(C 'raise) ,(C 'AssertionError) (,(G 'quote) ,f) ,n ,m))))
(,(G 'not) (,(C 'boolit) ,(exp vs (car x))))
(,(C 'raise) ,(C 'AssertionError)
,@(if (> (length x) 1) (list (exp vs (cadr x))) '())
(,(G 'quote) ,f) ,m ,n))))
......@@ -2468,9 +2487,10 @@ empty list."
,@(map (lambda (s)
(if (member s (fluid-ref ignore))
`(,(C 'var) ,s))) globs)
`(,(C 'var) ,s))) globs)
(,(C 'with-exit) ,@e))))))))
(define-syntax-parameter break
(lambda (x) #'(values)))
......@@ -21,9 +21,11 @@
pylist-pop! pylist-count pylist-extend! len in
pylist-insert! pylist-remove! pylist-sort!
pylist-index pylist-null pylist-delete!
pylist pylist-listing
pylist pylist-listing Ellipsis Slice
py-all py-any py-reversed))
(define-python-class Ellipsis ())
(define-python-class Slice ())
(define-syntax-rule (pset o n val . rest)
((list? n)
(define-module (language python module _collections_abc)
#:export (check_methods_))
(define (check_methods_ . x) #t)
(define-module (language python module _python)
#:use-module (oop goops)
#:use-module ((oop dict) #:select (slask-it))
#:use-module (ice-9 match)
#:use-module (ice-9 readline)
#:use-module ((oop pf-objects) #:select
(<p> <property> class-method static-method ref (set . pf-set)
py-super-mac type object pylist-ref define-python-class
object-method py-dict rawdel))
object-method py-dict rawdel rawref kind))
#:use-module (rnrs bytevectors)
#:use-module (language python exceptions )
#:use-module ((language python module string ) #:select ())
......@@ -43,7 +44,7 @@
tuple bytes bytearray locals globals
exec type object __import__ frozenset
Warning BytesWarning DeprecationWarning
py-list raise
py-list raise Ellipsis Slice
#:export (print repr complex float int str
......@@ -115,12 +116,14 @@
(if (f x)
(yield x)))))))
(define miss ((@ (guile) list) 'miss))
(define miss (slask-it ((@ (guile) list) 'miss)))
(define* (getattr a b #:optional (k miss))
(let ((r (ref a (if (string? b) (string->symbol b) b) k)))
(let ((r (ref a (if (string? b) (string->symbol b) b) miss)))
(if (eq? r miss)
(raise AttributeError "object/class ~a is missing attribute ~a" a b)
(if (eq? k miss)
(raise AttributeError "object/class ~a is missing attribute ~a" a b)
(define (setattr a k v)
......@@ -132,8 +135,9 @@
(define-method (issubclass x y) #f)
(define-method (issubclass (sub <p>) (cls <p>))
(aif it (ref cls '__subclasscheck__)
(it sub)
(pk sub cls (ref sub '__class__))
(aif it (ref (ref sub '__class__) '__subclasscheck__)
(it cls sub)
(if (eq? sub cls)
(if (memq cls (ref sub '__mro__))
......@@ -192,9 +196,9 @@
(define-method (isinstance (i <integer>) (y <p>))
((ref y '__instancecheck__) =>
((rawref y '__instancecheck__) =>
(lambda (it)
(it i)))
(it y i)))
......@@ -208,9 +212,9 @@
(define-method (isinstance (i <real>) (y <p>))
((ref y '__instancecheck__) =>
((rawref y '__instancecheck__) =>
(lambda (it)
(it i)))
(it y i)))
......@@ -224,9 +228,9 @@
(define-method (isinstance (i <pair>) (y <p>))
((ref y '__instancecheck__) =>
((rawref y '__instancecheck__) =>
(lambda (it)
(it i)))
(it y i)))
......@@ -240,9 +244,9 @@
(define-method (isinstance (i <string>) (y <p>))
((ref y '__instancecheck__) =>
((rawref y '__instancecheck__) =>
(lambda (it)
(it i)))
(it y i)))
......@@ -256,9 +260,9 @@
(define-method (isinstance (i <bytevector>) (y <p>))
((ref y '__instancecheck__) =>
((rawref y '__instancecheck__) =>
(lambda (it)
(it i)))
(it y i)))
......@@ -279,9 +283,9 @@
(define-method (isinstance (o <p>) (cl <p>))
((ref cl '__instancecheck__) =>
((rawref cl '__instancecheck__) =>
(lambda (it)
(it o)))
(it cl o)))
((pair? cl)
(isinstance o (car cl))
......@@ -13,7 +13,7 @@
#:export (MappingProxyType Functiontype LambdaType
MethodType BuiltinMethodType CodeType
AsyncGeneratorType CoroutineType GeneratorType
TracebackType FrameType WrapperDescriptor
TracebackType FrameType WrapperDescriptorType
MethodWrapperType MethodDescriptorType))
......@@ -34,7 +34,7 @@ Define names for built-in types that aren't directly accessible as a builtin.
(define DynamicClassAttribute #:DynamicClassAttribute)
(define ClassType type)
(define InctanceType object)
(define WrapperDescriptor #:Method)
(define WrapperDescriptorType #:Method)
(define MethodWrapperType #:Method)
(define MethodDescriptorType #:Method)
(define-python-class DynamicClassAttribute ()
......@@ -117,6 +117,10 @@
(or ((ref cls '__subclasscheck__) subclass)
((ref cls '__subclasscheck__) subtype))))))))
(define __subclasshook__
(lambda (cls subclass)
(define __subclasscheck__
(lambda (cls subclass)
(let/ec ret
......@@ -6,12 +6,15 @@ import functools
import re as stdlib_re # Avoid confusion with the re we export.
import sys
import types
import collections.abc as collections_abc
except ImportError:
import collections as collections_abc # Fallback for PY3.2.
if sys.version_info[:2] >= (3, 6):
import _collections_abc # Needed for private function _check_methods # noqa
from types import WrapperDescriptorType, MethodWrapperType, MethodDescriptorType
except ImportError:
......@@ -19,7 +22,6 @@ except ImportError:
MethodWrapperType = type(object().__str__)
MethodDescriptorType = type(str.join)
# Please keep __all__ alphabetized within each category.
__all__ = [
# Super-special typing primitives.
......@@ -101,7 +103,6 @@ __all__ = [
# namespace, but excluded from __all__ because they might stomp on
# legitimate imports of those modules.
def _qualname(x):
if sys.version_info[:2] >= (3, 3):
return x.__qualname__
......@@ -347,7 +348,6 @@ def _eval_type(t, globalns, localns):
return t._eval_type(globalns, localns)
return t
def _type_check(arg, msg):
"""Check that the argument is a type, and return it (internal helper).
As a special case, accept None and return type(None) instead.
......@@ -787,10 +787,8 @@ class _Union(_FinalTypingBase, _root=True):
def __subclasscheck__(self, cls):
raise TypeError("Unions cannot be used with issubclass().")
Union = _Union(_root=True)
class _Optional(_FinalTypingBase, _root=True):
"""Optional type.
Optional[X] is equivalent to Union[X, None].
......@@ -814,7 +812,9 @@ def _next_in_mro(cls):
next_in_mro = object
# Look for the last occurrence of Generic or Generic[...].
for i, c in enumerate(cls.__mro__[:-1]):
if isinstance(c, GenericMeta) and c._gorg is Generic:
next_in_mro = cls.__mro__[i + 1]
return next_in_mro
......@@ -849,7 +849,6 @@ def _make_subclasshook(cls):
return NotImplemented
return __extrahook__
def _no_slots_copy(dct):
"""Internal helper: copy class __dict__ and clean slots class variables.
(They will be re-created if necessary by normal class machinery.)
......@@ -920,12 +919,12 @@ class GenericMeta(TypingMeta, abc.ABCMeta):
(", ".join(str(t) for t in tvars if t not in gvarset),
", ".join(str(g) for g in gvars)))
tvars = gvars
initial_bases = bases
if extra is not None and type(extra) is abc.ABCMeta and extra not in bases:
bases = (extra,) + bases
bases = tuple(b._gorg if isinstance(b, GenericMeta) else b for b in bases)
# remove bare Generic from bases if there are other generic bases
if any(isinstance(b, GenericMeta) and b is not Generic for b in bases):
bases = tuple(b for b in bases if b is not Generic)
......@@ -934,6 +933,7 @@ class GenericMeta(TypingMeta, abc.ABCMeta):
self = super().__new__(cls, name, bases, namespace, _root=True)
super(GenericMeta, self).__setattr__('_gorg',
self if not origin else origin._gorg)
self.__parameters__ = tvars
# Be prepared that GenericMeta will be subclassed by TupleMeta
# and CallableMeta, those two allow ..., (), or [] in __args___.
......@@ -941,11 +941,13 @@ class GenericMeta(TypingMeta, abc.ABCMeta):
() if a is _TypingEmpty else
a for a in args) if args else None
# Speed hack (https://github.com/python/typing/issues/196).
self.__next_in_mro__ = _next_in_mro(self)
# Preserve base classes on subclassing (__bases__ are type erased now).
if orig_bases is None:
self.__orig_bases__ = initial_bases
# This allows unparameterized generic collections to be used
# with issubclass() and isinstance() in the same way as their
# collections.abc counterparts (e.g., isinstance([], Iterable)).
......@@ -955,17 +957,20 @@ class GenericMeta(TypingMeta, abc.ABCMeta):
getattr(self.__subclasshook__, '__name__', '') == '__extrahook__'
self.__subclasshook__ = _make_subclasshook(self)
if isinstance(extra, abc.ABCMeta):
self._abc_registry = extra._abc_registry
self._abc_cache = extra._abc_cache
elif origin is not None:
self._abc_registry = origin._abc_registry
self._abc_cache = origin._abc_cache
if origin and hasattr(origin, '__qualname__'): # Fix for Python 3.2.
self.__qualname__ = origin.__qualname__
self.__tree_hash__ = (hash(self._subs_tree()) if origin else
super(GenericMeta, self).__hash__())
return self
# _abc_negative_cache and _abc_negative_cache_version
......@@ -1099,6 +1104,7 @@ class GenericMeta(TypingMeta, abc.ABCMeta):
def __subclasscheck__(self, cls):
if self.__origin__ is not None:
if sys._getframe(1).f_globals['__name__'] not in ['abc', 'functools']:
raise TypeError("Parameterized generics cannot be used with class "
......@@ -1115,6 +1121,7 @@ class GenericMeta(TypingMeta, abc.ABCMeta):
# latter, we must extend __instancecheck__ too. For simplicity
# we just skip the cache check -- instance checks for generic
# classes are supposed to be rare anyways.
return issubclass(instance.__class__, self)
def __setattr__(self, attr, value):
......@@ -1156,6 +1163,7 @@ def _generic_new(base_cls, cls, *args, **kwds):
obj.__init__(*args, **kwds)
return obj
class Generic(metaclass=GenericMeta):
"""Abstract base class for generic types.
......@@ -1182,18 +1190,18 @@ class Generic(metaclass=GenericMeta):
"it can be used only as a base class")
return _generic_new(cls.__next_in_mro__, cls, *args, **kwds)
class _TypingEmpty:
"""Internal placeholder for () or []. Used by TupleMeta and CallableMeta
to allow empty list/tuple in specific places, without allowing them
to sneak in where prohibited.
class _TypingEllipsis:
"""Internal placeholder for ... (ellipsis)."""
class TupleMeta(GenericMeta):
"""Metaclass for Tuple (internal)."""
......@@ -1227,7 +1235,7 @@ class TupleMeta(GenericMeta):
raise TypeError("Parameterized Tuple cannot be used "
"with issubclass().")
class Tuple(tuple, extra=tuple, metaclass=TupleMeta):
"""Tuple type; Tuple[X, Y] is the cross-product type of X and Y.
Example: Tuple[T1, T2] is a tuple of two elements corresponding
......@@ -1244,7 +1252,7 @@ class Tuple(tuple, extra=tuple, metaclass=TupleMeta):
"use tuple() instead")
return _generic_new(tuple, cls, *args, **kwds)
class CallableMeta(GenericMeta):
"""Metaclass for Callable (internal)."""
......@@ -1555,7 +1563,7 @@ def overload(func):
return _overload_dummy
class _ProtocolMeta(GenericMeta):
"""Internal metaclass for _Protocol.
This exists so _Protocol classes can be generic without deriving
......@@ -2089,7 +2097,7 @@ class NamedTupleMeta(type):
setattr(nm_tpl, key, ns[key])
return nm_tpl
class NamedTuple(metaclass=NamedTupleMeta):
"""Typed version of namedtuple.
Usage in Python versions >= 3.6::
......@@ -2662,7 +2670,7 @@ def _make_nmtuple(name, types):
return nm_tpl
_PY36 = sys.version_info[:2] >= (3, 6)
# attributes prohibited to set in NamedTuple class syntax
......@@ -2936,7 +2944,7 @@ class TextIO(IO[str]):
def __enter__(self) -> 'TextIO':
class io:
"""Wrapper namespace for IO generic classes."""
......@@ -40,7 +40,7 @@
(define-method (rawref (f <generic>) tag . l)
(apply ref-f f tag l))
(define (ref-f f tag . l)
(define (ref-f f tag . l)
(set! tag (if (symbol? tag) tag (string->symbol tag)))
......@@ -50,7 +50,11 @@
((equal? tag '__name__)
(let ((r (procedure-property- f '__name__)))
(if (not r)
(symbol->string (procedure-name f))
(aif it (procedure-name f)
(symbol->string (procedure-name f))
(if (pair? l)
(car l)
((equal? tag '__code__)
......@@ -14,7 +14,7 @@
#:re-export (object-method class-method static-method)
#:export (set ref make-p <p> <py> <pf> <pyf> <property>
call with copy fset fcall put put! py-get
pcall pcall! get fset-x pyclass?
pcall pcall! get fset-x pyclass? kind
def-p-class mk-p-class make-p-class mk-p-class2
mk-py-class mk-py-class2
define-python-class define-python-class-noname
......@@ -1270,7 +1270,7 @@ explicitly tell it to not update etc.
(let lp ((code code))
(syntax-case code (set! @)
(syntax-case code (set! @ @@)
((set! x y)
(aif it (hash-ref m (syntax->datum #'x))
#`(set! #,it #,(sec #'y))
......@@ -1280,6 +1280,12 @@ explicitly tell it to not update etc.
(aif it (hash-ref m (syntax->datum #'x))
#`((@ (guile) set!) #,it #,(sec #'y))
(error "wrong set! in classdef" (syntax->datum #'x))))
(((@@ a set-x) x y ...)
(equal? 'set-x (syntax->datum #'set-x))
(aif it (hash-ref m (syntax->datum #'x))
#`((@@ a set-x) #,it y ...)
(error "wrong set! in classdef" (syntax->datum #'x))))
(((@@ u qset) x . y)
(equal? (syntax->datum #'qset) 'qset!)
......@@ -1547,10 +1553,12 @@ explicitly tell it to not update etc.
(let ((c (make-p <py>))
(o (make-p <py>)))
(rawset c '__class__ type)
(rawset c '__mro__ (cons* c parents))
(rawset c '__class__ (ref cl '__class__))
(rawset c '__mro__ (cons* c parents))
(rawset c '__getattribute__
(lambda (self key)
(if (equal? key "__setattr__")
(pk key obj cl class parents))
(set! key (if (string? key) (string->symbol key) key))
(kif it (ficap c key fail)
(aif dt (ref it '__get__)
......@@ -1563,7 +1571,11 @@ explicitly tell it to not update etc.
(lambda ()
(let ((ll (ref (ref obj '__class__) '__mro__ '())))
(let ((ll (if (eq? (kind class) (kind obj))
(aif it (ref obj '__mro__)
(ref (ref obj '__class__) '__mro__ '()))
(ref (ref obj '__class__) '__mro__ '()))))
(if (pair? ll)
(let lp ((l ll))
(if (pair? l)
......@@ -1812,14 +1824,24 @@ explicitly tell it to not update etc.
(define *setattr* __setattr__)
(define subclasscheck
(lambda (self c)
(pk self c)
(aif it (pk (rawref c '__mro__ #f))
(memq self it)
(set! type
(make-python-class type ()
(define __new__ new-class0)
(define __init_subclass__ (lambda x (values)))
(define __zub_classes__ (make-weak-key-hash-table))
(define __subclasses__ subclasses)
(define __subclasscheck__ (object-method subclasscheck))
(define __call__ type-call)
(define __str__ *str*)
(define __hash__ (object-method
(lambda (self) (object-address self))))
(define __getattribute__ attr)
(define __setattr__ (object-method *setattr*))
(define __format__ (lambda (self x) (*str* self)))
......@@ -1842,6 +1864,8 @@ explicitly tell it to not update etc.
(find-in-class-raw class '__class__ #f)
(find-in-class-raw class '__goops__ #f))))
(define __hash__ (object-method
(lambda (self) (object-address self))))
(define __init__ (lambda x (values)))
(define __subclasses__ subclasses)
(define __getattribute__ attr)
......@@ -1877,4 +1901,5 @@ explicitly tell it to not update etc.
(define-method (py-dict (o <p>))
(aif it (ref o '__dict__)
(dictRNs (slot-ref o 'h))))
(dictRNs (slot-ref o 'h)))
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment