* Migrate set() and frozenset() from the sandbox.

* Install the unittests, docs, newsitem, include file, and makefile update.
* Exercise the new functions whereever sets.py was being used.

Includes the docs for libfuncs.tex.  Separate docs for the types are
forthcoming.
This commit is contained in:
Raymond Hettinger 2003-11-16 16:17:49 +00:00
parent d456849f19
commit a690a9967e
21 changed files with 2338 additions and 40 deletions

View File

@ -477,6 +477,17 @@ class C:
and is known to vary.}
\end{funcdesc}
\begin{funcdesc}{frozenset}{\optional{iterable}}
Return a frozenset object whose elements are taken from \var{iterable}.
Frozensets are sets that have no update methods but can be hashed and
used as members of other sets or as dictionary keys. The elements of
a frozenset must be immutable themselves. To represent sets of sets,
the inner sets should also be \class{frozenset} objects. If
\var{iterable} is not specified, returns a new empty set,
\code{frozenset([])}.
\versionadded{2.4}
\end{funcdesc}
\begin{funcdesc}{getattr}{object, name\optional{, default}}
Return the value of the named attributed of \var{object}. \var{name}
must be a string. If the string is the name of one of the object's
@ -897,6 +908,14 @@ class C(object):
\code{round(0.5)} is \code{1.0} and \code{round(-0.5)} is \code{-1.0}).
\end{funcdesc}
\begin{funcdesc}{set}{\optional{iterable}}
Return a set whose elements are taken from \var{iterable}. The elements
must be immutable. To represent sets of sets, the inner sets should
be \class{frozenset} objects. If \var{iterable} is not specified,
returns a new empty set, \code{set([])}.
\versionadded{2.4}
\end{funcdesc}
\begin{funcdesc}{setattr}{object, name, value}
This is the counterpart of \function{getattr()}. The arguments are an
object, a string and an arbitrary value. The string may name an

View File

@ -86,6 +86,7 @@
#include "listobject.h"
#include "dictobject.h"
#include "enumobject.h"
#include "setobject.h"
#include "methodobject.h"
#include "moduleobject.h"
#include "funcobject.h"

26
Include/setobject.h Normal file
View File

@ -0,0 +1,26 @@
/* Set object interface */
#ifndef Py_SETOBJECT_H
#define Py_SETOBJECT_H
#ifdef __cplusplus
extern "C" {
#endif
/*
This data structure is shared by set and frozenset objects.
*/
typedef struct {
PyObject_HEAD
PyObject *data;
long hash; /* only used by frozenset objects */
} PySetObject;
PyAPI_DATA(PyTypeObject) PySet_Type;
PyAPI_DATA(PyTypeObject) PyFrozenSet_Type;
#ifdef __cplusplus
}
#endif
#endif /* !Py_SETOBJECT_H */

View File

@ -16,7 +16,6 @@ import calendar
from re import compile as re_compile
from re import IGNORECASE
from datetime import date as datetime_date
from sets import ImmutableSet as sets_ImmutableSet
try:
from thread import allocate_lock as _thread_allocate_lock
except:
@ -165,11 +164,11 @@ class LocaleTime(object):
time.tzset()
except AttributeError:
pass
no_saving = sets_ImmutableSet(["utc", "gmt", time.tzname[0].lower()])
no_saving = frozenset(["utc", "gmt", time.tzname[0].lower()])
if time.daylight:
has_saving = sets_ImmutableSet([time.tzname[1].lower()])
has_saving = frozenset([time.tzname[1].lower()])
else:
has_saving = sets_ImmutableSet()
has_saving = frozenset()
self.timezone = (no_saving, has_saving)

View File

