Rev 4740: Implement StaticTuple.from_sequence() in http://bazaar.launchpad.net/~jameinel/bzr/2.1-st-from-sequence

John Arbash Meinel john at arbash-meinel.com
Tue Oct 13 19:00:27 BST 2009


At http://bazaar.launchpad.net/~jameinel/bzr/2.1-st-from-sequence

------------------------------------------------------------
revno: 4740
revision-id: john at arbash-meinel.com-20091013180016-y9ciypkm8lor58fx
parent: pqm at pqm.ubuntu.com-20091013092944-37m2zia1k83g061y
committer: John Arbash Meinel <john at arbash-meinel.com>
branch nick: 2.1-st-from-sequence
timestamp: Tue 2009-10-13 13:00:16 -0500
message:
  Implement StaticTuple.from_sequence()
  
  This allows casting from something that *might* be a StaticTuple
  into something that is definitely a StaticTuple, without having to
  create a new instance.
-------------- next part --------------
=== modified file 'bzrlib/_static_tuple_c.c'
--- a/bzrlib/_static_tuple_c.c	2009-10-12 21:44:27 +0000
+++ b/bzrlib/_static_tuple_c.c	2009-10-13 18:00:16 +0000
@@ -174,6 +174,52 @@
 }
 
 
+static StaticTuple *
+StaticTuple_FromSequence(PyObject *sequence)
+{
+    StaticTuple *new;
+    PyObject *item;
+    Py_ssize_t i, size;
+
+    if (StaticTuple_CheckExact(sequence)) {
+        Py_INCREF(sequence);
+        return (StaticTuple *)sequence;
+    }
+    if (!PySequence_Check(sequence)) {
+        PyErr_Format(PyExc_TypeError, "Type %s is not a sequence type",
+                     Py_TYPE(sequence)->tp_name);
+        return NULL;
+    }
+    size = PySequence_Size(sequence);
+    if (size == -1)
+        return NULL;
+    new = StaticTuple_New(size);
+    if (new == NULL) {
+        return NULL;
+    }
+    for (i = 0; i < size; ++i) {
+        // This returns a new reference, which we then 'steal' with 
+        // StaticTuple_SET_ITEM
+        item = PySequence_GetItem(sequence, i);
+        if (item == NULL) {
+            Py_DECREF(new);
+            return NULL;
+        }
+        StaticTuple_SET_ITEM(new, i, item);
+    }
+    return (StaticTuple *)new;
+}
+
+static StaticTuple *
+StaticTuple_from_sequence(PyObject *self, PyObject *args, PyObject *kwargs)
+{
+    PyObject *sequence;
+    if (!PyArg_ParseTuple(args, "O", &sequence))
+        return NULL;
+    return StaticTuple_FromSequence(sequence);
+}
+
+
 static PyObject *
 StaticTuple_new_constructor(PyTypeObject *type, PyObject *args, PyObject *kwds)
 {
@@ -565,6 +611,10 @@
     {"intern", (PyCFunction)StaticTuple_Intern, METH_NOARGS, StaticTuple_Intern_doc},
     {"_is_interned", (PyCFunction)StaticTuple__is_interned, METH_NOARGS,
      StaticTuple__is_interned_doc},
+    {"from_sequence", (PyCFunction)StaticTuple_from_sequence,
+     METH_STATIC | METH_VARARGS,
+     "Create a StaticTuple from a given sequence. This functions"
+     " the same as the tuple() constructor."},
     {NULL, NULL} /* sentinel */
 };
 
@@ -684,6 +734,8 @@
         "StaticTuple *(Py_ssize_t)");
     _export_function(m, "StaticTuple_Intern", StaticTuple_Intern,
         "StaticTuple *(StaticTuple *)");
+    _export_function(m, "StaticTuple_FromSequence", StaticTuple_FromSequence,
+        "StaticTuple *(PyObject *)");
     _export_function(m, "_StaticTuple_CheckExact", _StaticTuple_CheckExact,
         "int(PyObject *)");
 }

