[Python-checkins] r55317 - sandbox/trunk/abc/struct.py

guido.van.rossum python-checkins at python.org
Mon May 14 21:08:34 CEST 2007


Author: guido.van.rossum
Date: Mon May 14 21:08:31 2007
New Revision: 55317

Added:
   sandbox/trunk/abc/struct.py   (contents, props changed)
Log:
Checkpoint.  Non-working code for now.


Added: sandbox/trunk/abc/struct.py
==============================================================================
--- (empty file)
+++ sandbox/trunk/abc/struct.py	Mon May 14 21:08:31 2007
@@ -0,0 +1,119 @@
+#!/usr/bin/env python3.0
+
+"""Define a structure using a class.
+
+Structures have some properties that normal classes don't:
+
+(a) instance attributes are typed
+(b) only pre-defined instance attributes are allowed
+(c) instance variables have a well-defined order (i.e., declaration order)
+
+Example:
+
+    class C(Structure):
+
+        '''A class with two fields, an int and a string.'''
+
+        a = Field(int)
+        b = Field(str)
+
+    x = C()
+    x.a = 42
+    x.b = "hello"
+    print(x.a)  # 42
+    print(x.b)  # hello
+
+The following assignments are now all disallowed:
+
+    x.a = "hello"
+    x.b = 42
+    x.c = 0
+
+"""
+
+class _FieldDict(dict):
+
+    __slots__ = ["_order"]
+
+    def __init__(self, initial=()):
+        if hasattr(initial, "keys"):
+            initial = [(key, initial[key]) for key in initial.keys()]
+        self._order = list(initial)
+        dict.__init__(self, initial)
+
+    def __setitem__(self, key, value):
+        self._order.append((key, value))
+        dict.__setitem__(self, key, value)
+
+class Field:
+
+    def __init__(self, type=object):
+        self._type = type
+        self._get = None
+        self._set = None
+        self._delete = None
+        self._name = "?"
+
+    def __get__(self, obj, cls=None):
+        return self._get(obj, cls)
+
+    def __set__(self, obj, value):
+        if not isinstance(value, self._type):
+            raise TypeError("can't set %s to %.100r; %s required" %
+                            (self._name, value, self._type.__name__))
+        self._set(obj, value)
+
+    def __delete__(self, obj):
+        self._delete(obj)
+
+class _StructureClass(type):
+
+    @classmethod
+    def __prepare__(mcls, *args):
+        return _FieldDict()
+
+    def __new__(mcls, classname, bases, namespace):
+        if "__slots__" in namespace:
+            raise TypeError("You can't define __slots__ in a Structure")
+        slots = []
+        fields = {}
+        for name, value in namespace._order:
+            if isinstance(value, Field):
+                if namespace.get(name) is value and name not in fields:
+                    value._name = name
+                    slots.append(name)
+                    fields[name] = value
+                    del namespace[name]
+        namespace = dict(namespace)
+        namespace["__slots__"] = slots
+        cls = type.__new__(mcls, classname, bases, namespace)
+        for name in slots:
+            field = fields[name]
+            descr = getattr(cls, name)
+            field._get = descr.__get__
+            field._set = descr.__set__
+            field._delete = descr.__delete__
+            setattr(cls, name, field)
+        return cls
+
+class Structure(metaclass=_StructureClass):
+
+    pass
+
+# Example
+
+class C(Structure):
+
+    a = Field(int)
+    b = Field(str)
+
+    def f(self):
+        print(self.a, self.b)
+
+x = C()
+x.a = 42
+x.b = "hello"
+assert not hasattr(x, "__dict__")
+print(x.__slots__)
+x.f()
+x.a = "hello"


More information about the Python-checkins mailing list