@ -75,7 +75,6 @@ import traceback
import random
import cStringIO
import warnings
from sets import Set
# I see no other way to suppress these warnings;
# putting them in test_grammar.py has no effect:
@ -306,7 +305,7 @@ def main(tests=None, testdir=None, verbose=0, quiet=0, generate=0,
e = _ExpectedSkips()
plat = sys.platform
if e.isvalid():
surprise = Set(skipped) - e.getexpected() - Set(resource_denieds)
surprise = set(skipped) - e.getexpected() - set(resource_denieds)
if surprise:
print count(len(surprise), "skip"), \
"unexpected on", plat + ":"
@ -948,7 +947,7 @@ class _ExpectedSkips:
self.valid = False
if sys.platform in _expectations:
s = _expectations[sys.platform]
self.expected = Set(s.split())
self.expected = set(s.split())
if not os.path.supports_unicode_filenames:
self.expected.add('test_pep277')

View File

@ -2,7 +2,6 @@ import unittest
from test import test_support
from test.test_support import verify, verbose
from sets import Set
import sys
import warnings
@ -43,8 +42,8 @@ class AllTest(unittest.TestCase):
exec "from %s import *" % modname in names
if names.has_key("__builtins__"):
del names["__builtins__"]
keys = Set(names)
all = Set(sys.modules[modname].__all__)
keys = set(names)
all = set(sys.modules[modname].__all__)
verify(keys==all, "%s != %s" % (keys, all))
def test_all(self):

View File

@ -2,7 +2,6 @@
import test.test_support, unittest
from test.test_support import fcmp, have_unicode, TESTFN, unlink
from sets import Set
import sys, warnings, cStringIO
warnings.filterwarnings("ignore", "hex../oct.. of negative int",
@ -1104,9 +1103,9 @@ class BuiltinTest(unittest.TestCase):
get_vars_f2 = staticmethod(get_vars_f2)
def test_vars(self):
self.assertEqual(Set(vars()), Set(dir()))
self.assertEqual(set(vars()), set(dir()))
import sys
self.assertEqual(Set(vars(sys)), Set(dir(sys)))
self.assertEqual(set(vars(sys)), set(dir(sys)))
self.assertEqual(self.get_vars_f0(), {})
self.assertEqual(self.get_vars_f2(), {'a': 1, 'b': 2})
self.assertRaises(TypeError, vars, 42, 42)

View File

@ -1,5 +1,4 @@
import unittest
from sets import Set
from test import test_support
@ -105,8 +104,8 @@ class EnumerateTestCase(unittest.TestCase):
def test_tuple_reuse(self):
# Tests an implementation detail where tuple is reused
# whenever nothing else holds a reference to it
self.assertEqual(len(Set(map(id, list(enumerate(self.seq))))), len(self.seq))
self.assertEqual(len(Set(map(id, enumerate(self.seq)))), min(1,len(self.seq)))
self.assertEqual(len(set(map(id, list(enumerate(self.seq))))), len(self.seq))
self.assertEqual(len(set(map(id, enumerate(self.seq)))), min(1,len(self.seq)))
class MyEnum(enumerate):
pass

View File

@ -2,7 +2,6 @@ import unittest
from test.test_support import run_unittest, TESTFN
import glob
import os
from sets import Set
def mkdirs(fname):
if os.path.exists(fname) or fname == '':
@ -62,7 +61,7 @@ class GlobTests(unittest.TestCase):
return glob.glob(p)
def assertSequencesEqual_noorder(self, l1, l2):
self.assertEqual(Set(l1), Set(l2))
self.assertEqual(set(l1), set(l2))
def test_glob_literal(self):
eq = self.assertSequencesEqual_noorder

View File

@ -7,7 +7,6 @@ import unittest, sys
from types import ClassType, FunctionType, MethodType
import pyclbr
from unittest import TestCase
from sets import Set
# This next line triggers an error on old versions of pyclbr.
@ -24,7 +23,7 @@ class PyclbrTest(TestCase):
def assertListEq(self, l1, l2, ignore):
''' succeed iff {l1} - {ignore} == {l2} - {ignore} '''
missing = (Set(l1) ^ Set(l2)) - Set(ignore)
missing = (set(l1) ^ set(l2)) - set(ignore)
if missing:
print >>sys.stderr, "l1=%r\nl2=%r\nignore=%r" % (l1, l2, ignore)
self.fail("%r missing" % missing.pop())

View File

@ -6,7 +6,6 @@ import time
import pickle
import warnings
from math import log, exp, sqrt, pi
from sets import Set
from test import test_support
class TestBasicOps(unittest.TestCase):
@ -64,9 +63,9 @@ class TestBasicOps(unittest.TestCase):
for k in xrange(N+1):
s = self.gen.sample(population, k)
self.assertEqual(len(s), k)
uniq = Set(s)
uniq = set(s)
self.assertEqual(len(uniq), k)
self.failUnless(uniq <= Set(population))
self.failUnless(uniq <= set(population))
self.assertEqual(self.gen.sample([], 0), []) # test edge case N==k==0
def test_sample_distribution(self):
@ -89,8 +88,7 @@ class TestBasicOps(unittest.TestCase):
def test_sample_inputs(self):
# SF bug #801342 -- population can be any iterable defining __len__()
from sets import Set
self.gen.sample(Set(range(20)), 2)
self.gen.sample(set(range(20)), 2)
self.gen.sample(range(20), 2)
self.gen.sample(xrange(20), 2)
self.gen.sample(dict.fromkeys('abcdefghijklmnopqrst'), 2)
@ -256,8 +254,8 @@ class MersenneTwister_TestBasicOps(TestBasicOps):
def test_rangelimits(self):
for start, stop in [(-2,0), (-(2**60)-2,-(2**60)), (2**60,2**60+2)]:
self.assertEqual(Set(range(start,stop)),
Set([self.gen.randrange(start,stop) for i in xrange(100)]))
self.assertEqual(set(range(start,stop)),
set([self.gen.randrange(start,stop) for i in xrange(100)]))
def test_genrandbits(self):
# Verify cross-platform repeatability
@ -364,7 +362,7 @@ class TestModule(unittest.TestCase):
def test__all__(self):
# tests validity but not completeness of the __all__ list
self.failUnless(Set(random.__all__) <= Set(dir(random)))
self.failUnless(set(random.__all__) <= set(dir(random)))
def test_main(verbose=None):
testclasses = (WichmannHill_TestBasicOps,

1183
Lib/test/test_set.py Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,6 @@
from test.test_support import verbose
import random
from UserList import UserList
from sets import Set
nerrors = 0
@ -230,7 +229,7 @@ class TestSorted(unittest.TestCase):
self.assertEqual(list.sorted(s), list.sorted(T(s)))
s = ''.join(dict.fromkeys(s).keys()) # unique letters only
for T in [unicode, Set, list, tuple, dict.fromkeys]:
for T in [unicode, set, frozenset, list, tuple, dict.fromkeys]:
self.assertEqual(list.sorted(s), list.sorted(T(s)))
def test_baddecorator(self):

View File

@ -4,7 +4,6 @@ import unittest
import time
import locale
import re
import sets
import sys
from test import test_support
@ -167,7 +166,7 @@ class TimeRETests(unittest.TestCase):
# Make sure when tuple or something has no values no regex is generated.
# Fixes bug #661354
test_locale = _strptime.LocaleTime()
test_locale.timezone = (sets.ImmutableSet(), sets.ImmutableSet())
test_locale.timezone = (frozenset(), frozenset())
self.failUnless(_strptime.TimeRE(test_locale).pattern("%Z") == '',
"with timezone == ('',''), TimeRE().pattern('%Z') != ''")

View File

@ -1,8 +1,6 @@
# Check every path through every method of UserDict
import test.test_support, unittest
from sets import Set
import UserDict
class TestMappingProtocol(unittest.TestCase):
@ -69,7 +67,7 @@ class TestMappingProtocol(unittest.TestCase):
self.assert_(hasattr(iter, 'next'))
self.assert_(hasattr(iter, '__iter__'))
x = list(iter)
self.assert_(Set(x)==Set(lst)==Set(ref))
self.assert_(set(x)==set(lst)==set(ref))
check_iterandlist(d.iterkeys(), d.keys(), self.reference.keys())
check_iterandlist(iter(d), d.keys(), self.reference.keys())
check_iterandlist(d.itervalues(), d.values(), self.reference.values())
@ -242,7 +240,7 @@ class UserDictTest(TestMappingProtocol):
for k in u2:
ikeys.append(k)
keys = u2.keys()
self.assertEqual(Set(ikeys), Set(keys))
self.assertEqual(set(ikeys), set(keys))
# Test setdefault
t = UserDict.UserDict()

View File

@ -4,7 +4,6 @@ import UserList
import weakref
from test import test_support
from sets import Set
class C:
@ -392,7 +391,7 @@ class MappingTestCase(TestBase):
"wrong object returned by weak dict!")
items1 = dict.items()
items2 = dict.copy().items()
self.assert_(Set(items1) == Set(items2),
self.assert_(set(items1) == set(items2),
"cloning of weak-keyed dictionary did not work!")
del items1, items2
self.assert_(len(dict) == self.COUNT)

View File

@ -275,6 +275,7 @@ OBJECT_OBJS= \
Objects/object.o \
Objects/obmalloc.o \
Objects/rangeobject.o \
Objects/setobject.o \
Objects/sliceobject.o \
Objects/stringobject.o \
Objects/structseq.o \
@ -500,6 +501,7 @@ PYTHON_HEADERS= \
Include/pystate.h \
Include/pythonrun.h \
Include/rangeobject.h \
Include/setobject.h \
Include/sliceobject.h \
Include/stringobject.h \
Include/structseq.h \

View File

@ -12,6 +12,8 @@ What's New in Python 2.4 alpha 1?
Core and builtins
-----------------
- Added two builtin types, set() and frozenset().
- Critical bugfix, for SF bug 840829: if cyclic garbage collection
happened to occur during a weakref callback for a new-style class
instance, subtle memory corruption was the result (in a release build;

1073
Objects/setobject.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -467,6 +467,10 @@ SOURCE=..\Modules\rotormodule.c
# End Source File
# Begin Source File
SOURCE=..\Objects\setobject.c
# End Source File
# Begin Source File
SOURCE=..\Modules\shamodule.c
# End Source File
# Begin Source File

View File

@ -2116,12 +2116,14 @@ _PyBuiltin_Init(void)
SETBUILTIN("dict", &PyDict_Type);
SETBUILTIN("enumerate", &PyEnum_Type);
SETBUILTIN("float", &PyFloat_Type);
SETBUILTIN("frozenset", &PyFrozenSet_Type);
SETBUILTIN("property", &PyProperty_Type);
SETBUILTIN("int", &PyInt_Type);
SETBUILTIN("list", &PyList_Type);
SETBUILTIN("long", &PyLong_Type);
SETBUILTIN("object", &PyBaseObject_Type);
SETBUILTIN("reversed", &PyReversed_Type);
SETBUILTIN("set", &PySet_Type);
SETBUILTIN("slice", &PySlice_Type);
SETBUILTIN("staticmethod", &PyStaticMethod_Type);
SETBUILTIN("str", &PyString_Type);