Python-checkins
Threads by month
- ----- 2024 -----
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2003 -----
- December
- November
- October
- September
- August
July 2005
- 22 participants
- 376 discussions
python/nondist/sandbox/setuptools pkg_resources.py, 1.54, 1.55 setup.py, 1.33, 1.34
by pje@users.sourceforge.net 31 Jul '05
by pje@users.sourceforge.net 31 Jul '05
31 Jul '05
Update of /cvsroot/python/python/nondist/sandbox/setuptools
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv5869
Modified Files:
pkg_resources.py setup.py
Log Message:
Misc. bugs reported by Ian Bicking and Ashley Walsh.
Index: pkg_resources.py
===================================================================
RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/pkg_resources.py,v
retrieving revision 1.54
retrieving revision 1.55
diff -u -d -r1.54 -r1.55
--- pkg_resources.py 25 Jul 2005 03:12:50 -0000 1.54
+++ pkg_resources.py 31 Jul 2005 16:31:17 -0000 1.55
@@ -227,7 +227,7 @@
"""Return a current distribution object for a Requirement or string"""
if isinstance(dist,basestring): dist = Requirement.parse(dist)
if isinstance(dist,Requirement): dist = get_provider(dist)
- if not isintance(dist,Distribution):
+ if not isinstance(dist,Distribution):
raise TypeError("Expected string, Requirement, or Distribution", dist)
return dist
@@ -1443,7 +1443,7 @@
path, parent = sys.path, None
if '.' in packageName:
- parent = '.'.join(package.split('.')[:-1])
+ parent = '.'.join(packageName.split('.')[:-1])
declare_namespace(parent)
__import__(parent)
try:
Index: setup.py
===================================================================
RCS file: /cvsroot/python/python/nondist/sandbox/setuptools/setup.py,v
retrieving revision 1.33
retrieving revision 1.34
diff -u -d -r1.33 -r1.34
--- setup.py 24 Jul 2005 22:47:05 -0000 1.33
+++ setup.py 31 Jul 2005 16:31:18 -0000 1.34
@@ -44,7 +44,7 @@
entry_points = {
"distutils.commands" : [
"%(cmd)s = setuptools.command.%(cmd)s:%(cmd)s" % locals()
- for cmd in SETUP_COMMANDS if cmd!="build_py" or sys.version>="2.4"
+ for cmd in SETUP_COMMANDS if cmd!="build_py" or sys.version<"2.4"
],
},
1
0
31 Jul '05
Update of /cvsroot/python/python/dist/src/Objects
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv27102
Modified Files:
setobject.c
Log Message:
Improve variable names.
Index: setobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/setobject.c,v
retrieving revision 1.35
retrieving revision 1.36
diff -u -d -r1.35 -r1.36
--- setobject.c 31 Jul 2005 13:09:28 -0000 1.35
+++ setobject.c 31 Jul 2005 15:36:06 -0000 1.36
@@ -42,8 +42,8 @@
register unsigned int perturb;
register setentry *freeslot;
register unsigned int mask = so->mask;
- setentry *ep0 = so->table;
- register setentry *ep;
+ setentry *entry0 = so->table;
+ register setentry *entry;
register int restore_error;
register int checked_error;
register int cmp;
@@ -51,26 +51,26 @@
PyObject *startkey;
i = hash & mask;
- ep = &ep0[i];
- if (ep->key == NULL || ep->key == key)
- return ep;
+ entry = &entry0[i];
+ if (entry->key == NULL || entry->key == key)
+ return entry;
restore_error = checked_error = 0;
- if (ep->key == dummy)
- freeslot = ep;
+ if (entry->key == dummy)
+ freeslot = entry;
else {
- if (ep->hash == hash) {
+ if (entry->hash == hash) {
/* error can't have been checked yet */
checked_error = 1;
if (PyErr_Occurred()) {
restore_error = 1;
PyErr_Fetch(&err_type, &err_value, &err_tb);
}
- startkey = ep->key;
+ startkey = entry->key;
cmp = PyObject_RichCompareBool(startkey, key, Py_EQ);
if (cmp < 0)
PyErr_Clear();
- if (ep0 == so->table && ep->key == startkey) {
+ if (entry0 == so->table && entry->key == startkey) {
if (cmp > 0)
goto Done;
}
@@ -78,7 +78,7 @@
/* The compare did major nasty stuff to the
* set: start over.
*/
- ep = set_lookkey(so, key, hash);
+ entry = set_lookkey(so, key, hash);
goto Done;
}
}
@@ -89,15 +89,15 @@
least likely outcome, so test for that last. */
for (perturb = hash; ; perturb >>= PERTURB_SHIFT) {
i = (i << 2) + i + perturb + 1;
- ep = &ep0[i & mask];
- if (ep->key == NULL) {
+ entry = &entry0[i & mask];
+ if (entry->key == NULL) {
if (freeslot != NULL)
- ep = freeslot;
+ entry = freeslot;
break;
}
- if (ep->key == key)
+ if (entry->key == key)
break;
- if (ep->hash == hash && ep->key != dummy) {
+ if (entry->hash == hash && entry->key != dummy) {
if (!checked_error) {
checked_error = 1;
if (PyErr_Occurred()) {
@@ -106,11 +106,11 @@
&err_tb);
}
}
- startkey = ep->key;
+ startkey = entry->key;
cmp = PyObject_RichCompareBool(startkey, key, Py_EQ);
if (cmp < 0)
PyErr_Clear();
- if (ep0 == so->table && ep->key == startkey) {
+ if (entry0 == so->table && entry->key == startkey) {
if (cmp > 0)
break;
}
@@ -118,18 +118,18 @@
/* The compare did major nasty stuff to the
* set: start over.
*/
- ep = set_lookkey(so, key, hash);
+ entry = set_lookkey(so, key, hash);
break;
}
}
- else if (ep->key == dummy && freeslot == NULL)
- freeslot = ep;
+ else if (entry->key == dummy && freeslot == NULL)
+ freeslot = entry;
}
Done:
if (restore_error)
PyErr_Restore(err_type, err_value, err_tb);
- return ep;
+ return entry;
}
/*
@@ -149,8 +149,8 @@
register unsigned int perturb;
register setentry *freeslot;
register unsigned int mask = so->mask;
- setentry *ep0 = so->table;
- register setentry *ep;
+ setentry *entry0 = so->table;
+ register setentry *entry;
/* Make sure this function doesn't have to handle non-string keys,
including subclasses of str; e.g., one reason to subclass
@@ -161,14 +161,14 @@
return set_lookkey(so, key, hash);
}
i = hash & mask;
- ep = &ep0[i];
- if (ep->key == NULL || ep->key == key)
- return ep;
- if (ep->key == dummy)
- freeslot = ep;
+ entry = &entry0[i];
+ if (entry->key == NULL || entry->key == key)
+ return entry;
+ if (entry->key == dummy)
+ freeslot = entry;
else {
- if (ep->hash == hash && _PyString_Eq(ep->key, key))
- return ep;
+ if (entry->hash == hash && _PyString_Eq(entry->key, key))
+ return entry;
freeslot = NULL;
}
@@ -176,43 +176,43 @@
least likely outcome, so test for that last. */
for (perturb = hash; ; perturb >>= PERTURB_SHIFT) {
i = (i << 2) + i + perturb + 1;
- ep = &ep0[i & mask];
- if (ep->key == NULL)
- return freeslot == NULL ? ep : freeslot;
- if (ep->key == key
- || (ep->hash == hash
- && ep->key != dummy
- && _PyString_Eq(ep->key, key)))
- return ep;
- if (ep->key == dummy && freeslot == NULL)
- freeslot = ep;
+ entry = &entry0[i & mask];
+ if (entry->key == NULL)
+ return freeslot == NULL ? entry : freeslot;
+ if (entry->key == key
+ || (entry->hash == hash
+ && entry->key != dummy
+ && _PyString_Eq(entry->key, key)))
+ return entry;
+ if (entry->key == dummy && freeslot == NULL)
+ freeslot = entry;
}
}
/*
-Internal routine to insert a new item into the table.
+Internal routine to insert a new key into the table.
Used both by the internal resize routine and by the public insert routine.
Eats a reference to key.
*/
static void
set_insert_key(register PySetObject *so, PyObject *key, long hash)
{
- register setentry *ep;
+ register setentry *entry;
typedef setentry *(*lookupfunc)(PySetObject *, PyObject *, long);
assert(so->lookup != NULL);
- ep = so->lookup(so, key, hash);
- if (ep->key == NULL) {
+ entry = so->lookup(so, key, hash);
+ if (entry->key == NULL) {
/* UNUSED */
so->fill++;
- ep->key = key;
- ep->hash = hash;
+ entry->key = key;
+ entry->hash = hash;
so->used++;
- } else if (ep->key == dummy) {
+ } else if (entry->key == dummy) {
/* DUMMY */
- ep->key = key;
- ep->hash = hash;
+ entry->key = key;
+ entry->hash = hash;
so->used++;
Py_DECREF(dummy);
} else {
@@ -223,14 +223,14 @@
/*
Restructure the table by allocating a new table and reinserting all
-items again. When entries have been deleted, the new table may
+keys again. When entries have been deleted, the new table may
actually be smaller than the old one.
*/
static int
set_table_resize(PySetObject *so, int minused)
{
int newsize;
- setentry *oldtable, *newtable, *ep;
+ setentry *oldtable, *newtable, *entry;
int i;
int is_oldtable_malloced;
setentry small_copy[PySet_MINSIZE];
@@ -290,19 +290,19 @@
/* Copy the data over; this is refcount-neutral for active entries;
dummy entries aren't copied over, of course */
- for (ep = oldtable; i > 0; ep++) {
- if (ep->key == NULL) {
+ for (entry = oldtable; i > 0; entry++) {
+ if (entry->key == NULL) {
/* UNUSED */
;
- } else if (ep->key == dummy) {
+ } else if (entry->key == dummy) {
/* DUMMY */
--i;
- assert(ep->key == dummy);
- Py_DECREF(ep->key);
+ assert(entry->key == dummy);
+ Py_DECREF(entry->key);
} else {
/* ACTIVE */
--i;
- set_insert_key(so, ep->key, ep->hash);
+ set_insert_key(so, entry->key, entry->hash);
}
}
@@ -346,7 +346,7 @@
set_discard_internal(PySetObject *so, PyObject *key)
{
register long hash;
- register setentry *ep;
+ register setentry *entry;
PyObject *old_key;
assert (PyAnySet_Check(so));
@@ -356,12 +356,12 @@
if (hash == -1)
return -1;
}
- ep = (so->lookup)(so, key, hash);
- if (ep->key == NULL || ep->key == dummy)
+ entry = (so->lookup)(so, key, hash);
+ if (entry->key == NULL || entry->key == dummy)
return DISCARD_NOTFOUND;
- old_key = ep->key;
+ old_key = entry->key;
Py_INCREF(dummy);
- ep->key = dummy;
+ entry->key = dummy;
so->used--;
Py_DECREF(old_key);
return DISCARD_FOUND;
@@ -370,7 +370,7 @@
static void
set_clear_internal(PySetObject *so)
{
- setentry *ep, *table;
+ setentry *entry, *table;
int table_is_malloced;
int fill;
setentry small_copy[PySet_MINSIZE];
@@ -413,18 +413,18 @@
* assert that the refcount on table is 1 now, i.e. that this function
* has unique access to it, so decref side-effects can't alter it.
*/
- for (ep = table; fill > 0; ++ep) {
+ for (entry = table; fill > 0; ++entry) {
#ifdef Py_DEBUG
assert(i < n);
++i;
#endif
- if (ep->key) {
+ if (entry->key) {
--fill;
- Py_DECREF(ep->key);
+ Py_DECREF(entry->key);
}
#ifdef Py_DEBUG
else
- assert(ep->key == NULL || ep->key == dummy);
+ assert(entry->key == NULL || entry->key == dummy);
#endif
}
@@ -446,45 +446,45 @@
* mutates the table.
*/
static int
-set_next_internal(PySetObject *so, int *ppos, PyObject **pkey)
+set_next_internal(PySetObject *so, int *pos, PyObject **key)
{
register int i, mask;
- register setentry *ep;
+ register setentry *entry;
assert (PyAnySet_Check(so));
- i = *ppos;
+ i = *pos;
if (i < 0)
return 0;
- ep = so->table;
+ entry = so->table;
mask = so->mask;
- while (i <= mask && (ep[i].key == NULL || ep[i].key == dummy))
+ while (i <= mask && (entry[i].key == NULL || entry[i].key == dummy))
i++;
- *ppos = i+1;
+ *pos = i+1;
if (i > mask)
return 0;
- if (pkey)
- *pkey = ep[i].key;
+ if (key)
+ *key = entry[i].key;
return 1;
}
/* Methods */
static int
-set_merge_internal(PySetObject *so, PyObject *b)
+set_merge_internal(PySetObject *so, PyObject *otherset)
{
register PySetObject *other;
register int i;
setentry *entry;
assert (PyAnySet_Check(so));
- assert (PyAnySet_Check(b));
+ assert (PyAnySet_Check(otherset));
- other = (PySetObject*)b;
+ other = (PySetObject*)otherset;
if (other == so || other->used == 0)
/* a.update(a) or a.update({}); nothing to do */
return 0;
/* Do one big resize at the start, rather than
- * incrementally resizing as we insert new items. Expect
+ * incrementally resizing as we insert new keys. Expect
* that there will be no (or few) overlapping keys.
*/
if ((so->fill + other->used)*3 >= (so->mask+1)*2) {
@@ -563,18 +563,18 @@
0, /* sq_concat */
};
-static PyObject *setiter_iternextkey(setiterobject *si)
+static PyObject *setiter_iternext(setiterobject *si)
{
PyObject *key;
register int i, mask;
- register setentry *ep;
- PySetObject *d = si->si_set;
+ register setentry *entry;
+ PySetObject *so = si->si_set;
- if (d == NULL)
+ if (so == NULL)
return NULL;
- assert (PyAnySet_Check(d));
+ assert (PyAnySet_Check(so));
- if (si->si_used != d->used) {
+ if (si->si_used != so->used) {
PyErr_SetString(PyExc_RuntimeError,
"Set changed size during iteration");
si->si_used = -1; /* Make this state sticky */
@@ -584,20 +584,20 @@
i = si->si_pos;
if (i < 0)
goto fail;
- ep = d->table;
- mask = d->mask;
- while (i <= mask && (ep[i].key == NULL || ep[i].key == dummy))
+ entry = so->table;
+ mask = so->mask;
+ while (i <= mask && (entry[i].key == NULL || entry[i].key == dummy))
i++;
si->si_pos = i+1;
if (i > mask)
goto fail;
si->len--;
- key = ep[i].key;
+ key = entry[i].key;
Py_INCREF(key);
return key;
fail:
- Py_DECREF(d);
+ Py_DECREF(so);
si->si_set = NULL;
return NULL;
}
@@ -605,7 +605,7 @@
PyTypeObject PySetIter_Type = {
PyObject_HEAD_INIT(&PyType_Type)
0, /* ob_size */
- "Set-keyiterator", /* tp_name */
+ "setiterator", /* tp_name */
sizeof(setiterobject), /* tp_basicsize */
0, /* tp_itemsize */
/* methods */
@@ -631,7 +631,7 @@
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
PyObject_SelfIter, /* tp_iter */
- (iternextfunc)setiter_iternextkey, /* tp_iternext */
+ (iternextfunc)setiter_iternext, /* tp_iternext */
};
/***** Derived functions (table accesses only done with above primitives *****/
@@ -650,7 +650,7 @@
static PyObject *
set_update(PySetObject *so, PyObject *other)
{
- PyObject *item, *it;
+ PyObject *key, *it;
if (PyAnySet_Check(other)) {
if (set_merge_internal(so, other) == -1)
@@ -659,10 +659,10 @@
}
if (PyDict_Check(other)) {
- PyObject *value, *item;
+ PyObject *key, *value;
int pos = 0;
- while (PyDict_Next(other, &pos, &item, &value)) {
- if (set_add_internal(so, item) == -1)
+ while (PyDict_Next(other, &pos, &key, &value)) {
+ if (set_add_internal(so, key) == -1)
return NULL;
}
Py_RETURN_NONE;
@@ -672,13 +672,13 @@
if (it == NULL)
return NULL;
- while ((item = PyIter_Next(it)) != NULL) {
- if (set_add_internal(so, item) == -1) {
+ while ((key = PyIter_Next(it)) != NULL) {
+ if (set_add_internal(so, key) == -1) {
Py_DECREF(it);
- Py_DECREF(item);
+ Py_DECREF(key);
return NULL;
}
- Py_DECREF(item);
+ Py_DECREF(key);
}
Py_DECREF(it);
if (PyErr_Occurred())
@@ -754,7 +754,7 @@
static void
set_dealloc(PySetObject *so)
{
- register setentry *ep;
+ register setentry *entry;
int fill = so->fill;
PyObject_GC_UnTrack(so);
@@ -762,10 +762,10 @@
if (so->weakreflist != NULL)
PyObject_ClearWeakRefs((PyObject *) so);
- for (ep = so->table; fill > 0; ep++) {
- if (ep->key) {
+ for (entry = so->table; fill > 0; entry++) {
+ if (entry->key) {
--fill;
- Py_DECREF(ep->key);
+ Py_DECREF(entry->key);
}
}
if (so->table != so->smalltable)
@@ -778,11 +778,11 @@
static int
set_traverse(PySetObject *so, visitproc visit, void *arg)
{
- int i = 0;
- PyObject *pk;
+ int pos = 0;
+ PyObject *key;
- while (set_next_internal(so, &i, &pk))
- Py_VISIT(pk);
+ while (set_next_internal(so, &pos, &key))
+ Py_VISIT(key);
return 0;
}
@@ -834,25 +834,25 @@
memcpy(b->smalltable, tab, sizeof(tab));
}
- h = a->hash; a->hash = b->hash; b->hash = h;
+ h = a->hash; a->hash = b->hash; b->hash = h;
}
static int
set_contains(PySetObject *so, PyObject *key)
{
- PyObject *tmp;
+ PyObject *tmpkey;
int result;
result = set_contains_internal(so, key);
if (result == -1 && PyAnySet_Check(key)) {
PyErr_Clear();
- tmp = make_new_set(&PyFrozenSet_Type, NULL);
- if (tmp == NULL)
+ tmpkey = make_new_set(&PyFrozenSet_Type, NULL);
+ if (tmpkey == NULL)
return -1;
- set_swap_bodies((PySetObject *)tmp, (PySetObject *)key);
- result = set_contains_internal(so, tmp);
- set_swap_bodies((PySetObject *)tmp, (PySetObject *)key);
- Py_DECREF(tmp);
+ set_swap_bodies((PySetObject *)tmpkey, (PySetObject *)key);
+ result = set_contains_internal(so, tmpkey);
+ set_swap_bodies((PySetObject *)tmpkey, (PySetObject *)key);
+ Py_DECREF(tmpkey);
}
return result;
}
@@ -942,7 +942,7 @@
set_intersection(PySetObject *so, PyObject *other)
{
PySetObject *result;
- PyObject *item, *it, *tmp;
+ PyObject *key, *it, *tmp;
result = (PySetObject *)make_new_set(so->ob_type, NULL);
if (result == NULL)
@@ -956,9 +956,9 @@
if (PyAnySet_Check(other)) {
int pos = 0;
- while (set_next_internal((PySetObject *)other, &pos, &item)) {
- if (set_contains_internal(so, item)) {
- if (set_add_internal(result, item) == -1) {
+ while (set_next_internal((PySetObject *)other, &pos, &key)) {
+ if (set_contains_internal(so, key)) {
+ if (set_add_internal(result, key) == -1) {
Py_DECREF(result);
return NULL;
}
@@ -973,16 +973,16 @@
return NULL;
}
- while ((item = PyIter_Next(it)) != NULL) {
- if (set_contains_internal(so, item)) {
- if (set_add_internal(result, item) == -1) {
+ while ((key = PyIter_Next(it)) != NULL) {
+ if (set_contains_internal(so, key)) {
+ if (set_add_internal(result, key) == -1) {
Py_DECREF(it);
Py_DECREF(result);
- Py_DECREF(item);
+ Py_DECREF(key);
return NULL;
}
}
- Py_DECREF(item);
+ Py_DECREF(key);
}
Py_DECREF(it);
if (PyErr_Occurred()) {
@@ -1043,19 +1043,19 @@
static PyObject *
set_difference_update(PySetObject *so, PyObject *other)
{
- PyObject *item, *it;
+ PyObject *key, *it;
it = PyObject_GetIter(other);
if (it == NULL)
return NULL;
- while ((item = PyIter_Next(it)) != NULL) {
- if (set_discard_internal(so, item) == -1) {
+ while ((key = PyIter_Next(it)) != NULL) {
+ if (set_discard_internal(so, key) == -1) {
Py_DECREF(it);
- Py_DECREF(item);
+ Py_DECREF(key);
return NULL;
}
- Py_DECREF(item);
+ Py_DECREF(key);
}
Py_DECREF(it);
if (PyErr_Occurred())
@@ -1425,9 +1425,9 @@
}
static PyObject *
-set_add(PySetObject *so, PyObject *item)
+set_add(PySetObject *so, PyObject *key)
{
- if (set_add_internal(so, item) == -1)
+ if (set_add_internal(so, key) == -1)
return NULL;
Py_RETURN_NONE;
}
@@ -1438,27 +1438,27 @@
This has no effect if the element is already present.");
static PyObject *
-set_remove(PySetObject *so, PyObject *item)
+set_remove(PySetObject *so, PyObject *key)
{
- PyObject *tmp, *result;
+ PyObject *tmpkey, *result;
int rv;
- if (PyType_IsSubtype(item->ob_type, &PySet_Type)) {
- tmp = make_new_set(&PyFrozenSet_Type, NULL);
- if (tmp == NULL)
+ if (PyType_IsSubtype(key->ob_type, &PySet_Type)) {
+ tmpkey = make_new_set(&PyFrozenSet_Type, NULL);
+ if (tmpkey == NULL)
return NULL;
- set_swap_bodies((PySetObject *)item, (PySetObject *)tmp);
- result = set_remove(so, tmp);
- set_swap_bodies((PySetObject *)item, (PySetObject *)tmp);
- Py_DECREF(tmp);
+ set_swap_bodies((PySetObject *)key, (PySetObject *)tmpkey);
+ result = set_remove(so, tmpkey);
+ set_swap_bodies((PySetObject *)key, (PySetObject *)tmpkey);
+ Py_DECREF(tmpkey);
return result;
}
- rv = set_discard_internal(so, item);
+ rv = set_discard_internal(so, key);
if (rv == -1)
return NULL;
else if (rv == DISCARD_NOTFOUND) {
- PyErr_SetObject(PyExc_KeyError, item);
+ PyErr_SetObject(PyExc_KeyError, key);
return NULL;
}
Py_RETURN_NONE;
@@ -1470,22 +1470,22 @@
If the element is not a member, raise a KeyError.");
static PyObject *
-set_discard(PySetObject *so, PyObject *item)
+set_discard(PySetObject *so, PyObject *key)
{
- PyObject *tmp, *result;
+ PyObject *tmpkey, *result;
- if (PyType_IsSubtype(item->ob_type, &PySet_Type)) {
- tmp = make_new_set(&PyFrozenSet_Type, NULL);
- if (tmp == NULL)
+ if (PyType_IsSubtype(key->ob_type, &PySet_Type)) {
+ tmpkey = make_new_set(&PyFrozenSet_Type, NULL);
+ if (tmpkey == NULL)
return NULL;
- set_swap_bodies((PySetObject *)item, (PySetObject *)tmp);
- result = set_discard(so, tmp);
- set_swap_bodies((PySetObject *)item, (PySetObject *)tmp);
- Py_DECREF(tmp);
+ set_swap_bodies((PySetObject *)key, (PySetObject *)tmpkey);
+ result = set_discard(so, tmpkey);
+ set_swap_bodies((PySetObject *)key, (PySetObject *)tmpkey);
+ Py_DECREF(tmpkey);
return result;
}
- if (set_discard_internal(so, item) == -1)
+ if (set_discard_internal(so, key) == -1)
return NULL;
Py_RETURN_NONE;
}
1
0
31 Jul '05
Update of /cvsroot/python/python/dist/src/Objects
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv32542
Modified Files:
setobject.c
Log Message:
Fix frozenset() ref count and a comment typo.
Index: setobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/setobject.c,v
retrieving revision 1.34
retrieving revision 1.35
diff -u -d -r1.34 -r1.35
--- setobject.c 31 Jul 2005 01:33:10 -0000 1.34
+++ setobject.c 31 Jul 2005 13:09:28 -0000 1.35
@@ -735,8 +735,7 @@
if (type == &PyFrozenSet_Type) {
if (emptyfrozenset == NULL)
emptyfrozenset = make_new_set(type, NULL);
- else
- Py_INCREF(emptyfrozenset);
+ Py_INCREF(emptyfrozenset);
return emptyfrozenset;
}
} else if (PyFrozenSet_CheckExact(iterable)) {
@@ -803,7 +802,7 @@
Useful for creating temporary frozensets from sets for membership testing
in __contains__(), discard(), and remove(). Also useful for operations
that update in-place (by allowing an intermediate result to be swapped
- into one of original the inputs).
+ into one of the original inputs).
*/
static void
1
0
31 Jul '05
Update of /cvsroot/python/python/dist/src/Objects
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv31785
Modified Files:
setobject.c
Log Message:
Comment on the set_swap_bodies() helper function.
Index: setobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/setobject.c,v
retrieving revision 1.33
retrieving revision 1.34
diff -u -d -r1.33 -r1.34
--- setobject.c 31 Jul 2005 01:16:36 -0000 1.33
+++ setobject.c 31 Jul 2005 01:33:10 -0000 1.34
@@ -793,6 +793,19 @@
return ((PySetObject *)so)->used;
}
+/* set_swap_bodies() switches the contents of any two sets by moving their
+ internal data pointers and, if needed, copying the internal smalltables.
+ Semantically equivalent to:
+
+ t=set(a); a.clear(); a.update(b); b.clear(); b.update(t); del t
+
+ The function always succeeds and it leaves both objects in a stable state.
+ Useful for creating temporary frozensets from sets for membership testing
+ in __contains__(), discard(), and remove(). Also useful for operations
+ that update in-place (by allowing an intermediate result to be swapped
+ into one of original the inputs).
+*/
+
static void
set_swap_bodies(PySetObject *a, PySetObject *b)
{
1
0
31 Jul '05
Update of /cvsroot/python/python/dist/src/Include
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv27783/Include
Modified Files:
setobject.h
Log Message:
Revised the set() and frozenset() implementaion to use its own internal
data structure instead of using dictionaries. Reduces memory consumption
by 1/3 and provides modest speed-ups for most set operations.
Index: setobject.h
===================================================================
RCS file: /cvsroot/python/python/dist/src/Include/setobject.h,v
retrieving revision 2.5
retrieving revision 2.6
diff -u -d -r2.5 -r2.6
--- setobject.h 28 Oct 2004 16:31:59 -0000 2.5
+++ setobject.h 31 Jul 2005 01:16:36 -0000 2.6
@@ -1,4 +1,3 @@
-
/* Set object interface */
#ifndef Py_SETOBJECT_H
@@ -7,28 +6,61 @@
extern "C" {
#endif
+
/*
-This data structure is shared by set and frozenset objects.
+There are three kinds of slots in the table:
+
+1. Unused: key == NULL
+2. Active: key != NULL and key != dummy
+3. Dummy: key == dummy
*/
+#define PySet_MINSIZE 8
+
typedef struct {
+ long hash; /* cached hash code for the entry key */
+ PyObject *key;
+} setentry;
+
+
+/*
+This data structure is shared by set and frozenset objects.
+*/
+
+typedef struct _setobject PySetObject;
+struct _setobject {
PyObject_HEAD
- PyObject *data;
- long hash; /* only used by frozenset objects */
- PyObject *weakreflist; /* List of weak references */
- /* Invariants:
- * data is a dictionary whose values are all True.
- * data points to the same dict for the whole life of the set.
- * For frozensets only:
- * data is immutable.
- * hash is the hash of the frozenset or -1 if not computed yet.
+ int fill; /* # Active + # Dummy */
+ int used; /* # Active */
+
+ /* The table contains mask + 1 slots, and that's a power of 2.
+ * We store the mask instead of the size because the mask is more
+ * frequently needed.
*/
-} PySetObject;
+ int mask;
+
+ /* table points to smalltable for small tables, else to
+ * additional malloc'ed memory. table is never NULL! This rule
+ * saves repeated runtime null-tests in the workhorse getitem and
+ * setitem calls.
+ */
+ setentry *table;
+ setentry *(*lookup)(PySetObject *so, PyObject *key, long hash);
+ setentry smalltable[PySet_MINSIZE];
+
+ long hash; /* only used by frozenset objects */
+ PyObject *weakreflist; /* List of weak references */
+};
PyAPI_DATA(PyTypeObject) PySet_Type;
PyAPI_DATA(PyTypeObject) PyFrozenSet_Type;
+/* Invariants for frozensets only:
+ * data is immutable.
+ * hash is the hash of the frozenset or -1 if not computed yet.
+ */
+
#define PyFrozenSet_CheckExact(ob) ((ob)->ob_type == &PyFrozenSet_Type)
#define PyAnySet_Check(ob) \
((ob)->ob_type == &PySet_Type || (ob)->ob_type == &PyFrozenSet_Type || \
1
0
31 Jul '05
Update of /cvsroot/python/python/dist/src/Objects
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv27783/Objects
Modified Files:
setobject.c
Log Message:
Revised the set() and frozenset() implementaion to use its own internal
data structure instead of using dictionaries. Reduces memory consumption
by 1/3 and provides modest speed-ups for most set operations.
Index: setobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/setobject.c,v
retrieving revision 1.32
retrieving revision 1.33
diff -u -d -r1.32 -r1.33
--- setobject.c 18 Jun 2005 21:00:25 -0000 1.32
+++ setobject.c 31 Jul 2005 01:16:36 -0000 1.33
@@ -1,4 +1,641 @@
+
+/* Set object implementation using a hash table
+ Functions adapted from dictobject.c
+*/
+
#include "Python.h"
+
+/* This must be >= 1. */
+#define PERTURB_SHIFT 5
+
+/* Object used as dummy key to fill deleted entries */
[...1390 lines suppressed...]
+ Py_TPFLAGS_BASETYPE, /* tp_flags */
set_doc, /* tp_doc */
(traverseproc)set_traverse, /* tp_traverse */
(inquiry)set_tp_clear, /* tp_clear */
(richcmpfunc)set_richcompare, /* tp_richcompare */
offsetof(PySetObject, weakreflist), /* tp_weaklistoffset */
- (getiterfunc)set_iter, /* tp_iter */
+ (getiterfunc)set_iter, /* tp_iter */
0, /* tp_iternext */
set_methods, /* tp_methods */
0, /* tp_members */
@@ -1120,7 +1772,7 @@
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES |
- Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
+ Py_TPFLAGS_BASETYPE, /* tp_flags */
frozenset_doc, /* tp_doc */
(traverseproc)set_traverse, /* tp_traverse */
0, /* tp_clear */
1
0
Update of /cvsroot/python/python/dist/src/Misc
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv27783/Misc
Modified Files:
NEWS
Log Message:
Revised the set() and frozenset() implementaion to use its own internal
data structure instead of using dictionaries. Reduces memory consumption
by 1/3 and provides modest speed-ups for most set operations.
Index: NEWS
===================================================================
RCS file: /cvsroot/python/python/dist/src/Misc/NEWS,v
retrieving revision 1.1326
retrieving revision 1.1327
diff -u -d -r1.1326 -r1.1327
--- NEWS 27 Jul 2005 20:24:40 -0000 1.1326
+++ NEWS 31 Jul 2005 01:16:35 -0000 1.1327
@@ -12,6 +12,10 @@
Core and builtins
-----------------
+- The implementation of set() and frozenset() was revised to use its
+ own internal data structure. Memory consumption is reduced by 1/3
+ and there are modest speed-ups as well. The API is unchanged.
+
- SF bug #1238681: freed pointer is used in longobject.c:long_pow().
- SF bug #1229429: PyObject_CallMethod failed to decrement some
1
0
python/nondist/sandbox/mailbox mailbox.py, 1.1, 1.2 libmailbox.tex, 1.2, 1.3 test_mailbox.py, 1.1, 1.2
by gregorykjohnson@users.sourceforge.net 30 Jul '05
by gregorykjohnson@users.sourceforge.net 30 Jul '05
30 Jul '05
Update of /cvsroot/python/python/nondist/sandbox/mailbox
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv31617
Modified Files:
mailbox.py libmailbox.tex test_mailbox.py
Log Message:
* Implement all Message subclasses, including conversion.
* Fix handling of new-ness by Maildir: let subdir and info vary
orthogonally (so flags can be added to messages in "new"). The spec
doesn't disallow this, and some implementations do so.
* Miscellaneous documentation and code enhancements.
Index: mailbox.py
===================================================================
RCS file: /cvsroot/python/python/nondist/sandbox/mailbox/mailbox.py,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- mailbox.py 26 Jul 2005 20:47:46 -0000 1.1
+++ mailbox.py 30 Jul 2005 22:49:08 -0000 1.2
@@ -191,9 +191,9 @@
Mailbox.__init__(self, dirname, factory)
if not os.path.exists(self._path):
os.mkdir(self._path, 0700)
- os.mkdir(os.path.join(self._path, "tmp"), 0700)
- os.mkdir(os.path.join(self._path, "new"), 0700)
- os.mkdir(os.path.join(self._path, "cur"), 0700)
+ os.mkdir(os.path.join(self._path, 'tmp'), 0700)
+ os.mkdir(os.path.join(self._path, 'new'), 0700)
+ os.mkdir(os.path.join(self._path, 'cur'), 0700)
self._toc = {}
def add(self, message):
@@ -252,6 +252,7 @@
self.discard(key)
os.rename(os.path.join(self._path, temp_subpath),
os.path.join(self._path, subdir, key + suffix))
+ # XXX: the mtime should be reset to keep delivery date
def get_message(self, key):
"""Return a Message representation or raise a KeyError."""
@@ -262,10 +263,9 @@
finally:
f.close()
subdir, name = os.path.split(subpath)
- if subdir == 'cur':
- msg.set_subdir('cur')
- if name.find(':') != -1:
- msg.set_info(name.split(':')[-1])
+ msg.set_subdir(subdir)
+ if name.find(':') != -1:
+ msg.set_info(name.split(':')[-1])
return msg
def get_string(self, key):
@@ -403,6 +403,8 @@
"""Initialize a Message instance."""
if isinstance(message, email.Message.Message):
self._become_message(copy.deepcopy(message))
+ if isinstance(message, Message):
+ message._explain_to(self)
elif isinstance(message, str):
self._become_message(email.message_from_string(message))
elif hasattr(message, "read"):
@@ -431,11 +433,9 @@
def __init__(self, message=None):
"""Initialize a MaildirMessage instance."""
- Message.__init__(self, message)
self._subdir = 'new'
self._info = ''
- if isinstance(message, Message):
- message._explain_to(self)
+ Message.__init__(self, message)
def get_subdir(self):
"""Return 'new' or 'cur'."""
@@ -453,21 +453,19 @@
if len(self._info) > 2 and self._info[:2] == '2,':
return self._info[2:]
else:
- return ""
+ return ''
def set_flags(self, flags):
"""Set the given flags and unset all others."""
- if self.get_subdir() == 'new':
- self.set_subdir('cur')
self._info = '2,' + ''.join(sorted(flags))
def add_flags(self, flags):
- """Set the given flags without changing others."""
+ """Set the given flags without changing others."""
self.set_flags(''.join(set(self.get_flags()) | set(flags)))
def remove_flags(self, flags):
- """Unset the given string flags (if set) without changing other."""
- if self.get_flags() != "":
+ """Unset the given string flags (if set) without changing others."""
+ if self.get_flags() != '':
self.set_flags(''.join(set(self.get_flags()) - set(flags)))
def get_info(self):
@@ -476,8 +474,6 @@
def set_info(self, info):
"""Set the message's "info" string."""
- if self.get_subdir() == 'new':
- self.set_subdir('cur')
if isinstance(info, str):
self._info = info
else:
@@ -485,13 +481,307 @@
def _explain_to(self, message):
"""Copy Maildir-specific state to message insofar as possible."""
- if isinstance(message, Message):
- return
- # XXX convert to other formats as needed
+ if isinstance(message, MaildirMessage):
+ message.set_flags(self.get_flags())
+ message.set_subdir(self.get_subdir())
+ elif isinstance(message, _mboxMMDFMessage):
+ flags = set(self.get_flags())
+ if 'S' in flags:
+ message.add_flags('R')
+ if self.get_subdir() == 'cur':
+ message.add_flags('O')
+ if 'T' in flags:
+ message.add_flags('D')
+ if 'F' in flags:
+ message.add_flags('F')
+ if 'R' in flags:
+ message.add_flags('A')
+ elif isinstance(message, MHMessage):
+ flags = set(self.get_flags())
+ if 'S' not in flags:
+ message.join_sequence('unseen')
+ if 'R' in flags:
+ message.join_sequence('replied')
+ if 'F' in flags:
+ message.join_sequence('flagged')
+ elif isinstance(message, BabylMessage):
+ flags = set(self.get_flags())
+ if 'S' not in flags:
+ message.add_label('unseen')
+ if 'T' in flags:
+ message.add_label('deleted')
+ if 'R' in flags:
+ message.add_label('answered')
+ if 'P' in flags:
+ message.add_label('forwarded')
+ elif isinstance(message, Message):
+ pass
+ else:
+ raise TypeError, "Cannot convert to specified type"
+
+
+class _mboxMMDFMessage(Message):
+ """Message with mbox- or MMDF-specific properties."""
+
+ def __init__(self, message=None):
+ """Initialize an mboxMMDFMessage instance."""
+ self.set_from('MAILER-DAEMON', True)
+ if isinstance(message, email.Message.Message):
+ unixfrom = message.get_unixfrom()
+ if unixfrom is not None and unixfrom[:5] == 'From ':
+ self.set_from(unixfrom[5:])
+ elif 'Return-Path' in message:
+ # XXX: generate "From " line from Return-Path: and Received:
+ pass
+ Message.__init__(self, message)
+
+ def get_from(self):
+ """Return contents of "From " line."""
+ return self._from
+
+ def set_from(self, from_, time_=None):
+ """Set "From " line, formatting and appending time_ if specified."""
+ if time_ is not None:
+ if time_ is True:
+ time_ = time.gmtime()
+ from_ += time.strftime(" %a %b %d %H:%M:%S %Y", time_)
+ self._from = from_
+
+ def get_flags(self):
+ """Return as a string the flags that are set."""
+ return self.get('Status', '') + self.get('X-Status', '')
+
+ def set_flags(self, flags):
+ """Set the given flags and unset all others."""
+ flags = set(flags)
+ status_flags, xstatus_flags = '', ''
+ for flag in ('R', 'O'):
+ if flag in flags:
+ status_flags += flag
+ flags.remove(flag)
+ for flag in ('D', 'F', 'A'):
+ if flag in flags:
+ xstatus_flags += flag
+ flags.remove(flag)
+ xstatus_flags += ''.join(sorted(flags))
+ try:
+ self.replace_header('Status', status_flags)
+ except KeyError:
+ self.add_header('Status', status_flags)
+ try:
+ self.replace_header('X-Status', xstatus_flags)
+ except KeyError:
+ self.add_header('X-Status', xstatus_flags)
+
+ def add_flags(self, flags):
+ """Set the given flags without changing others."""
+ self.set_flags(''.join(set(self.get_flags()) | set(flags)))
+
+ def remove_flags(self, flags):
+ """Unset the given string flags (if set) without changing others."""
+ if 'Status' in self or 'X-Status' in self:
+ self.set_flags(''.join(set(self.get_flags()) - set(flags)))
+
+ def _explain_to(self, message):
+ """Copy mbox- or MMDF-specific state to message insofar as possible."""
+ if isinstance(message, MaildirMessage):
+ flags = set(self.get_flags())
+ if 'O' in flags:
+ message.set_subdir('cur')
+ if 'F' in flags:
+ message.add_flags('F')
+ if 'A' in flags:
+ message.add_flags('R')
+ if 'R' in flags:
+ message.add_flags('S')
+ if 'D' in flags:
+ message.add_flags('T')
+ elif isinstance(message, _mboxMMDFMessage):
+ message.set_flags(self.get_flags())
+ message.set_from(self.get_from())
+ elif isinstance(message, MHMessage):
+ flags = set(self.get_flags())
+ if 'R' not in flags:
+ message.join_sequence('unseen')
+ if 'A' in flags:
+ message.join_sequence('replied')
+ if 'F' in flags:
+ message.join_sequence('flagged')
+ elif isinstance(message, BabylMessage):
+ flags = set(self.get_flags())
+ if 'R' not in flags:
+ message.add_label('unseen')
+ if 'D' in flags:
+ message.add_label('deleted')
+ if 'A' in flags:
+ message.add_label('answered')
+ elif isinstance(message, Message):
+ pass
+ else:
+ raise TypeError, "Cannot convert to specified type"
+
+
+class mboxMessage(_mboxMMDFMessage):
+ """Message with mbox-specific properties."""
+
+
+class MHMessage(Message):
+ """Message with MH-specific properties."""
+
+ def __init__(self, message=None):
+ """Initialize an MHMessage instance."""
+ self._sequences = []
+ Message.__init__(self, message)
+
+ def list_sequences(self):
+ """Return a list of sequences that include the message."""
+ return self._sequences[:]
+
+ def join_sequence(self, sequence):
+ """Add sequence to list of sequences including the message."""
+ if isinstance(sequence, str):
+ if not sequence in self._sequences:
+ self._sequences.append(sequence)
+ else:
+ raise TypeError, "sequence must be a string"
+
+ def leave_sequence(self, sequence):
+ """Remove sequence from the list of sequences including the message."""
+ try:
+ self._sequences.remove(sequence)
+ except ValueError:
+ pass
+
+ def _explain_to(self, message):
+ """Copy MH-specific state to message insofar as possible."""
+ if isinstance(message, MaildirMessage):
+ sequences = set(self.list_sequences())
+ if 'unseen' in sequences:
+ message.set_subdir('cur')
+ else:
+ message.set_subdir('cur')
+ message.add_flags('S')
+ if 'flagged' in sequences:
+ message.add_flags('F')
+ if 'replied' in sequences:
+ message.add_flags('R')
+ elif isinstance(message, _mboxMMDFMessage):
+ sequences = set(self.list_sequences())
+ if 'unseen' not in sequences:
+ message.add_flags('RO')
+ else:
+ message.add_flags('O')
+ if 'flagged' in sequences:
+ message.add_flags('F')
+ if 'replied' in sequences:
+ message.add_flags('A')
+ elif isinstance(message, MHMessage):
+ for sequence in self.list_sequences():
+ message.join_sequence(sequence)
+ elif isinstance(message, BabylMessage):
+ sequences = set(self.list_sequences())
+ if 'unseen' in sequences:
+ message.add_label('unseen')
+ if 'replied' in sequences:
+ message.add_label('answered')
+ elif isinstance(message, Message):
+ pass
+ else:
+ raise TypeError, "Cannot convert to specified type"
+
+
+class BabylMessage(Message):
+ """Message with Babyl-specific properties."""
+
+ def __init__(self, message=None):
+ """Initialize an BabylMessage instance."""
+ self._labels = []
+ self._visible = Message()
+ Message.__init__(self, message)
+
+ def list_labels(self):
+ """Return a list of labels on the message."""
+ return self._labels[:]
+
+ def add_label(self, label):
+ """Add label to list of labels on the message."""
+ if isinstance(label, str):
+ if label not in self._labels:
+ self._labels.append(label)
+ else:
+ raise TypeError, "label must be a string"
+
+ def remove_label(self, label):
+ """Remove label from the list of labels on the message."""
+ try:
+ self._labels.remove(label)
+ except ValueError:
+ pass
+
+ def get_visible(self):
+ """Return a Message representation of visible headers."""
+ return Message(self._visible)
+
+ def set_visible(self, visible):
+ """Set the Message representation of visible headers."""
+ self._visible = Message(visible)
+
+ def update_visible(self):
+ """Update and/or sensibly generate a set of visible headers."""
+ for header in self._visible.keys():
+ if header in self:
+ self._visible.replace_header(header, self[header])
+ else:
+ del self._visible[header]
+ for header in ('Date', 'From', 'Reply-To', 'To', 'CC', 'Subject'):
+ if header in self and header not in self._visible:
+ self._visible[header] = self[header]
+
+ def _explain_to(self, message):
+ """Copy Babyl-specific state to message insofar as possible."""
+ if isinstance(message, MaildirMessage):
+ labels = set(self.list_labels())
+ if 'unseen' in labels:
+ message.set_subdir('cur')
+ else:
+ message.set_subdir('cur')
+ message.add_flags('S')
+ if 'forwarded' in labels or 'resent' in labels:
+ message.add_flags('P')
+ if 'answered' in labels:
+ message.add_flags('R')
+ if 'deleted' in labels:
+ message.add_flags('T')
+ elif isinstance(message, _mboxMMDFMessage):
+ labels = set(self.list_labels())
+ if 'unseen' not in labels:
+ message.add_flags('RO')
+ else:
+ message.add_flags('O')
+ if 'deleted' in labels:
+ message.add_flags('D')
+ if 'answered' in labels:
+ message.add_flags('A')
+ elif isinstance(message, MHMessage):
+ labels = set(self.list_labels())
+ if 'unseen' in labels:
+ message.join_sequence('unseen')
+ if 'answered' in labels:
+ message.join_sequence('replied')
+ elif isinstance(message, BabylMessage):
+ message.set_visible(self.get_visible())
+ for label in self.list_labels():
+ message.add_label(label)
+ elif isinstance(message, Message):
+ pass
else:
raise TypeError, "Cannot convert to specified type"
+class MMDFMessage(_mboxMMDFMessage):
+ """Message with MMDF-specific properties."""
+
+
class _ProxyFile:
"""A read-only wrapper of a file."""
Index: libmailbox.tex
===================================================================
RCS file: /cvsroot/python/python/nondist/sandbox/mailbox/libmailbox.tex,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- libmailbox.tex 26 Jul 2005 20:47:48 -0000 1.2
+++ libmailbox.tex 30 Jul 2005 22:49:08 -0000 1.3
@@ -29,7 +29,6 @@
in a mailbox, the modified message representation must be explicitly assigned
back into the \class{Mailbox} instance's mapping.
-
\begin{seealso}
\seemodule{email}{Represent and manipulate messages.}
\seemodule{poplib}{Access mail via POP3.}
@@ -37,12 +36,11 @@
\seemodule{smtplib}{Transfer mail via SMTP.}
\end{seealso}
-
\subsection{\class{Mailbox} objects}
\label{mailbox-objects}
\begin{classdesc*}{Mailbox}
-Represents a mailbox, which may be inspected and modified.
+A mailbox, which may be inspected and modified.
\end{classdesc*}
The \class{Mailbox} interface is dictionary-like, with small keys
@@ -107,7 +105,7 @@
\class{Mailbox} instances have the following methods:
-\begin{methoddesc}[Mailbox]{add}{message}
+\begin{methoddesc}{add}{message}
Add \var{message} to the mailbox and return the key that has been assigned to
it.
@@ -119,7 +117,7 @@
Otherwise, reasonable defaults for format-specific information are used.
\end{methoddesc}
-\begin{methoddesc}[Mailbox]{remove}{key}
+\begin{methoddesc}{remove}{key}
\methodline{__delitem__}{key}
\methodline{discard}{key}
Delete the message corresponding to \var{key} from the mailbox.
@@ -131,7 +129,7 @@
format supports concurrent modification by other processes.
\end{methoddesc}
-\begin{methoddesc}[Mailbox]{__setitem__}{key, message}
+\begin{methoddesc}{__setitem__}{key, message}
Replace the message corresponding to \var{key} with the message represented by
\var{message}. Raise a \exception{KeyError} exception if no message already
corresponds to \var{key}.
@@ -145,13 +143,13 @@
corresponds to \var{key} is left unchanged.
\end{methoddesc}
-\begin{methoddesc}[Mailbox]{iterkeys}{}
+\begin{methoddesc}{iterkeys}{}
\methodline{keys}{}
Return an iterator over all keys if called as \method{iterkeys()} or return a
list of keys if called as \method{keys()}.
\end{methoddesc}
-\begin{methoddesc}[Mailbox]{itervalues}{}
+\begin{methoddesc}{itervalues}{}
\methodline{__iter__}{}
\methodline{values}{}
Return an iterator over representations of all messages if called as
@@ -162,7 +160,7 @@
\method{__iter__()} is unlike that of dictionaries, which iterate over keys.}
\end{methoddesc}
-\begin{methoddesc}[Mailbox]{iteritems}{}
+\begin{methoddesc}{iteritems}{}
\methodline{items}{}
Return an iterator over (\var{key}, \var{message}) pairs, where \var{key} is a
key and \var{message} is a message representation, if called as
@@ -172,7 +170,7 @@
was initialized.
\end{methoddesc}
-\begin{methoddesc}[Mailbox]{get}{key\optional{, default=None}}
+\begin{methoddesc}{get}{key\optional{, default=None}}
\methodline{__getitem__}{key}
Return a representation of the message corresponding to \var{key}. If no such
message exists, \var{default} is returned if the method was called as
@@ -182,18 +180,18 @@
\class{Mailbox} instance was initialized.
\end{methoddesc}
-\begin{methoddesc}[Mailbox]{get_message}{key}
+\begin{methoddesc}{get_message}{key}
Return a \class{Message} representation of the message corresponding to
\var{key}, or raise a \exception{KeyError} exception if no such message
exists.
\end{methoddesc}
-\begin{methoddesc}[Mailbox]{get_string}{key}
+\begin{methoddesc}{get_string}{key}
Return a string representation of the message corresponding to \var{key}, or
raise a \exception{KeyError} exception if no such message exists.
\end{methoddesc}
-\begin{methoddesc}[Mailbox]{get_file}{key}
+\begin{methoddesc}{get_file}{key}
Return a file-like representation of the message corresponding to \var{key},
or raise a \exception{KeyError} exception if no such message exists. This file
should be closed once it is no longer needed.
@@ -204,21 +202,21 @@
More specific documentation is provided by each subclass.}
\end{methoddesc}
-\begin{methoddesc}[Mailbox]{has_key}{key}
+\begin{methoddesc}{has_key}{key}
\methodline{__contains__}{}
Return \code{True} if \var{key} corresponds to a message, \code{False}
otherwise.
\end{methoddesc}
-\begin{methoddesc}[Mailbox]{__len__}{}
+\begin{methoddesc}{__len__}{}
Return a count of messages in the mailbox.
\end{methoddesc}
-\begin{methoddesc}[Mailbox]{clear}{}
+\begin{methoddesc}{clear}{}
Delete all messages from the mailbox.
\end{methoddesc}
-\begin{methoddesc}[Mailbox]{pop}{key\optional{, default}}
+\begin{methoddesc}{pop}{key\optional{, default}}
Return a representation of the message corresponding to \var{key} and delete
the message. If no such message exists, return \var{default} if it was supplied
or else raise a \exception{KeyError} exception. The message is represented as a
@@ -226,7 +224,7 @@
\class{Mailbox} instance was initialized.
\end{methoddesc}
-\begin{methoddesc}[Mailbox]{popitem}{}
+\begin{methoddesc}{popitem}{}
Return an arbitrary (\var{key}, \var{message}) pair, where \var{key} is a key
and \var{message} is a message representation, and delete the corresponding
message. If the mailbox is empty, raise a \exception{KeyError} exception. The
@@ -234,7 +232,7 @@
factory was specified when the \class{Mailbox} instance was initialized.
\end{methoddesc}
-\begin{methoddesc}[Mailbox]{update}{arg}
+\begin{methoddesc}{update}{arg}
Parameter \var{arg} should be a \var{key}-to-\var{message} mapping or an
iterable of (\var{key}, \var{message}) pairs. Updates the mailbox so that, for
each given \var{key} and \var{message}, the message corresponding to \var{key}
@@ -244,7 +242,7 @@
are not supported.}
\end{methoddesc}
-\begin{methoddesc}[Mailbox]{flush}{}
+\begin{methoddesc}{flush}{}
Write any pending changes to the filesystem. For some \class{Mailbox}
subclasses, this is done automatically and calling \method{flush()} has no
effect. More specific documentation is provided by each subclass.
@@ -277,23 +275,23 @@
\class{Maildir} instances have all of the methods of \class{Mailbox} in
addition to the following:
-\begin{methoddesc}[Maildir]{list_folders}{}
+\begin{methoddesc}{list_folders}{}
Return a list of the names of all folders. If there are no folders, the empty
list is returned.
\end{methoddesc}
-\begin{methoddesc}[Maildir]{open_folder}{name}
+\begin{methoddesc}{open_folder}{name}
Return a \class{Maildir} instance representing the folder whose name is
\var{name}. The folder will be created if it does not exist.
\end{methoddesc}
-\begin{methoddesc}[Maildir]{remove_folder}{name}
+\begin{methoddesc}{remove_folder}{name}
Delete the folder whose name is \var{name}. If the folder contains any
messages, an \exception{IOError} exception will be raised and the folder will
not be deleted.
\end{methoddesc}
-\begin{methoddesc}[Maildir]{clean}{}
+\begin{methoddesc}{clean}{}
Delete temporary files from the mailbox that have not been accessed in the
last 36 hours. The Maildir specification says that mail-reading programs
should do this occassionally.
@@ -307,9 +305,9 @@
simultaneously.}
Some \class{Mailbox} methods implemented by \class{Maildir} deserve special
-remarks:
+remarks:
-\begin{methoddesc}[Maildir]{add}{message}
+\begin{methoddesc}{add}{message}
\methodline[Maildir]{__setitem__}{key, message}
\methodline[Maildir]{update}{arg}
\warning{These methods generate unique file names based upon the current
@@ -318,12 +316,12 @@
these methods to manipulate the same mailbox simultaneously.}
\end{methoddesc}
-\begin{methoddesc}[Maildir]{flush}{}
+\begin{methoddesc}{flush}{}
All changes to Maildir mailboxes are immediately applied. This method does
nothing.
\end{methoddesc}
-\begin{methoddesc}[Maildir]{get_file}{key}
+\begin{methoddesc}{get_file}{key}
Depending upon the host platform, it may not be possible to use a
\class{Maildir} instance to modify or remove the underlying message while the
returned file remains open.
@@ -343,18 +341,205 @@
\subsubsection{\class{mbox}}
\label{mailbox-mbox}
+\begin{classdesc}{mbox}{path\optional{, factory}}
+A subclass of \class{Mailbox} for mailboxes in mbox format. Parameters
+\var{path} and \var{factory} has the same meaning as with the module-level
+\method{open()} function.
+\end{classdesc}
+
+The mbox format is the classic format for storing mail on \UNIX{} systems. All
+messages in an mbox mailbox are stored in a single file with the beginning of
+each message indicated by a line whose first five characters are "From~".
+Several variations of the mbox format exist to address perceived shortcomings.
+In the interest of compatibility, \class{mbox} implements the original format,
+which is sometimes referred to as \dfn{mboxo}. This means that the
+\mailheader{Content-Length} header, if present, is ignored and that any
+occurrences of "From~" at the beginning of a line in a message body are
+transformed to ">From~" when storing the message although occurences of
+">From~" are not transformed to "From~" when reading the message.
+
+Some \class{Mailbox} methods implemented by \class{mbox} deserve special
+remarks:
+
+\begin{methoddesc}{get_file}{key}
+XXX
+\end{methoddesc}
+
+\begin{seealso}
+ \seelink{http://www.qmail.org/man/man5/mbox.html}{mbox man page from
+ qmail}{A specification of the format and its variations.}
+ \seelink{http://home.netscape.com/eng/mozilla/2.0/relnotes/demo/content-length.html}
+ {Configuring Netscape Mail on \UNIX{}: Why The Content-Length Format is
+ Bad}{An argument for using the original mbox format rather than a
+ variation.}
+ \seelink{http://homepages.tesco.net./\tilde{}J.deBoynePollard/FGA/mail-mbox-formats.html}
+ {"mbox" is a family of several mutually incompatible mailbox formats}{A
+ history of mbox variations.}
+\end{seealso}
\subsubsection{\class{MH}}
\label{mailbox-mh}
+\begin{classdesc}{MH}{path\optional{, factory}}
+A subclass of \class{Mailbox} for mailboxes in MH format. Parameters \var{path}
+and \var{factory} has the same meaning as with the module-level \method{open()}
+function.
+\end{classdesc}
+
+MH is a directory-based mailbox format invented for the MH Message Handling
+System, a mail reading application. Each message in an MH mailbox resides in
+its own file. An MH mailbox may contain other MH mailboxes (called
+\dfn{folders}) in addition to messages. Folders may be nested indefinitely.
+
+MH mailboxes support \dfn{sequences}, which are named lists used to logically
+group messages without moving them to sub-folders. Some mail reading programs
+(although not the standard \program{mh} and \program{nmh} implementations) use
+sequences to the same end as flags are used in other formats: unread messages
+are added to the "unseen" sequence, replied-to messages are added to the
+"replied" sequence, and important messages are added upon request to the
+"flagged" sequence.
+
+\class{MH} instances have all of the methods of \class{Mailbox} in addition to
+the following:
+
+\begin{methoddesc}{list_folders}{}
+Return a list of the names of all folders. If there are no folders, the empty
+list is returned.
+\end{methoddesc}
+
+\begin{methoddesc}{open_folder}{name}
+Return an \class{MH} instance representing the folder whose name is \var{name}.
+The folder will be created if it does not exist.
+\end{methoddesc}
+
+\begin{methoddesc}{remove_folder}{name}
+Delete the folder whose name is \var{name}. If the folder contains any
+messages, an \exception{IOError} exception will be raised and the folder will
+not be deleted.
+\end{methoddesc}
+
+\begin{methoddesc}{list_sequences}{}
+Return a list of the names of sequences defined in the mailbox. If there are no
+sequences, the empty list is returned.
+\end{methoddesc}
+
+\begin{methoddesc}{get_sequence}{name}
+Return a list of keys in sequence \var{name}.
+\end{methoddesc}
+
+\begin{methoddesc}{set_sequence}{name, value}
+Set to \var{value} the list of keys in sequence \var{name}. The sequence will
+be created if it does not exist. If \var{value} is the empty list, sequence
+\var{name} will be removed.
+\end{methoddesc}
+
+\begin{methoddesc}{pack}{}
+Renames messages in the mailbox as necessary to eliminate gaps in numbering.
+Already-issued keys are invalidated by this operation.
+\end{methoddesc}
+
+Some \class{Mailbox} methods implemented by \class{MH} deserve special remarks:
+
+\begin{methoddesc}{remove}{key}
+\methodline{__delitem__}{key}
+\methodline{discard}{key}
+These methods immediately delete the message. The \program{mh} convention of
+marking a message for deletion by prepending a comma to its name is not used.
+\end{methoddesc}
+
+\begin{methoddesc}{get_file}{key}
+XXX
+\end{methoddesc}
+
+\begin{methoddesc}{flush}{}
+All changes to MH mailboxes are immediately applied. This method does nothing.
+\end{methoddesc}
+
+\begin{classdesc}{MH}{path\optional{, factory}}
+A subclass of \class{Mailbox} for mailboxes in MH format. Parameters \var{path}
+and \var{factory} has the same meaning as with the module-level \method{open()}
+function.
+\end{classdesc}
+
+\class{MH} instances have all of the methods of \class{Mailbox} in addition to
+the following:
+
+Some \class{Mailbox} methods implemented by \class{MH} deserve special remarks:
+
+\begin{methoddesc}{get_file}{key}
+XXX
+\end{methoddesc}
+
+\begin{seealso}
+\seelink{http://www.nongnu.org/nmh/}{nmh - Message Handling System}{Home page
+of \program{nmh}, a modern version of the original \program{mh}.}
+\seelink{http://www.ics.uci.edu/\tilde{}mh/book/}{MH \& nmh: Email for Users \&
+Programmers}{An open-source book on \program{mh} and \program{nmh}, with some
+information on the mailbox format.}
+\end{seealso}
\subsubsection{\class{Babyl}}
\label{mailbox-babyl}
+\begin{classdesc}{Babyl}{path\optional{, factory}}
+A subclass of \class{Mailbox} for mailboxes in Babyl format. Parameters
+\var{path} and \var{factory} has the same meaning as with the module-level
+\method{open()} function.
+\end{classdesc}
+
+Babyl is a single-file mailbox format invented for use with the Rmail mail
+reading application that ships with Emacs. A Babyl mailbox begins with a
+so-called options section that indicates the format of the mailbox. Messages
+follow the options section, with the beginning and end of each message
+indicated by control characters. Each message in a Babyl mailbox has an
+accompanying list of \dfn{labels}, or short strings that record extra
+information about the message.
+
+Some \class{Mailbox} methods implemented by \class{Babyl} deserve special
+remarks:
+
+\begin{methoddesc}{get_file}{key}
+XXX
+\end{methoddesc}
+
+\begin{seealso}
+\seelink{http://quimby.gnus.org/notes/BABYL}{Format of Version 5 Babyl Files}{A
+specification of the Babyl format.}
+\seelink{http://www.gnu.org/software/emacs/manual/html_node/Rmail.html}{Reading
+Mail with Rmail}{The Rmail manual, with some information on Babyl semantics.}
+\end{seealso}
\subsubsection{\class{MMDF}}
\label{mailbox-mmdf}
+\begin{classdesc}{MMDF}{path\optional{, factory}}
+A subclass of \class{Mailbox} for mailboxes in MMDF format. Parameters
+\var{path} and \var{factory} has the same meaning as with the module-level
+\method{open()} function.
+\end{classdesc}
+
+MMDF is a single-file mailbox format invented for the Multichannel Memorandum
+Distribution Facility, a mail transfer agent. Each message is in the same form
+as an mbox message but is bracketed before and after by lines containing four
+Control-A characters. As with the mbox format, the beginning of each message
+indicated by a line whose first five characters are "From~", but because of the
+additional message separators it is unnecessary to transform "From~" to
+">From~" when storing messages.
+
+Some \class{Mailbox} methods implemented by \class{MMDF} deserve special
+remarks:
+
+\begin{methoddesc}{get_file}{key}
+XXX
+\end{methoddesc}
+
+\begin{seealso}
+\seelink{http://www.tin.org/bin/man.cgi?section=5\&topic=mmdf}{mmdf man page
+from tin}{A specification of MMDF format from the documentation of tin, a
+newsreader.}
+\seelink{http://en.wikipedia.org/wiki/MMDF}{MMDF}{A Wikipedia article
+describing the Multichannel Memorandum Distribution Facility.}
+\end{seealso}
\subsection{\class{Message} objects}
\label{mailbox-message-objects}
@@ -364,7 +549,7 @@
support mailbox-format-specific state and behavior.
\begin{classdesc}{Message}{\optional{message}}
-Represents a message with mailbox-format-specific properties.
+A message with mailbox-format-specific properties.
If \var{message} is omitted, the new instance is created in a default, empty
state. If \var{message} is an \class{email.Message.Message} instance, its
@@ -400,19 +585,22 @@
\label{mailbox-maildirmessage}
\begin{classdesc}{MaildirMessage}{\optional{message}}
-Represents a message with Maildir-specific behaviors. Parameter \var{message}
+A message with Maildir-specific behaviors. Parameter \var{message}
has the same meaning as with the \class{Message} constructor.
\end{classdesc}
Maildir messages are stored in individual files, in either the \file{new} or
-the \file{cur} subdirectory of the Maildir. Typically, messages are delivered
-to the \file{new} subdirectory and then moved to the \file{cur} subdirectory
-as soon as the user's mail reading application detects them. Each message in
-\file{cur} has an "info" section added to its file name to store information
-about its state. The "info" section may take one of two forms: it may contain
-a standardized list of flags or it may contain so-called experimental
-information.
+the \file{cur} subdirectory of the Maildir. Messages are delivered to the
+\file{new} subdirectory. Typically, a mail reading application moves messages
+to the \file{cur} subdirectory after the user opens and closes the mailbox,
+thereby recording that the messages are old whether or not they've actually
+been read.
+Each message in \file{cur} has an "info" section added to its file name to
+store information about its state. (Some mail readers may also add an "info"
+section to messages in \file{new}.) The "info" section may take one of two
+forms: it may contain "2," followed by a list of standardized flags (e.g.,
+"2,FR") or it may contain "1," followed by so-called experimental information.
Standard flags for Maildir messages are as follows:
\begin{tableiii}{l|l|l}{textrm}{Flag}{Meaning}{Explanation}
@@ -426,81 +614,507 @@
\class{MaildirMessage} instances offer the following methods:
-\begin{methoddesc}[MaildirMessage]{get_subdir}{}
+\begin{methoddesc}{get_subdir}{}
Return either "new" (if the message should be stored in the \file{new}
subdirectory) or "cur" (if the message should be stored in the \file{cur}
-subdirectory). \note{A Maildir message typically moves from \file{new} to
-\file{cur} when an MUA first detects it, but most MUAs refer to a message as
-new if it is unseen, i.e., if \code{"S" in get_flags()} is \code{False}.}
+subdirectory). \note{A message is typically moved from \file{new} to \file{cur}
+after its mailbox has been accessed, whether or not the message is has been
+read. A message has been read if \code{"S" not in get_flags()}.}
\end{methoddesc}
-\begin{methoddesc}[MaildirMessage]{set_subdir}{subdir}
+\begin{methoddesc}{set_subdir}{subdir}
Set the subdirectory the message should be stored in. Parameter \var{subdir}
must be either "new" or "cur".
\end{methoddesc}
-\begin{methoddesc}[MaildirMessage]{get_flags}{}
+\begin{methoddesc}{get_flags}{}
Return a string specifying the flags that are currently set. If the message
complies with the standard Maildir format, the result is the concatenation in
alphabetical order of zero or one occurrence of each of \character{D},
\character{F}, \character{P}, \character{R}, \character{S}, and \character{T}.
-The empty string is returned if no flags are set, if the message is new, or if
-"info" contains experimental semantics.
+The empty string is returned if no flags are set or if "info" contains
+experimental semantics.
\end{methoddesc}
-\begin{methoddesc}[MaildirMessage]{set_flags}{flags}
+\begin{methoddesc}{set_flags}{flags}
Set the flags specified by \var{flags} and unset all others. Parameter
\var{flags} should be the concatenation in any order of zero or more
occurrences of each of \character{D}, \character{F}, \character{P},
-\character{R}, \character{S}, and \character{T}. If the message is new, it
-is made non-new. The current "info" is overwritten whether or not it contains
-experimental information instead of flags.
+\character{R}, \character{S}, and \character{T}. The current "info" is
+overwritten whether or not it contains experimental information instead of
+flags.
\end{methoddesc}
-\begin{methoddesc}[MaildirMessage]{add_flags}{flags}
+\begin{methoddesc}{add_flags}{flags}
Set the flags specified by \var{flags} (if they are not set), and don't change
other flags. Parameter \var{flags} should be the concatenation in any order of
zero or more occurrences of each of \character{D}, \character{F},
-\character{P}, \character{R}, \character{S}, and \character{T}. If the message
-is new, it is made non-new. If "info" contains experimental information rather
-than flags, the "info" will be overwritten.
+\character{P}, \character{R}, \character{S}, and \character{T}. The current
+"info" is overwritten whether or not it contains experimental information
+instead of flags.
\end{methoddesc}
-\begin{methoddesc}[MaildirMessage]{remove_flags}{flags}
+\begin{methoddesc}{remove_flags}{flags}
Unset the flags specified by \var{flags} (if they are set), and don't change
other flags. Parameter \var{flags} should be the concatenation in any order of
zero or more occurrences of each of \character{D}, \character{F},
-\character{P}, \character{R}, \character{S}, and \character{T}. If the message
-is new, it remains so. If "info" contains experimental information rather than
-flags, the current "info" is not modified.
+\character{P}, \character{R}, \character{S}, and \character{T}. If "info"
+contains experimental information rather than flags, the current "info" is not
+modified.
\end{methoddesc}
-\begin{methoddesc}[MaildirMessage]{get_info}{}
+\begin{methoddesc}{get_info}{}
Return a string containing the "info" for a message. This is useful for
accessing and modifying "info" that is experimental (i.e., not a list of
flags).
\end{methoddesc}
-\begin{methoddesc}[MaildirMessage]{set_info}{info}
-Set "info" to \var{info}, which should be a string. If the message is new, it
-is made non-new.
+\begin{methoddesc}{set_info}{info}
+Set "info" to \var{info}, which should be a string.
\end{methoddesc}
+When a \class{MaildirMessage} instance is created based upon an
+\class{mboxMessage} or \class{MMDFMessage} instance, the \mailheader{Status}
+and \mailheader{X-Status} headers are omitted and the following conversions
+take place:
+
+\begin{tableii}{l|l}{textrm}
+ {Resulting state}{\class{mboxMessage} or \class{MMDFMessage} state}
+\lineii{"cur" subdirectory}{O flag}
+\lineii{F flag}{F flag}
+\lineii{R flag}{A flag}
+\lineii{S flag}{R flag}
+\lineii{T flag}{D flag}
+\end{tableii}
+
+When a \class{MaildirMessage} instance is created based upon an
+\class{MHMessage} instance, the following conversions take place:
+
+\begin{tableii}{l|l}{textrm}
+ {Resulting state}{\class{MHMessage} state}
+\lineii{"cur" subdirectory}{"unseen" sequence}
+\lineii{"cur" subdirectory and S flag}{no "unseen" sequence}
+\lineii{F flag}{"flagged" sequence}
+\lineii{R flag}{"replied" sequence}
+\end{tableii}
+
+When a \class{MaildirMessage} instance is created based upon a
+\class{BabylMessage} instance, the following conversions take place:
+
+\begin{tableii}{l|l}{textrm}
+ {Resulting state}{\class{BabylMessage} state}
+\lineii{"cur" subdirectory}{"unseen" label}
+\lineii{"cur" subdirectory and S flag}{no "unseen" label}
+\lineii{P flag}{"forwarded" or "resent" label}
+\lineii{R flag}{"answered" label}
+\lineii{T flag}{"deleted" label}
+\end{tableii}
+
\subsubsection{\class{mboxMessage}}
\label{mailbox-mboxmessage}
+\begin{classdesc}{mboxMessage}{\optional{message}}
+A message with mbox-specific behaviors. Parameter \var{message} has the same
+meaning as with the \class{Message} constructor.
+\end{classdesc}
+
+Messages in an mbox mailbox are stored together in a single file. The sender's
+envelope address and the time of delivery are typically stored in a line
+beginning with "From~" that is used to indicate the start of a message, though
+there is considerable variation in the exact format of this data among mbox
+implementations. Flags that indicate the state of the message, such as whether
+it has been read or marked as important, are typically stored in
+\mailheader{Status} and \mailheader{X-Status} headers.
+
+Conventional flags for mbox messages are as follows:
+
+\begin{tableiii}{l|l|l}{textrm}{Flag}{Meaning}{Explanation}
+\lineiii{R}{Read}{Read by the user}
+\lineiii{O}{Old}{Previously detected by mail reader}
+\lineiii{D}{Deleted}{Marked for subsequent deletion}
+\lineiii{F}{Flagged}{Marked by the user as important}
+\lineiii{A}{Answered}{Responded to}
+\end{tableiii}
+
+The "R" and "O" flags are stored in the \mailheader{Status} header, and the
+"D", "F", and "A" flags are stored in the \mailheader{X-Status} header. The
+flags and headers typically appear in the order mentioned.
+
+\class{mboxMessage} instances offer the following methods:
+
+\begin{methoddesc}{get_from}{}
+Return a string representing the "From~" line that marks the start of the
+message in an mbox mailbox. The leading "From~" and the trailing newline are
+excluded.
+\end{methoddesc}
+
+\begin{methoddesc}{set_from}{from_\optional{, time_=None}}
+Set the "From~" line to \var{from_}, which should be specified without a
+leading "From~" or trailing newline. If \var{time_} is specified, it should be
+a \class{struct_time} or a tuple suitable for passing to
+\method{time.strftime()}; if \var{time_} is \code{True}, the result of
+\method{time.gmtime()} is used.
+\end{methoddesc}
+
+\begin{methoddesc}{get_flags}{}
+Return a string specifying the flags that are currently set. If the message
+complies with the conventional format, the result is the concatenation in the
+following order of zero or one occurrence of each of \character{R},
+\character{O}, \character{D}, \character{F}, and \character{A}.
+\end{methoddesc}
+
+\begin{methoddesc}{set_flags}{flags}
+Set the flags specified by \var{flags} and unset all others. Parameter
+\var{flags} should be the concatenation in any order of zero or more
+occurrences of each of \character{R}, \character{O}, \character{D},
+\character{F}, and \character{A}.
+\end{methoddesc}
+
+\begin{methoddesc}{add_flags}{flags}
+Set the flags specified by \var{flags} (if they are not set), and don't change
+other flags. Parameter \var{flags} should be the concatenation in any order of
+zero or more occurrences of each of \character{R}, \character{O},
+\character{D}, \character{F}, and \character{A}.
+\end{methoddesc}
+
+\begin{methoddesc}{remove_flags}{flags}
+Unset the flags specified by \var{flags} (if they are set), and don't change
+other flags. Parameter \var{flags} should be the concatenation in any order of
+zero or more occurrences of each of \character{R}, \character{O},
+\character{D}, \character{F}, and \character{A}.
+\end{methoddesc}
+
+When an \class{mboxMessage} instance is created based upon a
+\class{MaildirMessage} instance, the following conversions take place:
+
+\begin{tableii}{l|l}{textrm}
+ {Resulting state}{\class{MaildirMessage} state}
+\lineii{R flag}{S flag}
+\lineii{O flag}{"cur" subdirectory}
+\lineii{D flag}{T flag}
+\lineii{F flag}{F flag}
+\lineii{A flag}{R flag}
+\end{tableii}
+
+When an \class{mboxMessage} instance is created based upon an \class{MHMessage}
+instance, the following conversions take place:
+
+\begin{tableii}{l|l}{textrm}
+ {Resulting state}{\class{MHMessage} state}
+\lineii{R flag and O flag}{no "unseen" sequence}
+\lineii{O flag}{"unseen" sequence}
+\lineii{F flag}{"flagged" sequence}
+\lineii{A flag}{"replied" sequence}
+\end{tableii}
+
+When an \class{mboxMessage} instance is created based upon a
+\class{BabylMessage} instance, the following conversions take place:
+
+\begin{tableii}{l|l}{textrm}
+ {Resulting state}{\class{BabylMessage} state}
+\lineii{R flag and O flag}{no "unseen" label}
+\lineii{O flag}{"unseen" label}
+\lineii{D flag}{"deleted" label}
+\lineii{A flag}{"answered" label}
+\end{tableii}
+
+When a \class{Message} instance is created based upon an \class{MMDFMessage}
+instance, the "From~" line is copied and all flags directly correspond:
+
+\begin{tableii}{l|l}{textrm}
+ {Resulting state}{\class{MMDFMessage} state}
+\lineii{R flag}{R flag}
+\lineii{O flag}{O flag}
+\lineii{D flag}{D flag}
+\lineii{F flag}{F flag}
+\lineii{A flag}{A flag}
+\end{tableii}
\subsubsection{\class{MHMessage}}
\label{mailbox-mhmessage}
+\begin{classdesc}{MHMessage}{\optional{message}}
+A message with MH-specific behaviors. Parameter \var{message} has the same
+meaning as with the \class{Message} constructor.
+\end{classdesc}
+
+MH messages do not support marks or flags in the traditional sense, but they do
+support sequences, which are logical groupings of arbitrary messages. Because
+sequences are often used to indicate the state of a messsage, they are
+maintained by the \class{MHMessage} class even though they are not, strictly
+speaking, a property of the message itself.
+
+Some mail user agents make use of sequences to record message state as follows:
+
+\begin{tableii}{l|l}{textrm}{Sequence}{Explanation}
+\lineii{unseen}{Previously detected by mail reader but not read}
+\lineii{replied}{Responded to}
+\lineii{flagged}{Marked by the user as important}
+\end{tableii}
+
+\class{MHMessage} instances offer the following methods:
+
+\begin{methoddesc}{list_sequences}{}
+Return a list of the names of sequences that include the message.
+\end{methoddesc}
+
+\begin{methoddesc}{join_sequence}{sequence}
+Add \var{sequence} to the list of sequences that include the message.
+\end{methoddesc}
+
+\begin{methoddesc}{leave_sequence}{sequence}
+Remove \var{sequence} from the list of sequences that include the message.
+\end{methoddesc}
+
+When an \class{MHMessage} instance is created based upon a
+\class{MaildirMessage} instance, the following conversions take place:
+
+\begin{tableii}{l|l}{textrm}
+ {Resulting state}{\class{MaildirMessage} state}
+\lineii{"unseen" sequence}{no S flag}
+\lineii{"replied" sequence}{R flag}
+\lineii{"flagged" sequence}{F flag}
+\end{tableii}
+
+When an \class{MHMessage} instance is created based upon an \class{mboxMessage}
+or \class{MMDFMessage} instance, the \mailheader{Status} and
+\mailheader{X-Status} headers are omitted and the following conversions take
+place:
+
+\begin{tableii}{l|l}{textrm}
+ {Resulting state}{\class{mboxMessage} or \class{MMDFMessage} state}
+\lineii{"unseen" sequence}{no R flag}
+\lineii{"replied" sequence}{A flag}
+\lineii{"flagged" sequence}{F flag}
+\end{tableii}
+
+When an \class{MHMessage} instance is created based upon a \class{BabylMessage}
+instance, the following conversions take place:
+
+\begin{tableii}{l|l}{textrm}
+ {Resulting state}{\class{BabylMessage} state}
+\lineii{"unseen" sequence}{"unseen" label}
+\lineii{"replied" sequence}{"answered" label}
+\end{tableii}
\subsubsection{\class{BabylMessage}}
\label{mailbox-babylmessage}
+\begin{classdesc}{BabylMessage}{\optional{message}}
+A message with Babyl-specific behaviors. Parameter \var{message} has the same
+meaning as with the \class{Message} constructor.
+\end{classdesc}
+
+Information about Babyl messages is recorded using \dfn{labels}, or short
+strings which are stored in an MH mailbox just before each message. Some
+labels are assigned special meaning and are called \dfn{attributes}. Other
+labels are user-defined. The attributes are as follows:
+
+\begin{tableii}{l|l}{textrm}{Label}{Explanation}
+\lineii{unseen}{Previously detected by mail reader but not read}
+\lineii{deleted}{Marked for subsequent deletion}
+\lineii{filed}{Copied to another file or mailbox}
+\lineii{answered}{Responded to}
+\lineii{forwarded}{Forwarded by the the user}
+\lineii{edited}{Message content modified by the user}
+\lineii{resent}{Resent by the user}
+\end{tableii}
+
+Each message in a Babyl mailbox has two sets of headers, original headers and
+visible headers. Visible headers are typically a subset of the original
+headers reformatted to be more attractive. By default, \program{rmail} displays
+only visible headers. \class{BabylMessage} uses the original headers because
+they are more complete, though the visible headers may be accessed explicitly
+if desired.
+
+\class{BabylMessage} instances offer the following methods:
+
+\begin{methoddesc}{list_labels}{}
+Return a list of labels on the message.
+\end{methoddesc}
+
+\begin{methoddesc}{add_label}{label}
+Add \var{label} to the list of labels on the message.
+\end{methoddesc}
+
+\begin{methoddesc}{remove_label}{label}
+Remove \var{label} from the list of labels on the message.
+\end{methoddesc}
+
+\begin{methoddesc}{get_visible}{}
+Return an \class{Message} instance whose headers are the message's visible
+headers and whose body is empty.
+\end{methoddesc}
+
+\begin{methoddesc}{set_visible}{visible}
+Set the message's visible headers to be the same as the headers in
+\var{message}. Parameter \var{visible} should be a \class{Message} instance, an
+\class{email.Message.Message} instance, a string, or a file-like object.
+\end{methoddesc}
+
+\begin{methoddesc}{update_visible}{}
+When a \class{BabylMessage} instance's original headers are modified, the
+visible headers are not automatically modified to correspond. This method
+updates the visible headers as follows: each visible header with a
+corresponding original header is set to the value of the original header, each
+visible header without a corresponding original header is removed, and any of
+\mailheader{Date}, \mailheader{From}, \mailheader{Reply-To}, \mailheader{To},
+\mailheader{CC}, and \mailheader{Subject} that are present in the original
+headers but not the visible headers are added to the visible headers.
+\end{methoddesc}
+
+When a \class{BabylMessage} instance is created based upon a
+\class{MaildirMessage} instance, the following conversions take place:
+
+\begin{tableii}{l|l}{textrm}
+ {Resulting state}{\class{MaildirMessage} state}
+\lineii{"unseen" label}{no S flag}
+\lineii{"deleted" label}{T flag}
+\lineii{"answered" label}{R flag}
+\lineii{"forwarded" label}{P flag}
+\end{tableii}
+
+When a \class{BabylMessage} instance is created based upon an
+\class{mboxMessage} or \class{MMDFMessage} instance, the \mailheader{Status}
+and \mailheader{X-Status} headers are omitted and the following conversions
+take place:
+
+\begin{tableii}{l|l}{textrm}
+ {Resulting state}{\class{mboxMessage} or \class{MMDFMessage} state}
+\lineii{"unseen" label}{no R flag}
+\lineii{"deleted" label}{D flag}
+\lineii{"answered" label}{A flag}
+\end{tableii}
+
+When a \class{BabylMessage} instance is created based upon an \class{MHMessage}
+instance, the following conversions take place:
+
+\begin{tableii}{l|l}{textrm}
+ {Resulting state}{\class{MHMessage} state}
+\lineii{"unseen" label}{"unseen" sequence}
+\lineii{"answered" label}{"replied" sequence}
+\end{tableii}
\subsubsection{\class{MMDFMessage}}
\label{mailbox-mmdfmessage}
+\begin{classdesc}{MMDFMessage}{\optional{message}}
+A message with MMDF-specific behaviors. Parameter \var{message} has the same
+meaning as with the \class{Message} constructor.
+\end{classdesc}
+
+As with message in an mbox mailbox, MMDF messages are stored with the sender's
+address and the delivery date in an initial line beginning with "From ".
+Likewise, flags that indicate the state of the message are typically stored in
+\mailheader{Status} and \mailheader{X-Status} headers.
+
+Conventional flags for MMDF messages are identical to those of mbox message and
+are as follows:
+
+\begin{tableiii}{l|l|l}{textrm}{Flag}{Meaning}{Explanation}
+\lineiii{R}{Read}{Read by the user}
+\lineiii{O}{Old}{Previously detected by mail reader}
+\lineiii{D}{Deleted}{Marked for subsequent deletion}
+\lineiii{F}{Flagged}{Marked by the user as important}
+\lineiii{A}{Answered}{Responded to}
+\end{tableiii}
+
+The "R" and "O" flags are stored in the \mailheader{Status} header, and the
+"D", "F", and "A" flags are stored in the \mailheader{X-Status} header. The
+flags and headers typically appear in the order mentioned.
+
+\class{MMDFMessage} instances offer the following methods, which are identical
+to those offered by \class{mboxMessage}:
+
+\begin{methoddesc}{get_from}{}
+Return a string representing the "From~" line that marks the start of the
+message in an mbox mailbox. The leading "From~" and the trailing newline are
+excluded.
+\end{methoddesc}
+
+\begin{methoddesc}{set_from}{from_\optional{, time_=None}}
+Set the "From~" line to \var{from_}, which should be specified without a
+leading "From~" or trailing newline. If \var{time_} is specified, it should be
+a \class{struct_time} or a tuple suitable for passing to
+\method{time.strftime()}; if \var{time_} is \code{True}, the result of
+\method{time.gmtime()} is used.
+\end{methoddesc}
+
+\begin{methoddesc}{get_flags}{}
+Return a string specifying the flags that are currently set. If the message
+complies with the conventional format, the result is the concatenation in the
+following order of zero or one occurrence of each of \character{R},
+\character{O}, \character{D}, \character{F}, and \character{A}.
+\end{methoddesc}
+
+\begin{methoddesc}{set_flags}{flags}
+Set the flags specified by \var{flags} and unset all others. Parameter
+\var{flags} should be the concatenation in any order of zero or more
+occurrences of each of \character{R}, \character{O}, \character{D},
+\character{F}, and \character{A}.
+\end{methoddesc}
+
+\begin{methoddesc}{add_flags}{flags}
+Set the flags specified by \var{flags} (if they are not set), and don't change
+other flags. Parameter \var{flags} should be the concatenation in any order of
+zero or more occurrences of each of \character{R}, \character{O},
+\character{D}, \character{F}, and \character{A}.
+\end{methoddesc}
+
+\begin{methoddesc}{remove_flags}{flags}
+Unset the flags specified by \var{flags} (if they are set), and don't change
+other flags. Parameter \var{flags} should be the concatenation in any order of
+zero or more occurrences of each of \character{R}, \character{O},
+\character{D}, \character{F}, and \character{A}.
+\end{methoddesc}
+
+When an \class{MMDFMessage} instance is created based upon a
+\class{MaildirMessage} instance, the following conversions take place:
+
+\begin{tableii}{l|l}{textrm}
+ {Resulting state}{\class{MaildirMessage} state}
+\lineii{R flag}{S flag}
+\lineii{O flag}{"cur" subdirectory}
+\lineii{D flag}{T flag}
+\lineii{F flag}{F flag}
+\lineii{A flag}{R flag}
+\end{tableii}
+
+When an \class{MMDFMessage} instance is created based upon an \class{MHMessage}
+instance, the following conversions take place:
+
+\begin{tableii}{l|l}{textrm}
+ {Resulting state}{\class{MHMessage} state}
+\lineii{R flag and O flag}{no "unseen" sequence}
+\lineii{O flag}{"unseen" sequence}
+\lineii{F flag}{"flagged" sequence}
+\lineii{A flag}{"replied" sequence}
+\end{tableii}
+
+When an \class{MMDFMessage} instance is created based upon a
+\class{BabylMessage} instance, the following conversions take place:
+
+\begin{tableii}{l|l}{textrm}
+ {Resulting state}{\class{BabylMessage} state}
+\lineii{R flag and O flag}{no "unseen" label}
+\lineii{O flag}{"unseen" label}
+\lineii{D flag}{"deleted" label}
+\lineii{A flag}{"answered" label}
+\end{tableii}
+
+When an \class{MMDFMessage} instance is created based upon an
+\class{mboxMessage} instance, the "From~" line is copied and all flags directly
+correspond:
+
+\begin{tableii}{l|l}{textrm}
+ {Resulting state}{\class{mboxMessage} state}
+\lineii{R flag}{R flag}
+\lineii{O flag}{O flag}
+\lineii{D flag}{D flag}
+\lineii{F flag}{F flag}
+\lineii{A flag}{A flag}
+\end{tableii}
+
\subsection{Deprecated classes}
\label{mailbox-deprecated-classes}
Index: test_mailbox.py
===================================================================
RCS file: /cvsroot/python/python/nondist/sandbox/mailbox/test_mailbox.py,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- test_mailbox.py 26 Jul 2005 20:47:48 -0000 1.1
+++ test_mailbox.py 30 Jul 2005 22:49:08 -0000 1.2
@@ -451,7 +451,7 @@
msg0.set_flags('TP')
key = box.add(msg0)
msg_returned = box.get_message(key)
- self.assert_(msg_returned.get_subdir() == 'cur')
+ self.assert_(msg_returned.get_subdir() == 'new')
self.assert_(msg_returned.get_flags() == 'PT')
msg1 = mailbox.MaildirMessage(template % 1)
box[key] = msg1
@@ -464,7 +464,7 @@
box[key] = msg2
box[key] = template % 3
msg_returned = box.get_message(key)
- self.assert_(msg_returned.get_subdir() == 'cur')
+ self.assert_(msg_returned.get_subdir() == 'new')
self.assert_(msg_returned.get_flags() == 'S')
self.assert_(msg_returned.get_payload() == '3')
@@ -696,7 +696,9 @@
# Copy self's format-specific data to other message formats.
# This test is superficial; better ones are in TestMessageConversion.
msg = self._factory()
- for class_ in (mailbox.Message, mailbox.MaildirMessage):
+ for class_ in (mailbox.Message, mailbox.MaildirMessage,
+ mailbox.mboxMessage, mailbox.MHMessage,
+ mailbox.BabylMessage, mailbox.MMDFMessage):
other_msg = class_()
msg._explain_to(other_msg)
other_msg = email.Message.Message()
@@ -735,7 +737,7 @@
self.assert_(msg.get_flags() == '')
self.assert_(msg.get_subdir() == 'new')
msg.set_flags('F')
- self.assert_(msg.get_subdir() == 'cur')
+ self.assert_(msg.get_subdir() == 'new')
self.assert_(msg.get_flags() == 'F')
msg.set_flags('SDTP')
self.assert_(msg.get_flags() == 'DPST')
@@ -743,7 +745,7 @@
self.assert_(msg.get_flags() == 'DFPST')
msg.remove_flags('TDRP')
self.assert_(msg.get_flags() == 'FS')
- self.assert_(msg.get_subdir() == 'cur')
+ self.assert_(msg.get_subdir() == 'new')
self._check_sample(msg)
def test_info(self):
@@ -774,8 +776,377 @@
self._check_sample(msg)
+class _TestMboxMMDFMessage(TestMessage):
+
+ _factory = mailbox._mboxMMDFMessage
+
+ def _post_initialize_hook(self, msg):
+ self._check_from(msg)
+
+ def test_initialize_with_unixfrom(self):
+ # Initialize with a message that already has a _unixfrom attribute
+ msg = mailbox.Message(_sample_message)
+ msg.set_unixfrom('From foo@bar blah')
+ msg = mailbox.mboxMessage(msg)
+ self.assert_(msg.get_from() == 'foo@bar blah', msg.get_from())
+
+ def test_from(self):
+ # Get and set "From " line
+ msg = mailbox.mboxMessage(_sample_message)
+ self._check_from(msg)
+ msg.set_from('foo bar')
+ self.assert_(msg.get_from() == 'foo bar')
+ msg.set_from('foo@bar', True)
+ self._check_from(msg, 'foo@bar')
+ msg.set_from('blah@temp', time.localtime())
+ self._check_from(msg, 'blah@temp')
+
+ def test_flags(self):
+ # Use get_flags(), set_flags(), add_flags(), remove_flags()
+ msg = mailbox.mboxMessage(_sample_message)
+ self.assert_(msg.get_flags() == '')
+ msg.set_flags('F')
+ self.assert_(msg.get_flags() == 'F')
+ msg.set_flags('XODR')
+ self.assert_(msg.get_flags() == 'RODX')
+ msg.add_flags('FA')
+ self.assert_(msg.get_flags() == 'RODFAX')
+ msg.remove_flags('FDXA')
+ self.assert_(msg.get_flags() == 'RO')
+ self._check_sample(msg)
+
+ def _check_from(self, msg, sender=None):
+ # Check contents of "From " line
+ if sender is None:
+ sender = "MAILER-DAEMON"
+ self.assert_(re.match(sender + r" \w{3} \w{3} [\d ]\d [\d ]\d:\d{2}:"
+ r"\d{2} \d{4}", msg.get_from()) is not None)
+
+
+class TestMboxMessage(_TestMboxMMDFMessage):
+
+ _factory = mailbox.mboxMessage
+
+
+class TestMHMessage(TestMessage):
+
+ _factory = mailbox.MHMessage
+
+ def _post_initialize_hook(self, msg):
+ self.assert_(msg._sequences == [])
+
+ def test_sequences(self):
+ # List, join, and leave sequences
+ msg = mailbox.MHMessage(_sample_message)
+ self.assert_(msg.list_sequences() == [])
+ msg.join_sequence('unseen')
+ self.assert_(msg.list_sequences() == ['unseen'])
+ msg.join_sequence('flagged')
+ self.assert_(msg.list_sequences() == ['unseen', 'flagged'])
+ msg.join_sequence('flagged')
+ self.assert_(msg.list_sequences() == ['unseen', 'flagged'])
+ msg.leave_sequence('unseen')
+ self.assert_(msg.list_sequences() == ['flagged'])
+ msg.join_sequence('foobar')
+ self.assert_(msg.list_sequences() == ['flagged', 'foobar'])
+ msg.leave_sequence('replied')
+ self.assert_(msg.list_sequences() == ['flagged', 'foobar'])
+
+
+class TestBabylMessage(TestMessage):
+
+ _factory = mailbox.BabylMessage
+
+ def _post_initialize_hook(self, msg):
+ self.assert_(msg._labels == [])
+
+ def test_labels(self):
+ # List, add, and remove labels
+ msg = mailbox.BabylMessage(_sample_message)
+ self.assert_(msg.list_labels() == [])
+ msg.add_label('filed')
+ self.assert_(msg.list_labels() == ['filed'])
+ msg.add_label('resent')
+ self.assert_(msg.list_labels() == ['filed', 'resent'])
+ msg.add_label('resent')
+ self.assert_(msg.list_labels() == ['filed', 'resent'])
+ msg.remove_label('filed')
+ self.assert_(msg.list_labels() == ['resent'])
+ msg.add_label('foobar')
+ self.assert_(msg.list_labels() == ['resent', 'foobar'])
+ msg.remove_label('unseen')
+ self.assert_(msg.list_labels() == ['resent', 'foobar'])
+
+ def test_visible(self):
+ # Get, set, and update visible headers
+ msg = mailbox.BabylMessage(_sample_message)
+ visible = msg.get_visible()
+ self.assert_(visible.keys() == [])
+ self.assert_(visible.get_payload() is None)
+ visible['User-Agent'] = 'FooBar 1.0'
+ visible['X-Whatever'] = 'Blah'
+ self.assert_(msg.get_visible().keys() == [])
+ msg.set_visible(visible)
+ visible = msg.get_visible()
+ self.assert_(visible.keys() == ['User-Agent', 'X-Whatever'])
+ self.assert_(visible['User-Agent'] == 'FooBar 1.0')
+ self.assert_(visible['X-Whatever'] == 'Blah')
+ self.assert_(visible.get_payload() is None)
+ msg.update_visible()
+ self.assert_(visible.keys() == ['User-Agent', 'X-Whatever'])
+ self.assert_(visible.get_payload() is None)
+ visible = msg.get_visible()
+ self.assert_(visible.keys() == ['User-Agent', 'Date', 'From', 'To',
+ 'Subject'])
+ for header in ('User-Agent', 'Date', 'From', 'To', 'Subject'):
+ self.assert_(visible[header] == msg[header])
+
+
+class TestMMDFMessage(_TestMboxMMDFMessage):
+
+ _factory = mailbox.MMDFMessage
+
+
class TestMessageConversion(TestBase):
- pass
+
+ def test_plain_to_x(self):
+ # Convert Message to all formats
+ for class_ in (mailbox.Message, mailbox.MaildirMessage,
+ mailbox.mboxMessage, mailbox.MHMessage,
+ mailbox.BabylMessage, mailbox.MMDFMessage):
+ msg_plain = mailbox.Message(_sample_message)
+ msg = class_(msg_plain)
+ self._check_sample(msg)
+
+ def test_x_to_plain(self):
+ # Convert all formats to Message
+ for class_ in (mailbox.Message, mailbox.MaildirMessage,
+ mailbox.mboxMessage, mailbox.MHMessage,
+ mailbox.BabylMessage, mailbox.MMDFMessage):
+ msg = class_(_sample_message)
+ msg_plain = mailbox.Message(msg)
+ self._check_sample(msg_plain)
+
+ def test_x_to_invalid(self):
+ # Convert all formats to an invalid format
+ for class_ in (mailbox.Message, mailbox.MaildirMessage,
+ mailbox.mboxMessage, mailbox.MHMessage,
+ mailbox.BabylMessage, mailbox.MMDFMessage):
+ self.assertRaises(TypeError, lambda: class_(False))
+
+ def test_maildir_to_maildir(self):
+ # Convert MaildirMessage to MaildirMessage
+ msg_maildir = mailbox.MaildirMessage(_sample_message)
+ msg_maildir.set_flags('DFPRST')
+ msg_maildir.set_subdir('cur')
+ msg = mailbox.MaildirMessage(msg_maildir)
+ self._check_sample(msg)
+ self.assert_(msg.get_flags() == 'DFPRST')
+ self.assert_(msg.get_subdir() == 'cur')
+
+ def test_maildir_to_mboxmmdf(self):
+ # Convert MaildirMessage to mboxmessage and MMDFMessage
+ pairs = (('D', ''), ('F', 'F'), ('P', ''), ('R', 'A'), ('S', 'R'),
+ ('T', 'D'), ('DFPRST', 'RDFA'))
+ for class_ in (mailbox.mboxMessage, mailbox.MMDFMessage):
+ msg_maildir = mailbox.MaildirMessage(_sample_message)
+ for setting, result in pairs:
+ msg_maildir.set_flags(setting)
+ self.assert_(class_(msg_maildir).get_flags() == result)
+ msg_maildir.set_subdir('cur')
+ self.assert_(class_(msg_maildir).get_flags() == 'RODFA')
+
+ def test_maildir_to_mh(self):
+ # Convert MaildirMessage to MHMessage
+ msg_maildir = mailbox.MaildirMessage(_sample_message)
+ pairs = (('D', ['unseen']), ('F', ['unseen', 'flagged']),
+ ('P', ['unseen']), ('R', ['unseen', 'replied']), ('S', []),
+ ('T', ['unseen']), ('DFPRST', ['replied', 'flagged']))
+ for setting, result in pairs:
+ msg_maildir.set_flags(setting)
+ self.assert_(mailbox.MHMessage(msg_maildir).list_sequences() == \
+ result)
+
+ def test_maildir_to_babyl(self):
+ # Convert MaildirMessage to Babyl
+ msg_maildir = mailbox.MaildirMessage(_sample_message)
+ pairs = (('D', ['unseen']), ('F', ['unseen']),
+ ('P', ['unseen', 'forwarded']), ('R', ['unseen', 'answered']),
+ ('S', []), ('T', ['unseen', 'deleted']),
+ ('DFPRST', ['deleted', 'answered', 'forwarded']))
+ for setting, result in pairs:
+ msg_maildir.set_flags(setting)
+ self.assert_(mailbox.BabylMessage(msg_maildir).list_labels() == \
+ result)
+
+ def test_mboxmmdf_to_maildir(self):
+ # Convert mboxMessage and MMDFMessage to MaildirMessage
+ for class_ in (mailbox.mboxMessage, mailbox.MMDFMessage):
+ msg_mboxMMDF = class_(_sample_message)
+ pairs = (('R', 'S'), ('O', ''), ('D', 'T'), ('F', 'F'), ('A', 'R'),
+ ('RODFA', 'FRST'))
+ for setting, result in pairs:
+ msg_mboxMMDF.set_flags(setting)
+ self.assert_(mailbox.MaildirMessage(msg_mboxMMDF).get_flags() \
+ == result)
+ msg_mboxMMDF.set_flags('O')
+ self.assert_(mailbox.MaildirMessage(msg_mboxMMDF).get_subdir() == \
+ 'cur')
+
+ def test_mboxmmdf_to_mboxmmdf(self):
+ # Convert mboxMessage and MMDFMessage to mboxMessage and MMDFMessage
+ for class_ in (mailbox.mboxMessage, mailbox.MMDFMessage):
+ msg_mboxMMDF = class_(_sample_message)
+ msg_mboxMMDF.set_flags('RODFA')
+ msg_mboxMMDF.set_from('foo@bar')
+ for class2_ in (mailbox.mboxMessage, mailbox.MMDFMessage):
+ msg2 = class2_(msg_mboxMMDF)
+ self.assert_(msg2.get_flags() == 'RODFA')
+ self.assert_(msg2.get_from() == 'foo@bar')
+
+ def test_mboxmmdf_to_mh(self):
+ # Convert mboxMessage and MMDFMessage to MHMessage
+ for class_ in (mailbox.mboxMessage, mailbox.MMDFMessage):
+ msg_mboxMMDF = class_(_sample_message)
+ pairs = (('R', []), ('O', ['unseen']), ('D', ['unseen']),
+ ('F', ['unseen', 'flagged']),
+ ('A', ['unseen', 'replied']),
+ ('RODFA', ['replied', 'flagged']))
+ for setting, result in pairs:
+ msg_mboxMMDF.set_flags(setting)
+ self.assert_(mailbox.MHMessage(msg_mboxMMDF).list_sequences() \
+ == result)
+
+ def test_mboxmmdf_to_babyl(self):
+ # Convert mboxMessage and MMDFMessage to BabylMessage
+ for class_ in (mailbox.mboxMessage, mailbox.MMDFMessage):
+ msg = class_(_sample_message)
+ pairs = (('R', []), ('O', ['unseen']),
+ ('D', ['unseen', 'deleted']), ('F', ['unseen']),
+ ('A', ['unseen', 'answered']),
+ ('RODFA', ['deleted', 'answered']))
+ for setting, result in pairs:
+ msg.set_flags(setting)
+ self.assert_(mailbox.BabylMessage(msg).list_labels() == result)
+
+ def test_mh_to_maildir(self):
+ # Convert MHMessage to MaildirMessage
+ pairs = (('unseen', ''), ('replied', 'RS'), ('flagged', 'FS'))
+ for setting, result in pairs:
+ msg = mailbox.MHMessage(_sample_message)
+ msg.join_sequence(setting)
+ self.assert_(mailbox.MaildirMessage(msg).get_flags() == result)
+ self.assert_(mailbox.MaildirMessage(msg).get_subdir() == 'cur')
+ msg = mailbox.MHMessage(_sample_message)
+ msg.join_sequence('unseen')
+ msg.join_sequence('replied')
+ msg.join_sequence('flagged')
+ self.assert_(mailbox.MaildirMessage(msg).get_flags() == 'FR')
+ self.assert_(mailbox.MaildirMessage(msg).get_subdir() == 'cur')
+
+ def test_mh_to_mboxmmdf(self):
+ # Convert MHMessage to mboxMessage and MMDFMessage
+ pairs = (('unseen', 'O'), ('replied', 'ROA'), ('flagged', 'ROF'))
+ for setting, result in pairs:
+ msg = mailbox.MHMessage(_sample_message)
+ msg.join_sequence(setting)
+ for class_ in (mailbox.mboxMessage, mailbox.MMDFMessage):
+ self.assert_(class_(msg).get_flags() == result)
+ msg = mailbox.MHMessage(_sample_message)
+ msg.join_sequence('unseen')
+ msg.join_sequence('replied')
+ msg.join_sequence('flagged')
+ for class_ in (mailbox.mboxMessage, mailbox.MMDFMessage):
+ self.assert_(class_(msg).get_flags() == 'OFA')
+
+ def test_mh_to_mh(self):
+ # Convert MHMessage to MHMessage
+ msg = mailbox.MHMessage(_sample_message)
+ msg.join_sequence('unseen')
+ msg.join_sequence('replied')
+ msg.join_sequence('flagged')
+ self.assert_(mailbox.MHMessage(msg).list_sequences() == \
+ ['unseen', 'replied', 'flagged'])
+
+ def test_mh_to_babyl(self):
+ # Convert MHMessage to BabylMessage
+ pairs = (('unseen', ['unseen']), ('replied', ['answered']),
+ ('flagged', []))
+ for setting, result in pairs:
+ msg = mailbox.MHMessage(_sample_message)
+ msg.join_sequence(setting)
+ self.assert_(mailbox.BabylMessage(msg).list_labels() == result)
+ msg = mailbox.MHMessage(_sample_message)
+ msg.join_sequence('unseen')
+ msg.join_sequence('replied')
+ msg.join_sequence('flagged')
+ self.assert_(mailbox.BabylMessage(msg).list_labels() == \
+ ['unseen', 'answered'])
+
+ def test_babyl_to_maildir(self):
+ # Convert BabylMessage to MaildirMessage
+ pairs = (('unseen', ''), ('deleted', 'ST'), ('filed', 'S'),
+ ('answered', 'RS'), ('forwarded', 'PS'), ('edited', 'S'),
+ ('resent', 'PS'))
+ for setting, result in pairs:
+ msg = mailbox.BabylMessage(_sample_message)
+ msg.add_label(setting)
+ self.assert_(mailbox.MaildirMessage(msg).get_flags() == result)
+ self.assert_(mailbox.MaildirMessage(msg).get_subdir() == 'cur')
+ msg = mailbox.BabylMessage(_sample_message)
+ for label in ('unseen', 'deleted', 'filed', 'answered', 'forwarded',
+ 'edited', 'resent'):
+ msg.add_label(label)
+ self.assert_(mailbox.MaildirMessage(msg).get_flags() == 'PRT')
+ self.assert_(mailbox.MaildirMessage(msg).get_subdir() == 'cur')
+
+ def test_babyl_to_mboxmmdf(self):
+ # Convert BabylMessage to mboxMessage and MMDFMessage
+ pairs = (('unseen', 'O'), ('deleted', 'ROD'), ('filed', 'RO'),
+ ('answered', 'ROA'), ('forwarded', 'RO'), ('edited', 'RO'),
+ ('resent', 'RO'))
+ for setting, result in pairs:
+ for class_ in (mailbox.mboxMessage, mailbox.MMDFMessage):
+ msg = mailbox.BabylMessage(_sample_message)
+ msg.add_label(setting)
+ self.assert_(class_(msg).get_flags() == result)
+ msg = mailbox.BabylMessage(_sample_message)
+ for label in ('unseen', 'deleted', 'filed', 'answered', 'forwarded',
+ 'edited', 'resent'):
+ msg.add_label(label)
+ for class_ in (mailbox.mboxMessage, mailbox.MMDFMessage):
+ self.assert_(class_(msg).get_flags() == 'ODA')
+
+ def test_babyl_to_mh(self):
+ # Convert BabylMessage to MHMessage
+ pairs = (('unseen', ['unseen']), ('deleted', []), ('filed', []),
+ ('answered', ['replied']), ('forwarded', []), ('edited', []),
+ ('resent', []))
+ for setting, result in pairs:
+ msg = mailbox.BabylMessage(_sample_message)
+ msg.add_label(setting)
+ self.assert_(mailbox.MHMessage(msg).list_sequences() == result)
+ msg = mailbox.BabylMessage(_sample_message)
+ for label in ('unseen', 'deleted', 'filed', 'answered', 'forwarded',
+ 'edited', 'resent'):
+ msg.add_label(label)
+ self.assert_(mailbox.MHMessage(msg).list_sequences() == \
+ ['unseen', 'replied'])
+
+ def test_babyl_to_babyl(self):
+ # Convert BabylMessage to BabylMessage
+ msg = mailbox.BabylMessage(_sample_message)
+ msg.update_visible()
+ for label in ('unseen', 'deleted', 'filed', 'answered', 'forwarded',
+ 'edited', 'resent'):
+ msg.add_label(label)
+ msg2 = mailbox.BabylMessage(msg)
+ self.assert_(msg2.list_labels() == ['unseen', 'deleted', 'filed',
+ 'answered', 'forwarded', 'edited',
+ 'resent'])
+ self.assert_(msg.get_visible().keys() == msg2.get_visible().keys())
+ for key in msg.get_visible().keys():
+ self.assert_(msg.get_visible()[key] == msg2.get_visible()[key])
class TestProxyFileBase(TestBase):
@@ -1016,8 +1387,9 @@
def test_main():
test_support.run_unittest(TestMaildir, TestMessage, TestMaildirMessage,
- TestMessageConversion, TestProxyFile,
- TestPartialFile)
+ TestMboxMessage, TestMHMessage, TestBabylMessage,
+ TestMMDFMessage, TestMessageConversion,
+ TestProxyFile, TestPartialFile)
if __name__ == '__main__':
1
0
python/nondist/sandbox/set setobject.c, 1.7, 1.8 setobject.h, 1.2, 1.3
by rhettinger@users.sourceforge.net 30 Jul '05
by rhettinger@users.sourceforge.net 30 Jul '05
30 Jul '05
Update of /cvsroot/python/python/nondist/sandbox/set
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv26909
Modified Files:
setobject.c setobject.h
Log Message:
More cleanups.
* Remove unnecessary typedefs and forward declarations.
* Make the empty frozenset a singleton
* Eliminate C++ style comments
Index: setobject.c
===================================================================
RCS file: /cvsroot/python/python/nondist/sandbox/set/setobject.c,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -d -r1.7 -r1.8
--- setobject.c 30 Jul 2005 21:07:28 -0000 1.7
+++ setobject.c 30 Jul 2005 22:21:09 -0000 1.8
@@ -5,18 +5,11 @@
#include "Python.h"
-typedef PySetEntry setentry;
-typedef PySetObject setobject;
-
/* This must be >= 1. */
#define PERTURB_SHIFT 5
/* Object used as dummy key to fill deleted entries */
-static PyObject *dummy; /* Initialized by first call to newsetobject() */
-
-/* forward declarations */
-static setentry *
-set_lookkey_string(setobject *so, PyObject *key, long hash);
+static PyObject *dummy; /* Initialized by first call to make_new_set() */
#define EMPTY_TO_MINSIZE(so) do { \
memset((so)->smalltable, 0, sizeof((so)->smalltable)); \
@@ -43,7 +36,7 @@
*/
static setentry *
-set_lookkey(setobject *so, PyObject *key, register long hash)
+set_lookkey(PySetObject *so, PyObject *key, register long hash)
{
register int i;
register unsigned int perturb;
@@ -83,9 +76,7 @@
}
else {
/* The compare did major nasty stuff to the
- * xx: start over.
- * XXX A clever adversary could prevent this
- * XXX from terminating.
+ * set: start over.
*/
ep = set_lookkey(so, key, hash);
goto Done;
@@ -125,9 +116,7 @@
}
else {
/* The compare did major nasty stuff to the
- * xx: start over.
- * XXX A clever adversary could prevent this
- * XXX from terminating.
+ * set: start over.
*/
ep = set_lookkey(so, key, hash);
break;
@@ -154,7 +143,7 @@
* expensive, and sets with pure-string keys may be very common.
*/
static setentry *
-set_lookkey_string(setobject *so, PyObject *key, register long hash)
+set_lookkey_string(PySetObject *so, PyObject *key, register long hash)
{
register int i;
register unsigned int perturb;
@@ -206,10 +195,10 @@
Eats a reference to key.
*/
static void
-set_insert_key(register setobject *so, PyObject *key, long hash)
+set_insert_key(register PySetObject *so, PyObject *key, long hash)
{
register setentry *ep;
- typedef PySetEntry *(*lookupfunc)(PySetObject *, PyObject *, long);
+ typedef setentry *(*lookupfunc)(PySetObject *, PyObject *, long);
assert(so->lookup != NULL);
@@ -222,10 +211,10 @@
so->used++;
} else if (ep->key == dummy) {
/* DUMMY */
- Py_DECREF(dummy);
ep->key = key;
ep->hash = hash;
so->used++;
+ Py_DECREF(dummy);
} else {
/* ACTIVE */
Py_DECREF(key);
@@ -238,7 +227,7 @@
actually be smaller than the old one.
*/
static int
-set_table_resize(setobject *so, int minused)
+set_table_resize(PySetObject *so, int minused)
{
int newsize;
setentry *oldtable, *newtable, *ep;
@@ -303,15 +292,15 @@
dummy entries aren't copied over, of course */
for (ep = oldtable; i > 0; ep++) {
if (ep->key == NULL) {
- // UNUSED
+ /* UNUSED */
;
} else if (ep->key == dummy) {
- // DUMMY
+ /* DUMMY */
--i;
assert(ep->key == dummy);
Py_DECREF(ep->key);
} else {
- // ACTIVE
+ /* ACTIVE */
--i;
set_insert_key(so, ep->key, ep->hash);
}
@@ -350,8 +339,8 @@
return set_table_resize(so, so->used*(so->used>50000 ? 2 : 4));
}
-#define DISCARD_FOUND 0
-#define DISCARD_NOTFOUND 1
+#define DISCARD_NOTFOUND 0
+#define DISCARD_FOUND 1
static int
set_discard_internal(PySetObject *so, PyObject *key)
@@ -490,7 +479,7 @@
assert (PyAnySet_Check(so));
assert (PyAnySet_Check(b));
- other = (setobject*)b;
+ other = (PySetObject*)b;
if (other == so || other->used == 0)
/* a.update(a) or a.update({}); nothing to do */
return 0;
@@ -529,20 +518,19 @@
}
static PyTypeObject PySetIter_Type; /* Forward */
-static PyObject *set_iter(setobject *);
/* Set iterator types */
typedef struct {
PyObject_HEAD
- setobject *si_set; /* Set to NULL when iterator is exhausted */
+ PySetObject *si_set; /* Set to NULL when iterator is exhausted */
int si_used;
int si_pos;
long len;
} setiterobject;
static PyObject *
-set_iter(setobject *so)
+set_iter(PySetObject *so)
{
setiterobject *si = PyObject_New(setiterobject, &PySetIter_Type);
if (si == NULL)
@@ -580,7 +568,7 @@
PyObject *key;
register int i, mask;
register setentry *ep;
- setobject *d = si->si_set;
+ PySetObject *d = si->si_set;
if (d == NULL)
return NULL;
@@ -646,7 +634,7 @@
(iternextfunc)setiter_iternextkey, /* tp_iternext */
};
-/***** Derived functions (table accesses only done thru above primitives *****/
+/***** Derived functions (table accesses only done with above primitives *****/
#include "structmember.h"
@@ -739,10 +727,19 @@
frozenset_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
PyObject *iterable = NULL;
+ static PyObject *emptyfrozenset = NULL;
if (!PyArg_UnpackTuple(args, type->tp_name, 0, 1, &iterable))
return NULL;
- if (iterable != NULL && PyFrozenSet_CheckExact(iterable)) {
+ if (iterable == NULL) {
+ if (type == &PyFrozenSet_Type) {
+ if (emptyfrozenset == NULL)
+ emptyfrozenset = make_new_set(type, NULL);
+ else
+ Py_INCREF(emptyfrozenset);
+ return emptyfrozenset;
+ }
+ } else if (PyFrozenSet_CheckExact(iterable)) {
Py_INCREF(iterable);
return iterable;
}
@@ -800,9 +797,9 @@
set_swap_bodies(PySetObject *a, PySetObject *b)
{
int t;
- PySetEntry *u;
- PySetEntry *(*f)(PySetObject *so, PyObject *key, long hash);
- PySetEntry tab[PySet_MINSIZE];
+ setentry *u;
+ setentry *(*f)(PySetObject *so, PyObject *key, long hash);
+ setentry tab[PySet_MINSIZE];
long h;
t = a->fill; a->fill = b->fill; b->fill = t;
Index: setobject.h
===================================================================
RCS file: /cvsroot/python/python/nondist/sandbox/set/setobject.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- setobject.h 30 Jul 2005 21:07:28 -0000 1.2
+++ setobject.h 30 Jul 2005 22:21:10 -0000 1.3
@@ -20,7 +20,7 @@
typedef struct {
long hash; /* cached hash code for the entry key */
PyObject *key;
-} PySetEntry;
+} setentry;
/*
@@ -45,9 +45,9 @@
* saves repeated runtime null-tests in the workhorse getitem and
* setitem calls.
*/
- PySetEntry *table;
- PySetEntry *(*lookup)(PySetObject *so, PyObject *key, long hash);
- PySetEntry smalltable[PySet_MINSIZE];
+ setentry *table;
+ setentry *(*lookup)(PySetObject *so, PyObject *key, long hash);
+ setentry smalltable[PySet_MINSIZE];
long hash; /* only used by frozenset objects */
PyObject *weakreflist; /* List of weak references */
1
0
python/nondist/sandbox/set setobject.c, 1.6, 1.7 setobject.h, 1.1, 1.2
by rhettinger@users.sourceforge.net 30 Jul '05
by rhettinger@users.sourceforge.net 30 Jul '05
30 Jul '05
Update of /cvsroot/python/python/nondist/sandbox/set
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv12279
Modified Files:
setobject.c setobject.h
Log Message:
Improve variable names and other minor clean-up.
Index: setobject.c
===================================================================
RCS file: /cvsroot/python/python/nondist/sandbox/set/setobject.c,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- setobject.c 30 Jul 2005 16:21:17 -0000 1.6
+++ setobject.c 30 Jul 2005 21:07:28 -0000 1.7
@@ -16,13 +16,13 @@
/* forward declarations */
static setentry *
-set_lookkey_string(setobject *mp, PyObject *key, long hash);
+set_lookkey_string(setobject *so, PyObject *key, long hash);
-#define EMPTY_TO_MINSIZE(mp) do { \
- memset((mp)->ma_smalltable, 0, sizeof((mp)->ma_smalltable)); \
- (mp)->ma_used = (mp)->ma_fill = 0; \
- (mp)->ma_table = (mp)->ma_smalltable; \
- (mp)->ma_mask = PySet_MINSIZE - 1; \
+#define EMPTY_TO_MINSIZE(so) do { \
+ memset((so)->smalltable, 0, sizeof((so)->smalltable)); \
+ (so)->used = (so)->fill = 0; \
+ (so)->table = (so)->smalltable; \
+ (so)->mask = PySet_MINSIZE - 1; \
} while(0)
@@ -38,18 +38,18 @@
All arithmetic on hash should ignore overflow.
This function must never return NULL; failures are indicated by returning
-a setentry* for which the me_value field is NULL. Exceptions are never
+a setentry* for which the value field is NULL. Exceptions are never
reported by this function, and outstanding exceptions are maintained.
*/
static setentry *
-set_lookkey(setobject *mp, PyObject *key, register long hash)
+set_lookkey(setobject *so, PyObject *key, register long hash)
{
register int i;
register unsigned int perturb;
register setentry *freeslot;
- register unsigned int mask = mp->ma_mask;
- setentry *ep0 = mp->ma_table;
+ register unsigned int mask = so->mask;
+ setentry *ep0 = so->table;
register setentry *ep;
register int restore_error;
register int checked_error;
@@ -59,25 +59,25 @@
i = hash & mask;
ep = &ep0[i];
- if (ep->me_key == NULL || ep->me_key == key)
+ if (ep->key == NULL || ep->key == key)
return ep;
restore_error = checked_error = 0;
- if (ep->me_key == dummy)
+ if (ep->key == dummy)
freeslot = ep;
else {
- if (ep->me_hash == hash) {
+ if (ep->hash == hash) {
/* error can't have been checked yet */
checked_error = 1;
if (PyErr_Occurred()) {
restore_error = 1;
PyErr_Fetch(&err_type, &err_value, &err_tb);
}
- startkey = ep->me_key;
+ startkey = ep->key;
cmp = PyObject_RichCompareBool(startkey, key, Py_EQ);
if (cmp < 0)
PyErr_Clear();
- if (ep0 == mp->ma_table && ep->me_key == startkey) {
+ if (ep0 == so->table && ep->key == startkey) {
if (cmp > 0)
goto Done;
}
@@ -87,26 +87,26 @@
* XXX A clever adversary could prevent this
* XXX from terminating.
*/
- ep = set_lookkey(mp, key, hash);
+ ep = set_lookkey(so, key, hash);
goto Done;
}
}
freeslot = NULL;
}
- /* In the loop, me_key == dummy is by far (factor of 100s) the
+ /* In the loop, key == dummy is by far (factor of 100s) the
least likely outcome, so test for that last. */
for (perturb = hash; ; perturb >>= PERTURB_SHIFT) {
i = (i << 2) + i + perturb + 1;
ep = &ep0[i & mask];
- if (ep->me_key == NULL) {
+ if (ep->key == NULL) {
if (freeslot != NULL)
ep = freeslot;
break;
}
- if (ep->me_key == key)
+ if (ep->key == key)
break;
- if (ep->me_hash == hash && ep->me_key != dummy) {
+ if (ep->hash == hash && ep->key != dummy) {
if (!checked_error) {
checked_error = 1;
if (PyErr_Occurred()) {
@@ -115,11 +115,11 @@
&err_tb);
}
}
- startkey = ep->me_key;
+ startkey = ep->key;
cmp = PyObject_RichCompareBool(startkey, key, Py_EQ);
if (cmp < 0)
PyErr_Clear();
- if (ep0 == mp->ma_table && ep->me_key == startkey) {
+ if (ep0 == so->table && ep->key == startkey) {
if (cmp > 0)
break;
}
@@ -129,11 +129,11 @@
* XXX A clever adversary could prevent this
* XXX from terminating.
*/
- ep = set_lookkey(mp, key, hash);
+ ep = set_lookkey(so, key, hash);
break;
}
}
- else if (ep->me_key == dummy && freeslot == NULL)
+ else if (ep->key == dummy && freeslot == NULL)
freeslot = ep;
}
@@ -154,13 +154,13 @@
* expensive, and sets with pure-string keys may be very common.
*/
static setentry *
-set_lookkey_string(setobject *mp, PyObject *key, register long hash)
+set_lookkey_string(setobject *so, PyObject *key, register long hash)
{
register int i;
register unsigned int perturb;
register setentry *freeslot;
- register unsigned int mask = mp->ma_mask;
- setentry *ep0 = mp->ma_table;
+ register unsigned int mask = so->mask;
+ setentry *ep0 = so->table;
register setentry *ep;
/* Make sure this function doesn't have to handle non-string keys,
@@ -168,36 +168,34 @@
strings is to override __eq__, and for speed we don't cater to
that here. */
if (!PyString_CheckExact(key)) {
- mp->ma_lookup = set_lookkey;
- return set_lookkey(mp, key, hash);
+ so->lookup = set_lookkey;
+ return set_lookkey(so, key, hash);
}
i = hash & mask;
ep = &ep0[i];
- if (ep->me_key == NULL || ep->me_key == key)
+ if (ep->key == NULL || ep->key == key)
return ep;
- if (ep->me_key == dummy)
+ if (ep->key == dummy)
freeslot = ep;
else {
- if (ep->me_hash == hash
- && _PyString_Eq(ep->me_key, key)) {
+ if (ep->hash == hash && _PyString_Eq(ep->key, key))
return ep;
- }
freeslot = NULL;
}
- /* In the loop, me_key == dummy is by far (factor of 100s) the
+ /* In the loop, key == dummy is by far (factor of 100s) the
least likely outcome, so test for that last. */
for (perturb = hash; ; perturb >>= PERTURB_SHIFT) {
i = (i << 2) + i + perturb + 1;
ep = &ep0[i & mask];
- if (ep->me_key == NULL)
+ if (ep->key == NULL)
return freeslot == NULL ? ep : freeslot;
- if (ep->me_key == key
- || (ep->me_hash == hash
- && ep->me_key != dummy
- && _PyString_Eq(ep->me_key, key)))
+ if (ep->key == key
+ || (ep->hash == hash
+ && ep->key != dummy
+ && _PyString_Eq(ep->key, key)))
return ep;
- if (ep->me_key == dummy && freeslot == NULL)
+ if (ep->key == dummy && freeslot == NULL)
freeslot = ep;
}
}
@@ -208,31 +206,27 @@
Eats a reference to key.
*/
static void
-set_insert_key(register setobject *mp, PyObject *key, long hash)
+set_insert_key(register setobject *so, PyObject *key, long hash)
{
register setentry *ep;
typedef PySetEntry *(*lookupfunc)(PySetObject *, PyObject *, long);
- assert(mp->ma_lookup != NULL);
+ assert(so->lookup != NULL);
- ep = mp->ma_lookup(mp, key, hash);
- if (ep->me_key == NULL) {
+ ep = so->lookup(so, key, hash);
+ if (ep->key == NULL) {
/* UNUSED */
- mp->ma_fill++;
- ep->me_key = key;
- ep->me_hash = hash;
- mp->ma_used++;
- }
-
- else if (ep->me_key == dummy) {
+ so->fill++;
+ ep->key = key;
+ ep->hash = hash;
+ so->used++;
+ } else if (ep->key == dummy) {
/* DUMMY */
Py_DECREF(dummy);
- ep->me_key = key;
- ep->me_hash = hash;
- mp->ma_used++;
- }
-
- else {
+ ep->key = key;
+ ep->hash = hash;
+ so->used++;
+ } else {
/* ACTIVE */
Py_DECREF(key);
}
@@ -244,7 +238,7 @@
actually be smaller than the old one.
*/
static int
-set_table_resize(setobject *mp, int minused)
+set_table_resize(setobject *so, int minused)
{
int newsize;
setentry *oldtable, *newtable, *ep;
@@ -265,15 +259,15 @@
}
/* Get space for a new table. */
- oldtable = mp->ma_table;
+ oldtable = so->table;
assert(oldtable != NULL);
- is_oldtable_malloced = oldtable != mp->ma_smalltable;
+ is_oldtable_malloced = oldtable != so->smalltable;
if (newsize == PySet_MINSIZE) {
/* A large table is shrinking, or we can't get any smaller. */
- newtable = mp->ma_smalltable;
+ newtable = so->smalltable;
if (newtable == oldtable) {
- if (mp->ma_fill == mp->ma_used) {
+ if (so->fill == so->used) {
/* No dummies, so no point doing anything. */
return 0;
}
@@ -283,7 +277,7 @@
as set_lookkey needs at least one virgin slot to
terminate failing searches. If fill < size, it's
merely desirable, as dummies slow searches. */
- assert(mp->ma_fill > mp->ma_used);
+ assert(so->fill > so->used);
memcpy(small_copy, oldtable, sizeof(small_copy));
oldtable = small_copy;
}
@@ -298,33 +292,28 @@
/* Make the set empty, using the new table. */
assert(newtable != oldtable);
- mp->ma_table = newtable;
- mp->ma_mask = newsize - 1;
+ so->table = newtable;
+ so->mask = newsize - 1;
memset(newtable, 0, sizeof(setentry) * newsize);
- mp->ma_used = 0;
- i = mp->ma_fill;
- mp->ma_fill = 0;
+ so->used = 0;
+ i = so->fill;
+ so->fill = 0;
/* Copy the data over; this is refcount-neutral for active entries;
dummy entries aren't copied over, of course */
for (ep = oldtable; i > 0; ep++) {
-
- if (ep->me_key == NULL) {
+ if (ep->key == NULL) {
// UNUSED
;
- }
-
- else if (ep->me_key == dummy) {
+ } else if (ep->key == dummy) {
// DUMMY
--i;
- assert(ep->me_key == dummy);
- Py_DECREF(ep->me_key);
- }
-
- else {
+ assert(ep->key == dummy);
+ Py_DECREF(ep->key);
+ } else {
// ACTIVE
--i;
- set_insert_key(mp, ep->me_key, ep->me_hash);
+ set_insert_key(so, ep->key, ep->hash);
}
}
@@ -338,7 +327,7 @@
/* CAUTION: set_add_internal() must guarantee that it won't resize the table */
static int
-set_add_internal(register PySetObject *mp, PyObject *key)
+set_add_internal(register PySetObject *so, PyObject *key)
{
register long hash;
register int n_used;
@@ -347,63 +336,50 @@
hash = ((PyStringObject *)key)->ob_shash;
if (hash == -1)
hash = PyObject_Hash(key);
- }
- else {
+ } else {
hash = PyObject_Hash(key);
if (hash == -1)
return -1;
}
- assert(mp->ma_fill <= mp->ma_mask); /* at least one empty slot */
- n_used = mp->ma_used;
+ assert(so->fill <= so->mask); /* at least one empty slot */
+ n_used = so->used;
Py_INCREF(key);
- set_insert_key(mp, key, hash);
- if (!(mp->ma_used > n_used && mp->ma_fill*3 >= (mp->ma_mask+1)*2))
+ set_insert_key(so, key, hash);
+ if (!(so->used > n_used && so->fill*3 >= (so->mask+1)*2))
return 0;
- return set_table_resize(mp, mp->ma_used*(mp->ma_used>50000 ? 2 : 4));
+ return set_table_resize(so, so->used*(so->used>50000 ? 2 : 4));
}
#define DISCARD_FOUND 0
#define DISCARD_NOTFOUND 1
static int
-set_discard_internal(PySetObject *mp, PyObject *key)
+set_discard_internal(PySetObject *so, PyObject *key)
{
register long hash;
register setentry *ep;
PyObject *old_key;
- assert (PyAnySet_Check(mp));
+ assert (PyAnySet_Check(so));
if (!PyString_CheckExact(key) ||
(hash = ((PyStringObject *) key)->ob_shash) == -1) {
hash = PyObject_Hash(key);
if (hash == -1)
return -1;
}
- ep = (mp->ma_lookup)(mp, key, hash);
- if (ep->me_key == NULL || ep->me_key == dummy)
+ ep = (so->lookup)(so, key, hash);
+ if (ep->key == NULL || ep->key == dummy)
return DISCARD_NOTFOUND;
- old_key = ep->me_key;
+ old_key = ep->key;
Py_INCREF(dummy);
- ep->me_key = dummy;
- mp->ma_used--;
+ ep->key = dummy;
+ so->used--;
Py_DECREF(old_key);
return DISCARD_FOUND;
}
-static int
-set_remove_internal(PySetObject *mp, PyObject *key)
-{
- int rv = set_discard_internal(mp, key);
-
- if (rv == 1) {
- PyErr_SetObject(PyExc_KeyError, key);
- return -1;
- }
- return rv;
-}
-
static void
-set_clear_internal(PySetObject *mp)
+set_clear_internal(PySetObject *so)
{
setentry *ep, *table;
int table_is_malloced;
@@ -413,15 +389,15 @@
int i, n;
#endif
- assert (PyAnySet_Check(mp));
+ assert (PyAnySet_Check(so));
#ifdef Py_DEBUG
- n = mp->ma_mask + 1;
+ n = so->mask + 1;
i = 0;
#endif
- table = mp->ma_table;
+ table = so->table;
assert(table != NULL);
- table_is_malloced = table != mp->ma_smalltable;
+ table_is_malloced = table != so->smalltable;
/* This is delicate. During the process of clearing the set,
* decrefs can cause the set to mutate. To avoid fatal confusion
@@ -429,9 +405,9 @@
* clearing the slots, and never refer to anything via mp->ref while
* clearing.
*/
- fill = mp->ma_fill;
+ fill = so->fill;
if (table_is_malloced)
- EMPTY_TO_MINSIZE(mp);
+ EMPTY_TO_MINSIZE(so);
else if (fill > 0) {
/* It's a small table with something that needs to be cleared.
@@ -440,7 +416,7 @@
*/
memcpy(small_copy, table, sizeof(small_copy));
table = small_copy;
- EMPTY_TO_MINSIZE(mp);
+ EMPTY_TO_MINSIZE(so);
}
/* else it's a small table that's already empty */
@@ -453,13 +429,13 @@
assert(i < n);
++i;
#endif
- if (ep->me_key) {
+ if (ep->key) {
--fill;
- Py_DECREF(ep->me_key);
+ Py_DECREF(ep->key);
}
#ifdef Py_DEBUG
else
- assert(ep->me_key == NULL || ep->me_key == dummy);
+ assert(ep->key == NULL || ep->key == dummy);
#endif
}
@@ -481,67 +457,64 @@
* mutates the table.
*/
static int
-set_next_internal(PySetObject *mp, int *ppos, PyObject **pkey)
+set_next_internal(PySetObject *so, int *ppos, PyObject **pkey)
{
register int i, mask;
register setentry *ep;
- assert (PyAnySet_Check(mp));
+ assert (PyAnySet_Check(so));
i = *ppos;
if (i < 0)
return 0;
- ep = mp->ma_table;
- mask = mp->ma_mask;
- while (i <= mask && (ep[i].me_key == NULL || ep[i].me_key == dummy))
+ ep = so->table;
+ mask = so->mask;
+ while (i <= mask && (ep[i].key == NULL || ep[i].key == dummy))
i++;
*ppos = i+1;
if (i > mask)
return 0;
if (pkey)
- *pkey = ep[i].me_key;
+ *pkey = ep[i].key;
return 1;
}
/* Methods */
static int
-set_merge_internal(PySetObject *mp, PyObject *b)
+set_merge_internal(PySetObject *so, PyObject *b)
{
register PySetObject *other;
register int i;
setentry *entry;
- assert (PyAnySet_Check(mp));
+ assert (PyAnySet_Check(so));
assert (PyAnySet_Check(b));
other = (setobject*)b;
- if (other == mp || other->ma_used == 0)
+ if (other == so || other->used == 0)
/* a.update(a) or a.update({}); nothing to do */
return 0;
/* Do one big resize at the start, rather than
* incrementally resizing as we insert new items. Expect
* that there will be no (or few) overlapping keys.
*/
- if ((mp->ma_fill + other->ma_used)*3 >= (mp->ma_mask+1)*2) {
- if (set_table_resize(mp, (mp->ma_used + other->ma_used)*2) != 0)
+ if ((so->fill + other->used)*3 >= (so->mask+1)*2) {
+ if (set_table_resize(so, (so->used + other->used)*2) != 0)
return -1;
}
- for (i = 0; i <= other->ma_mask; i++) {
- entry = &other->ma_table[i];
- if (entry->me_key != NULL &&
- entry->me_key != dummy) {
- Py_INCREF(entry->me_key);
- set_insert_key(mp, entry->me_key, entry->me_hash);
+ for (i = 0; i <= other->mask; i++) {
+ entry = &other->table[i];
+ if (entry->key != NULL &&
+ entry->key != dummy) {
+ Py_INCREF(entry->key);
+ set_insert_key(so, entry->key, entry->hash);
}
}
return 0;
}
-static PyTypeObject PysetiterKey_Type; /* Forward */
-static PyObject *set_iter(setobject *);
-
static int
-set_contains_internal(PySetObject *mp, PyObject *key)
+set_contains_internal(PySetObject *so, PyObject *key)
{
long hash;
@@ -551,51 +524,49 @@
if (hash == -1)
return -1;
}
- key = (mp->ma_lookup)(mp, key, hash)->me_key;
+ key = (so->lookup)(so, key, hash)->key;
return key != NULL && key != dummy;
}
+static PyTypeObject PySetIter_Type; /* Forward */
+static PyObject *set_iter(setobject *);
/* Set iterator types */
typedef struct {
PyObject_HEAD
- setobject *di_set; /* Set to NULL when iterator is exhausted */
- int di_used;
- int di_pos;
- PyObject* di_result; /* reusable result tuple for iteritems */
+ setobject *si_set; /* Set to NULL when iterator is exhausted */
+ int si_used;
+ int si_pos;
long len;
} setiterobject;
static PyObject *
set_iter(setobject *so)
{
- setiterobject *di;
- di = PyObject_New(setiterobject, &PysetiterKey_Type);
- if (di == NULL)
+ setiterobject *si = PyObject_New(setiterobject, &PySetIter_Type);
+ if (si == NULL)
return NULL;
Py_INCREF(so);
- di->di_set = so;
- di->di_used = so->ma_used;
- di->di_pos = 0;
- di->len = so->ma_used;
- di->di_result = NULL;
- return (PyObject *)di;
+ si->si_set = so;
+ si->si_used = so->used;
+ si->si_pos = 0;
+ si->len = so->used;
+ return (PyObject *)si;
}
static void
-setiter_dealloc(setiterobject *di)
+setiter_dealloc(setiterobject *si)
{
- Py_XDECREF(di->di_set);
- Py_XDECREF(di->di_result);
- PyObject_Del(di);
+ Py_XDECREF(si->si_set);
+ PyObject_Del(si);
}
static int
-setiter_len(setiterobject *di)
+setiter_len(setiterobject *si)
{
- if (di->di_set != NULL && di->di_used == di->di_set->ma_used)
- return di->len;
+ if (si->si_set != NULL && si->si_used == si->si_set->used)
+ return si->len;
return 0;
}
@@ -604,49 +575,49 @@
0, /* sq_concat */
};
-static PyObject *setiter_iternextkey(setiterobject *di)
+static PyObject *setiter_iternextkey(setiterobject *si)
{
PyObject *key;
register int i, mask;
register setentry *ep;
- setobject *d = di->di_set;
+ setobject *d = si->si_set;
if (d == NULL)
return NULL;
assert (PyAnySet_Check(d));
- if (di->di_used != d->ma_used) {
+ if (si->si_used != d->used) {
PyErr_SetString(PyExc_RuntimeError,
"Set changed size during iteration");
- di->di_used = -1; /* Make this state sticky */
+ si->si_used = -1; /* Make this state sticky */
return NULL;
}
- i = di->di_pos;
+ i = si->si_pos;
if (i < 0)
goto fail;
- ep = d->ma_table;
- mask = d->ma_mask;
- while (i <= mask && (ep[i].me_key == NULL || ep[i].me_key == dummy))
+ ep = d->table;
+ mask = d->mask;
+ while (i <= mask && (ep[i].key == NULL || ep[i].key == dummy))
i++;
- di->di_pos = i+1;
+ si->si_pos = i+1;
if (i > mask)
goto fail;
- di->len--;
- key = ep[i].me_key;
+ si->len--;
+ key = ep[i].key;
Py_INCREF(key);
return key;
fail:
Py_DECREF(d);
- di->di_set = NULL;
+ si->si_set = NULL;
return NULL;
}
-PyTypeObject PysetiterKey_Type = {
+PyTypeObject PySetIter_Type = {
PyObject_HEAD_INIT(&PyType_Type)
0, /* ob_size */
- "Set-keyiterator", /* tp_name */
+ "Set-keyiterator", /* tp_name */
sizeof(setiterobject), /* tp_basicsize */
0, /* tp_itemsize */
/* methods */
@@ -748,8 +719,7 @@
return NULL;
EMPTY_TO_MINSIZE(so);
- so->ma_lookup = set_lookkey_string;
- //_PyObject_GC_TRACK(so);
+ so->lookup = set_lookkey_string;
so->hash = -1;
so->weakreflist = NULL;
@@ -762,7 +732,6 @@
Py_DECREF(tmp);
}
- assert (so->hash == -1);
return (PyObject *)so;
}
@@ -790,21 +759,21 @@
set_dealloc(PySetObject *so)
{
register setentry *ep;
- int fill = so->ma_fill;
+ int fill = so->fill;
PyObject_GC_UnTrack(so);
Py_TRASHCAN_SAFE_BEGIN(so)
if (so->weakreflist != NULL)
PyObject_ClearWeakRefs((PyObject *) so);
- for (ep = so->ma_table; fill > 0; ep++) {
- if (ep->me_key) {
+ for (ep = so->table; fill > 0; ep++) {
+ if (ep->key) {
--fill;
- Py_DECREF(ep->me_key);
+ Py_DECREF(ep->key);
}
}
- if (so->ma_table != so->ma_smalltable)
- PyMem_DEL(so->ma_table);
+ if (so->table != so->smalltable)
+ PyMem_DEL(so->table);
so->ob_type->tp_free(so);
Py_TRASHCAN_SAFE_END(so)
@@ -813,21 +782,18 @@
static int
set_traverse(PySetObject *so, visitproc visit, void *arg)
{
- int i = 0, err;
+ int i = 0;
PyObject *pk;
- while (set_next_internal(so, &i, &pk)) {
- err = visit(pk, arg);
- if (err)
- return err;
- }
+ while (set_next_internal(so, &i, &pk))
+ Py_VISIT(pk);
return 0;
}
static int
set_len(PyObject *so)
{
- return ((PySetObject *)so)->ma_used;
+ return ((PySetObject *)so)->used;
}
static void
@@ -835,28 +801,28 @@
{
int t;
PySetEntry *u;
- PySetEntry *(*f)(PySetObject *mp, PyObject *key, long hash);
+ PySetEntry *(*f)(PySetObject *so, PyObject *key, long hash);
PySetEntry tab[PySet_MINSIZE];
long h;
- t = a->ma_fill; a->ma_fill = b->ma_fill; b->ma_fill = t;
- t = a->ma_used; a->ma_used = b->ma_used; b->ma_used = t;
- t = a->ma_mask; a->ma_mask = b->ma_mask; b->ma_mask = t;
+ t = a->fill; a->fill = b->fill; b->fill = t;
+ t = a->used; a->used = b->used; b->used = t;
+ t = a->mask; a->mask = b->mask; b->mask = t;
- u = a->ma_table;
- if (a->ma_table == a->ma_smalltable)
- u = b->ma_smalltable;
- a->ma_table = b->ma_table;
- if (b->ma_table == b->ma_smalltable)
- a->ma_table = a->ma_smalltable;
- b->ma_table = u;
+ u = a->table;
+ if (a->table == a->smalltable)
+ u = b->smalltable;
+ a->table = b->table;
+ if (b->table == b->smalltable)
+ a->table = a->smalltable;
+ b->table = u;
- f = a->ma_lookup; a->ma_lookup = b->ma_lookup; b->ma_lookup = f;
+ f = a->lookup; a->lookup = b->lookup; b->lookup = f;
- if (a->ma_table == a->ma_smalltable || b->ma_table == b->ma_smalltable) {
- memcpy(tab, a->ma_smalltable, sizeof(tab));
- memcpy(a->ma_smalltable, b->ma_smalltable, sizeof(tab));
- memcpy(b->ma_smalltable, tab, sizeof(tab));
+ if (a->table == a->smalltable || b->table == b->smalltable) {
+ memcpy(tab, a->smalltable, sizeof(tab));
+ memcpy(a->smalltable, b->smalltable, sizeof(tab));
+ memcpy(b->smalltable, tab, sizeof(tab));
}
h = a->hash; a->hash = b->hash; b->hash = h;
@@ -1466,6 +1432,7 @@
set_remove(PySetObject *so, PyObject *item)
{
PyObject *tmp, *result;
+ int rv;
if (PyType_IsSubtype(item->ob_type, &PySet_Type)) {
tmp = make_new_set(&PyFrozenSet_Type, NULL);
@@ -1478,8 +1445,13 @@
return result;
}
- if (set_remove_internal(so, item) == -1)
+ rv = set_discard_internal(so, item);
+ if (rv == -1)
+ return NULL;
+ else if (rv == DISCARD_NOTFOUND) {
+ PyErr_SetObject(PyExc_KeyError, item);
return NULL;
+ }
Py_RETURN_NONE;
}
@@ -1519,14 +1491,21 @@
{
PyObject *key;
int pos = 0;
+ int rv;
if (!set_next_internal(so, &pos, &key)) {
PyErr_SetString(PyExc_KeyError, "pop from an empty set");
return NULL;
}
Py_INCREF(key);
- if (set_remove_internal(so, key) == -1) {
+
+ rv = set_discard_internal(so, key);
+ if (rv == -1) {
+ Py_DECREF(key);
+ return NULL;
+ } else if (rv == DISCARD_NOTFOUND) {
Py_DECREF(key);
+ PyErr_SetObject(PyExc_KeyError, key);
return NULL;
}
return key;
Index: setobject.h
===================================================================
RCS file: /cvsroot/python/python/nondist/sandbox/set/setobject.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- setobject.h 22 Jul 2005 15:32:30 -0000 1.1
+++ setobject.h 30 Jul 2005 21:07:28 -0000 1.2
@@ -10,16 +10,16 @@
/*
There are three kinds of slots in the table:
-1. Unused: me_key == NULL
-2. Active: me_key != NULL and me_key != dummy
-3. Dummy: me_key == dummy
+1. Unused: key == NULL
+2. Active: key != NULL and key != dummy
+3. Dummy: key == dummy
*/
#define PySet_MINSIZE 8
typedef struct {
- long me_hash; /* cached hash code of me_key */
- PyObject *me_key;
+ long hash; /* cached hash code for the entry key */
+ PyObject *key;
} PySetEntry;
@@ -31,23 +31,23 @@
struct _setobject {
PyObject_HEAD
- int ma_fill; /* # Active + # Dummy */
- int ma_used; /* # Active */
+ int fill; /* # Active + # Dummy */
+ int used; /* # Active */
- /* The table contains ma_mask + 1 slots, and that's a power of 2.
+ /* The table contains mask + 1 slots, and that's a power of 2.
* We store the mask instead of the size because the mask is more
* frequently needed.
*/
- int ma_mask;
+ int mask;
- /* ma_table points to ma_smalltable for small tables, else to
- * additional malloc'ed memory. ma_table is never NULL! This rule
+ /* table points to smalltable for small tables, else to
+ * additional malloc'ed memory. table is never NULL! This rule
* saves repeated runtime null-tests in the workhorse getitem and
* setitem calls.
*/
- PySetEntry *ma_table;
- PySetEntry *(*ma_lookup)(PySetObject *mp, PyObject *key, long hash);
- PySetEntry ma_smalltable[PySet_MINSIZE];
+ PySetEntry *table;
+ PySetEntry *(*lookup)(PySetObject *so, PyObject *key, long hash);
+ PySetEntry smalltable[PySet_MINSIZE];
long hash; /* only used by frozenset objects */
PyObject *weakreflist; /* List of weak references */
1
0