=== modified file 'bzrlib/_static_tuple_c.h'
--- a/bzrlib/_static_tuple_c.h	2009-10-07 15:57:25 +0000
+++ b/bzrlib/_static_tuple_c.h	2009-10-13 18:00:16 +0000
@@ -74,6 +74,7 @@
 
 static StaticTuple * StaticTuple_New(Py_ssize_t);
 static StaticTuple * StaticTuple_Intern(StaticTuple *self);
+static StaticTuple * StaticTuple_FromSequence(PyObject *);
 #define StaticTuple_CheckExact(op) (Py_TYPE(op) == &StaticTuple_Type)
 
 #else
@@ -83,6 +84,7 @@
 
 static StaticTuple *(*StaticTuple_New)(Py_ssize_t);
 static StaticTuple *(*StaticTuple_Intern)(StaticTuple *);
+static StaticTuple *(*StaticTuple_FromSequence)(PyObject *);
 static PyTypeObject *_p_StaticTuple_Type;
 
 #define StaticTuple_CheckExact(op) (Py_TYPE(op) == _p_StaticTuple_Type)
@@ -98,6 +100,8 @@
             "StaticTuple *(Py_ssize_t)"},
         {"StaticTuple_Intern", (void **)&StaticTuple_Intern,
             "StaticTuple *(StaticTuple *)"},
+        {"StaticTuple_FromSequence", (void **)&StaticTuple_FromSequence,
+            "StaticTuple *(PyObject *)"},
         {"_StaticTuple_CheckExact", (void **)&_StaticTuple_CheckExact,
             "int(PyObject *)"},
         {NULL}};

=== modified file 'bzrlib/_static_tuple_py.py'
--- a/bzrlib/_static_tuple_py.py	2009-10-12 17:07:05 +0000
+++ b/bzrlib/_static_tuple_py.py	2009-10-13 18:00:16 +0000
@@ -51,6 +51,15 @@
     def intern(self):
         return _interned_tuples.setdefault(self, self)
 
+    @staticmethod
+    def from_sequence(seq):
+        """Convert a sequence object into a StaticTuple instance."""
+        if isinstance(seq, StaticTuple):
+            # it already is
+            return seq
+        return StaticTuple(*seq)
+
+
 
 # Have to set it to None first, so that __new__ can determine whether
 # the _empty_tuple singleton has been created yet or not.

=== modified file 'bzrlib/tests/test__static_tuple.py'
--- a/bzrlib/tests/test__static_tuple.py	2009-10-12 18:10:24 +0000
+++ b/bzrlib/tests/test__static_tuple.py	2009-10-13 18:00:16 +0000
@@ -416,3 +416,34 @@
         if self.module is _static_tuple_py:
             return
         self.assertIsNot(None, self.module._C_API)
+
+    def test_from_sequence_tuple(self):
+        st = self.module.StaticTuple.from_sequence(('foo', 'bar'))
+        self.assertIsInstance(st, self.module.StaticTuple)
+        self.assertEqual(('foo', 'bar'), st)
+
+    def test_from_sequence_str(self):
+        st = self.module.StaticTuple.from_sequence('foo')
+        self.assertIsInstance(st, self.module.StaticTuple)
+        self.assertEqual(('f', 'o', 'o'), st)
+
+    def test_from_sequence_list(self):
+        st = self.module.StaticTuple.from_sequence(['foo', 'bar'])
+        self.assertIsInstance(st, self.module.StaticTuple)
+        self.assertEqual(('foo', 'bar'), st)
+
+    def test_from_sequence_static_tuple(self):
+        st = self.module.StaticTuple('foo', 'bar')
+        st2 = self.module.StaticTuple.from_sequence(st)
+        # If the source is a StaticTuple already, we return the exact object
+        self.assertIs(st, st2)
+
+    def test_from_sequence_not_sequence(self):
+        self.assertRaises(TypeError,
+                          self.module.StaticTuple.from_sequence, object())
+
+    def test_from_sequence_incorrect_args(self):
+        self.assertRaises(TypeError,
+                          self.module.StaticTuple.from_sequence, object(), 'a')
+        self.assertRaises(TypeError,
+                          self.module.StaticTuple.from_sequence, foo='a')



More information about the bazaar-commits mailing list