diff options
Diffstat (limited to 'modules/language/python/module')
-rw-r--r-- | modules/language/python/module/collections.scm | 113 | ||||
-rw-r--r-- | modules/language/python/module/collections/abc.scm | 19 | ||||
-rw-r--r-- | modules/language/python/module/enum.py | 47 | ||||
-rw-r--r-- | modules/language/python/module/python.scm | 8 |
4 files changed, 104 insertions, 83 deletions
diff --git a/modules/language/python/module/collections.scm b/modules/language/python/module/collections.scm index 1a158c9..04f7ab6 100644 --- a/modules/language/python/module/collections.scm +++ b/modules/language/python/module/collections.scm @@ -94,20 +94,19 @@ (define-python-class OrderedDict (dict) (define __init__ (lam (self (* args) (** kwds)) + ((ref dict '__init__) self) + (if (> (len args) 1) (raise TypeError (format #f "expected at most 1 arguments, got ~a" (len args)))) - (try - (lambda () (ref self '__root)) - (#:except AttributeError => - (lambda x - (let* ((l (link))) - (set self '__root l) - (set-next! l l) - (set-prev! l l))))) + (if (not (ref self '__root)) + (let* ((l (link))) + (set self '__root l) + (set-next! l l) + (set-prev! l l))) (set self '__map (dict)) (py-apply py-update self (* args) (** kwds)))) @@ -127,7 +126,7 @@ (set-key! link key) (set-next! last link) (set-prev! root link) - (dict_setitem self key value))))) + (dict-set! self key value))))) (define __delitem__ (lam (self key (= dict_delitem dict-del!)) @@ -145,7 +144,7 @@ (lambda (yield) (let ((root (ref self '__root))) (let lp ((curr (get-next root))) - (if ((not (eq? curr root))) + (if (not (eq? curr root)) (let ((key (get-key curr))) (yield key (pylist-ref self key)) (lp (get-next curr))))))))))) @@ -209,11 +208,16 @@ (define __update update) (define keys - (lambda (self) _OrderedDictKeysView(self))) + (lambda (self) + (_OrderedDictKeysView self))) + (define items - (lambda (self) _OrderedDictItemsView(self))) + (lambda (self) + (_OrderedDictItemsView self))) + (define values - (lambda (self) _OrderedDictValuesView(self))) + (lambda (self) + (_OrderedDictValuesView self))) (define __ne__ (ref MutableMapping '__ne__)) @@ -645,51 +649,54 @@ (make-p-class (string->symbol typename) '(()) (lambda (dict) - (pylist-set! dict '__init__ - (eval (v `(lam - (self - ,@(map (lambda (key) `(= ,key #f)) - field_names)) + (pylist-set! dict '__init__ + (object-method + (eval (v `(lam + (self + ,@(map (lambda (key) `(= ,key #f)) + field_names)) - ,@(map (lambda (key) `(set self ',key ,key)) - field_names))) - mod)) + ,@(map (lambda (key) `(set self ',key ,key)) + field_names))) + mod))) - (pylist-set! dict '__getitem__ - (lam (self i) - (if (number? i) - (ref self (list-ref field_names i)) - (ref self (scm-sym i))))) + (pylist-set! dict '__getitem__ + (object-method + (lambda (self i) + (if (number? i) + (ref self (list-ref field_names i)) + (ref self (scm-sym i)))))) - (pylist-set! dict '__setitem__ - (lam (self i val) - (if (number? i) - (set self (list-ref field_names i) val) - (set self (scm-sym i) val)))) - - (pylist-set! dict '__repr__ - (lam (self) - (let ((l (map (lambda (x) - (format #f "~a=~a" - x - (ref self x))) - field_names))) - - (format #f "~a(~a~{,~a~})" - typename - (car l) - (cdr l))))) + (pylist-set! dict '__setitem__ + (object-method + (lambda (self i val) + (if (number? i) + (set self (list-ref field_names i) val) + (set self (scm-sym i) val))))) + + (pylist-set! dict '__repr__ + (object-method + (lambda (self . l) + (let ((l (map (lambda (x) + (format #f "~a=~a" + x + (ref self x))) + field_names))) + (format #f "~a(~a~{,~a~})" + typename + (car l) + (cdr l)))))) - (if (eq? module None) - (set! module (module-name (current-module))) - (if (string? (scm-str module)) - (set! module - (+ '(language python module) - (map scm-sym - (string-split module #\.)))))) - - (if verbose (pretty-print verbose)))))) + (if (eq? module None) + (set! module (module-name (current-module))) + (if (string? (scm-str module)) + (set! module + (+ '(language python module) + (map scm-sym + (string-split module #\.)))))) + + (if verbose (pretty-print verbose)))))) (define UserDict dict) (define UserString pystring) diff --git a/modules/language/python/module/collections/abc.scm b/modules/language/python/module/collections/abc.scm index 4bd242d..4d442d3 100644 --- a/modules/language/python/module/collections/abc.scm +++ b/modules/language/python/module/collections/abc.scm @@ -516,7 +516,10 @@ (define __iter__ (lambda (self) - ((ref (ref self '_mapping) 'items))))) + ((make-generator () + (lambda (yield) + (for ((k v : (ref self '_mapping))) () + (yield (list k v))))))))) (define-python-class KeysView (MappingView Set) ;; Mixins @@ -524,10 +527,13 @@ (lambda (self k) (let ((m (ref self '_mapping))) (in k m)))) - + (define __iter__ (lambda (self) - ((ref (ref self '_mapping) 'keys))))) + ((make-generator () + (lambda (yield) + (for ((k v : (ref self '_mapping))) () + (yield k)))))))) (define-python-class ValuesView (MappingView) ;; Mixins @@ -541,6 +547,7 @@ (define __iter__ (lambda (self) - ((ref (ref self '_mapping) 'values))))) - - + ((make-generator () + (lambda (yield) + (for ((k v : (ref self '_mapping))) () + (yield v)))))))) diff --git a/modules/language/python/module/enum.py b/modules/language/python/module/enum.py index 0f623f0..723fab7 100644 --- a/modules/language/python/module/enum.py +++ b/modules/language/python/module/enum.py @@ -50,14 +50,12 @@ def _make_class_unpicklable(cls): _auto_null = object() - class auto: """ Instances are replaced with an appropriate value in Enum class suites. """ value = _auto_null - class _EnumDict(dict): """Track enum member order and ensure member names are not reused. @@ -90,10 +88,10 @@ class _EnumDict(dict): elif _is_dunder(key): if key == '__order__': key = '_order_' - elif key in self._member_names: + elif (key in self._member_names): # descriptor overwriting an enum? raise TypeError('Attempted to reuse key: %r' % key) - elif not _is_descriptor(value): + elif (not _is_descriptor(value)): if key in self: # enum overwriting a descriptor? raise TypeError('%r already defined as: %r' % (key, self[key])) @@ -105,13 +103,12 @@ class _EnumDict(dict): self._last_values.append(value) super().__setitem__(key, value) - # Dummy value for Enum as EnumMeta explicitly checks for it, but of course # until EnumMeta finishes running the first time the Enum class doesn't exist. # This is also why there are checks in EnumMeta like `if Enum is not None` Enum = None - +pk('EnumMeta') class EnumMeta(type): """Metaclass for Enum""" @classmethod @@ -132,13 +129,15 @@ class EnumMeta(type): # cannot be mixed with other types (int, float, etc.) if it has an # inherited __new__ unless a new __new__ is defined (or the resulting # class will fail). + member_type, first_enum = metacls._get_mixins_(bases) - __new__, save_new, use_args = metacls._find_new_(classdict, member_type, - first_enum) + new, save_new, use_args = metacls._find_new_(classdict, member_type, + first_enum) # save enum items into separate mapping so they don't get baked into # the new class enum_members = {k: classdict[k] for k in classdict._member_names} + for name in classdict._member_names: del classdict[name] @@ -150,21 +149,19 @@ class EnumMeta(type): if invalid_names: raise ValueError('Invalid enum member name: {0}'.format( ','.join(invalid_names))) - + # create a default docstring if one has not been provided if '__doc__' not in classdict: classdict['__doc__'] = 'An enumeration.' # create our new Enum type enum_class = super().__new__(metacls, cls, bases, classdict) - pk(enum_class) enum_class._member_names_ = [] # names in definition order enum_class._member_map_ = OrderedDict() # name->value map enum_class._member_type_ = member_type # save attributes from super classes so we know if we can take # the shortcut of storing members in the class dict - base_attributes = {a for b in enum_class.mro() for a in b.__dict__} # Reverse value->name map for hashable values. @@ -197,14 +194,16 @@ class EnumMeta(type): args = (value, ) else: args = value + if member_type is tuple: # special case for tuple enums args = (args, ) # wrap it one more time + if not use_args: - enum_member = __new__(enum_class) + enum_member = new(enum_class) if not hasattr(enum_member, '_value_'): enum_member._value_ = value else: - enum_member = __new__(enum_class, *args) + enum_member = new(enum_class, *args) if not hasattr(enum_member, '_value_'): if member_type is object: enum_member._value_ = value @@ -214,6 +213,7 @@ class EnumMeta(type): enum_member._name_ = member_name enum_member.__objclass__ = enum_class enum_member.__init__(*args) + # If another member with the same value was already defined, the # new member becomes an alias to the existing one. for name, canonical_member in enum_class._member_map_.items(): @@ -223,11 +223,13 @@ class EnumMeta(type): else: # Aliases don't appear in member names (only in __members__). enum_class._member_names_.append(member_name) + # performance boost for any member that would not shadow # a DynamicClassAttribute if member_name not in base_attributes: setattr(enum_class, member_name, enum_member) # now add to _member_map_ + enum_class._member_map_[member_name] = enum_member try: # This may fail if value is not hashable. We can't add the value @@ -370,8 +372,6 @@ class EnumMeta(type): if name in member_map: raise AttributeError('Cannot reassign members.') - pk('set',name) - super().__setattr__(name, value) @@ -522,6 +522,7 @@ class EnumMeta(type): return __new__, save_new, use_args +pk('enum') class Enum(metaclass=EnumMeta): """Generic enumeration. @@ -529,7 +530,6 @@ class Enum(metaclass=EnumMeta): Derive from this class to define new enumerations. """ - pk(1) def __new__(cls, value): # all enum instances are actually created during class construction @@ -551,8 +551,6 @@ class Enum(metaclass=EnumMeta): # still not found -- try _missing_ hook return cls._missing_(value) - pk(2) - def _generate_next_value_(name, start, count, last_values): for last_value in reversed(last_values): try: @@ -562,8 +560,6 @@ class Enum(metaclass=EnumMeta): else: return start - pk(3) - @classmethod def _missing_(cls, value): raise ValueError("%r is not a valid %s" % (value, cls.__name__)) @@ -583,7 +579,7 @@ class Enum(metaclass=EnumMeta): if m[0] != '_' and m not in self._member_map_ ] return (['__class__', '__doc__', '__module__'] + added_behavior) - pk(4) + def __format__(self, format_spec): # mixed-in Enums should use the mixed-in type's __format__, otherwise # we can get strange results with the Enum name showing up instead of @@ -611,7 +607,7 @@ class Enum(metaclass=EnumMeta): # to have members named `name` and `value`. This works because enumeration # members are not set directly on the enum class -- __getattr__ is # used to look them up. - pk(5) + @DynamicClassAttribute def name(self): """The name of the Enum member.""" @@ -658,6 +654,7 @@ class Enum(metaclass=EnumMeta): module_globals[name] = cls return cls +pk('intenum') class IntEnum(int, Enum): """Enum where members are also (and must be) ints""" @@ -666,6 +663,7 @@ class IntEnum(int, Enum): def _reduce_ex_by_name(self, proto): return self.name +pk('flag') class Flag(Enum): """Support for flags""" @@ -773,7 +771,8 @@ class Flag(Enum): ] inverted = reduce(_or_, inverted_members, self.__class__(0)) return self.__class__(inverted) - + +pk('intflag') class IntFlag(int, Flag): """Support for integer-based Flags""" @@ -837,6 +836,8 @@ class IntFlag(int, Flag): def __invert__(self): result = self.__class__(~self._value_) return result + +pk('rest') def _high_bit(value): """returns index of highest bit, or -1 if value is zero or negative""" diff --git a/modules/language/python/module/python.scm b/modules/language/python/module/python.scm index 1a90757..7b01c93 100644 --- a/modules/language/python/module/python.scm +++ b/modules/language/python/module/python.scm @@ -324,7 +324,13 @@ (define-python-class StaticMethod ()) (define-python-class Funcobj ()) +(define-method (py-mod (s <string>) l) + (let* ((s (py-replace s "%s" "~a")) + (s (py-replace s "%r" "~a")) + (l (for ((x : l)) ((r '())) + (cons x r) + #:final (reverse r)))) + (apply (@ (guile) format) #f s l))) - |