Kaydet (Commit) a690a996 authored tarafından Raymond Hettinger's avatar Raymond Hettinger

* 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.
üst d456849f
...@@ -477,6 +477,17 @@ class C: ...@@ -477,6 +477,17 @@ class C:
and is known to vary.} and is known to vary.}
\end{funcdesc} \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}} \begin{funcdesc}{getattr}{object, name\optional{, default}}
Return the value of the named attributed of \var{object}. \var{name} 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 must be a string. If the string is the name of one of the object's
...@@ -897,6 +908,14 @@ class C(object): ...@@ -897,6 +908,14 @@ class C(object):
\code{round(0.5)} is \code{1.0} and \code{round(-0.5)} is \code{-1.0}). \code{round(0.5)} is \code{1.0} and \code{round(-0.5)} is \code{-1.0}).
\end{funcdesc} \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} \begin{funcdesc}{setattr}{object, name, value}
This is the counterpart of \function{getattr()}. The arguments are an This is the counterpart of \function{getattr()}. The arguments are an
object, a string and an arbitrary value. The string may name an object, a string and an arbitrary value. The string may name an
......
...@@ -86,6 +86,7 @@ ...@@ -86,6 +86,7 @@
#include "listobject.h" #include "listobject.h"
#include "dictobject.h" #include "dictobject.h"
#include "enumobject.h" #include "enumobject.h"
#include "setobject.h"
#include "methodobject.h" #include "methodobject.h"
#include "moduleobject.h" #include "moduleobject.h"
#include "funcobject.h" #include "funcobject.h"
......
/* 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 */
...@@ -16,7 +16,6 @@ import calendar ...@@ -16,7 +16,6 @@ import calendar
from re import compile as re_compile from re import compile as re_compile
from re import IGNORECASE from re import IGNORECASE
from datetime import date as datetime_date from datetime import date as datetime_date
from sets import ImmutableSet as sets_ImmutableSet
try: try:
from thread import allocate_lock as _thread_allocate_lock from thread import allocate_lock as _thread_allocate_lock
except: except:
...@@ -165,11 +164,11 @@ class LocaleTime(object): ...@@ -165,11 +164,11 @@ class LocaleTime(object):
time.tzset() time.tzset()
except AttributeError: except AttributeError:
pass pass
no_saving = sets_ImmutableSet(["utc", "gmt", time.tzname[0].lower()]) no_saving = frozenset(["utc", "gmt", time.tzname[0].lower()])
if time.daylight: if time.daylight:
has_saving = sets_ImmutableSet([time.tzname[1].lower()]) has_saving = frozenset([time.tzname[1].lower()])
else: else:
has_saving = sets_ImmutableSet() has_saving = frozenset()
self.timezone = (no_saving, has_saving) self.timezone = (no_saving, has_saving)
......
...@@ -75,7 +75,6 @@ import traceback ...@@ -75,7 +75,6 @@ import traceback
import random import random
import cStringIO import cStringIO
import warnings import warnings
from sets import Set
# I see no other way to suppress these warnings; # I see no other way to suppress these warnings;
# putting them in test_grammar.py has no effect: # 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, ...@@ -306,7 +305,7 @@ def main(tests=None, testdir=None, verbose=0, quiet=0, generate=0,
e = _ExpectedSkips() e = _ExpectedSkips()
plat = sys.platform plat = sys.platform
if e.isvalid(): if e.isvalid():
surprise = Set(skipped) - e.getexpected() - Set(resource_denieds) surprise = set(skipped) - e.getexpected() - set(resource_denieds)
if surprise: if surprise:
print count(len(surprise), "skip"), \ print count(len(surprise), "skip"), \
"unexpected on", plat + ":" "unexpected on", plat + ":"
...@@ -948,7 +947,7 @@ class _ExpectedSkips: ...@@ -948,7 +947,7 @@ class _ExpectedSkips:
self.valid = False self.valid = False
if sys.platform in _expectations: if sys.platform in _expectations:
s = _expectations[sys.platform] s = _expectations[sys.platform]
self.expected = Set(s.split()) self.expected = set(s.split())
if not os.path.supports_unicode_filenames: if not os.path.supports_unicode_filenames:
self.expected.add('test_pep277') self.expected.add('test_pep277')
......
...@@ -2,7 +2,6 @@ import unittest ...@@ -2,7 +2,6 @@ import unittest
from test import test_support from test import test_support
from test.test_support import verify, verbose from test.test_support import verify, verbose
from sets import Set
import sys import sys
import warnings import warnings
...@@ -43,8 +42,8 @@ class AllTest(unittest.TestCase): ...@@ -43,8 +42,8 @@ class AllTest(unittest.TestCase):
exec "from %s import *" % modname in names exec "from %s import *" % modname in names
if names.has_key("__builtins__"): if names.has_key("__builtins__"):
del names["__builtins__"] del names["__builtins__"]
keys = Set(names) keys = set(names)
all = Set(sys.modules[modname].__all__) all = set(sys.modules[modname].__all__)
verify(keys==all, "%s != %s" % (keys, all)) verify(keys==all, "%s != %s" % (keys, all))
def test_all(self): def test_all(self):
......
...@@ -2,7 +2,6 @@ ...@@ -2,7 +2,6 @@
import test.test_support, unittest import test.test_support, unittest
from test.test_support import fcmp, have_unicode, TESTFN, unlink from test.test_support import fcmp, have_unicode, TESTFN, unlink
from sets import Set
import sys, warnings, cStringIO import sys, warnings, cStringIO
warnings.filterwarnings("ignore", "hex../oct.. of negative int", warnings.filterwarnings("ignore", "hex../oct.. of negative int",
...@@ -1104,9 +1103,9 @@ class BuiltinTest(unittest.TestCase): ...@@ -1104,9 +1103,9 @@ class BuiltinTest(unittest.TestCase):
get_vars_f2 = staticmethod(get_vars_f2) get_vars_f2 = staticmethod(get_vars_f2)
def test_vars(self): def test_vars(self):
self.assertEqual(Set(vars()), Set(dir())) self.assertEqual(set(vars()), set(dir()))
import sys 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_f0(), {})
self.assertEqual(self.get_vars_f2(), {'a': 1, 'b': 2}) self.assertEqual(self.get_vars_f2(), {'a': 1, 'b': 2})
self.assertRaises(TypeError, vars, 42, 42) self.assertRaises(TypeError, vars, 42, 42)
......
import unittest import unittest
from sets import Set
from test import test_support from test import test_support
...@@ -105,8 +104,8 @@ class EnumerateTestCase(unittest.TestCase): ...@@ -105,8 +104,8 @@ class EnumerateTestCase(unittest.TestCase):
def test_tuple_reuse(self): def test_tuple_reuse(self):
# Tests an implementation detail where tuple is reused # Tests an implementation detail where tuple is reused
# whenever nothing else holds a reference to it # 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, 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, enumerate(self.seq)))), min(1,len(self.seq)))
class MyEnum(enumerate): class MyEnum(enumerate):
pass pass
......
...@@ -2,7 +2,6 @@ import unittest ...@@ -2,7 +2,6 @@ import unittest
from test.test_support import run_unittest, TESTFN from test.test_support import run_unittest, TESTFN
import glob import glob
import os import os
from sets import Set
def mkdirs(fname): def mkdirs(fname):
if os.path.exists(fname) or fname == '': if os.path.exists(fname) or fname == '':
...@@ -62,7 +61,7 @@ class GlobTests(unittest.TestCase): ...@@ -62,7 +61,7 @@ class GlobTests(unittest.TestCase):
return glob.glob(p) return glob.glob(p)
def assertSequencesEqual_noorder(self, l1, l2): def assertSequencesEqual_noorder(self, l1, l2):
self.assertEqual(Set(l1), Set(l2)) self.assertEqual(set(l1), set(l2))
def test_glob_literal(self): def test_glob_literal(self):
eq = self.assertSequencesEqual_noorder eq = self.assertSequencesEqual_noorder
......
...@@ -7,7 +7,6 @@ import unittest, sys ...@@ -7,7 +7,6 @@ import unittest, sys
from types import ClassType, FunctionType, MethodType from types import ClassType, FunctionType, MethodType
import pyclbr import pyclbr
from unittest import TestCase from unittest import TestCase
from sets import Set
# This next line triggers an error on old versions of pyclbr. # This next line triggers an error on old versions of pyclbr.
...@@ -24,7 +23,7 @@ class PyclbrTest(TestCase): ...@@ -24,7 +23,7 @@ class PyclbrTest(TestCase):
def assertListEq(self, l1, l2, ignore): def assertListEq(self, l1, l2, ignore):
''' succeed iff {l1} - {ignore} == {l2} - {ignore} ''' ''' succeed iff {l1} - {ignore} == {l2} - {ignore} '''
missing = (Set(l1) ^ Set(l2)) - Set(ignore) missing = (set(l1) ^ set(l2)) - set(ignore)
if missing: if missing:
print >>sys.stderr, "l1=%r\nl2=%r\nignore=%r" % (l1, l2, ignore) print >>sys.stderr, "l1=%r\nl2=%r\nignore=%r" % (l1, l2, ignore)
self.fail("%r missing" % missing.pop()) self.fail("%r missing" % missing.pop())
......
...@@ -6,7 +6,6 @@ import time ...@@ -6,7 +6,6 @@ import time
import pickle import pickle
import warnings import warnings
from math import log, exp, sqrt, pi from math import log, exp, sqrt, pi
from sets import Set
from test import test_support from test import test_support
class TestBasicOps(unittest.TestCase): class TestBasicOps(unittest.TestCase):
...@@ -64,9 +63,9 @@ class TestBasicOps(unittest.TestCase): ...@@ -64,9 +63,9 @@ class TestBasicOps(unittest.TestCase):
for k in xrange(N+1): for k in xrange(N+1):
s = self.gen.sample(population, k) s = self.gen.sample(population, k)
self.assertEqual(len(s), k) self.assertEqual(len(s), k)
uniq = Set(s) uniq = set(s)
self.assertEqual(len(uniq), k) 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 self.assertEqual(self.gen.sample([], 0), []) # test edge case N==k==0
def test_sample_distribution(self): def test_sample_distribution(self):
...@@ -89,8 +88,7 @@ class TestBasicOps(unittest.TestCase): ...@@ -89,8 +88,7 @@ class TestBasicOps(unittest.TestCase):
def test_sample_inputs(self): def test_sample_inputs(self):
# SF bug #801342 -- population can be any iterable defining __len__() # 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(range(20), 2)
self.gen.sample(xrange(20), 2) self.gen.sample(xrange(20), 2)
self.gen.sample(dict.fromkeys('abcdefghijklmnopqrst'), 2) self.gen.sample(dict.fromkeys('abcdefghijklmnopqrst'), 2)
...@@ -256,8 +254,8 @@ class MersenneTwister_TestBasicOps(TestBasicOps): ...@@ -256,8 +254,8 @@ class MersenneTwister_TestBasicOps(TestBasicOps):
def test_rangelimits(self): def test_rangelimits(self):
for start, stop in [(-2,0), (-(2**60)-2,-(2**60)), (2**60,2**60+2)]: for start, stop in [(-2,0), (-(2**60)-2,-(2**60)), (2**60,2**60+2)]:
self.assertEqual(Set(range(start,stop)), self.assertEqual(set(range(start,stop)),
Set([self.gen.randrange(start,stop) for i in xrange(100)])) set([self.gen.randrange(start,stop) for i in xrange(100)]))
def test_genrandbits(self): def test_genrandbits(self):
# Verify cross-platform repeatability # Verify cross-platform repeatability
...@@ -364,7 +362,7 @@ class TestModule(unittest.TestCase): ...@@ -364,7 +362,7 @@ class TestModule(unittest.TestCase):
def test__all__(self): def test__all__(self):
# tests validity but not completeness of the __all__ list # 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): def test_main(verbose=None):
testclasses = (WichmannHill_TestBasicOps, testclasses = (WichmannHill_TestBasicOps,
......
This diff is collapsed.
from test.test_support import verbose from test.test_support import verbose
import random import random
from UserList import UserList from UserList import UserList
from sets import Set
nerrors = 0 nerrors = 0
...@@ -230,7 +229,7 @@ class TestSorted(unittest.TestCase): ...@@ -230,7 +229,7 @@ class TestSorted(unittest.TestCase):
self.assertEqual(list.sorted(s), list.sorted(T(s))) self.assertEqual(list.sorted(s), list.sorted(T(s)))
s = ''.join(dict.fromkeys(s).keys()) # unique letters only 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))) self.assertEqual(list.sorted(s), list.sorted(T(s)))
def test_baddecorator(self): def test_baddecorator(self):
......
...@@ -4,7 +4,6 @@ import unittest ...@@ -4,7 +4,6 @@ import unittest
import time import time
import locale import locale
import re import re
import sets
import sys import sys
from test import test_support from test import test_support
...@@ -167,7 +166,7 @@ class TimeRETests(unittest.TestCase): ...@@ -167,7 +166,7 @@ class TimeRETests(unittest.TestCase):
# Make sure when tuple or something has no values no regex is generated. # Make sure when tuple or something has no values no regex is generated.
# Fixes bug #661354 # Fixes bug #661354
test_locale = _strptime.LocaleTime() test_locale = _strptime.LocaleTime()
test_locale.timezone = (sets.ImmutableSet(), sets.ImmutableSet()) test_locale.timezone = (frozenset(), frozenset())
self.failUnless(_strptime.TimeRE(test_locale).pattern("%Z") == '', self.failUnless(_strptime.TimeRE(test_locale).pattern("%Z") == '',
"with timezone == ('',''), TimeRE().pattern('%Z') != ''") "with timezone == ('',''), TimeRE().pattern('%Z') != ''")
......
# Check every path through every method of UserDict # Check every path through every method of UserDict
import test.test_support, unittest import test.test_support, unittest
from sets import Set
import UserDict import UserDict
class TestMappingProtocol(unittest.TestCase): class TestMappingProtocol(unittest.TestCase):
...@@ -69,7 +67,7 @@ class TestMappingProtocol(unittest.TestCase): ...@@ -69,7 +67,7 @@ class TestMappingProtocol(unittest.TestCase):
self.assert_(hasattr(iter, 'next')) self.assert_(hasattr(iter, 'next'))
self.assert_(hasattr(iter, '__iter__')) self.assert_(hasattr(iter, '__iter__'))
x = list(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(d.iterkeys(), d.keys(), self.reference.keys())
check_iterandlist(iter(d), d.keys(), self.reference.keys()) check_iterandlist(iter(d), d.keys(), self.reference.keys())
check_iterandlist(d.itervalues(), d.values(), self.reference.values()) check_iterandlist(d.itervalues(), d.values(), self.reference.values())
...@@ -242,7 +240,7 @@ class UserDictTest(TestMappingProtocol): ...@@ -242,7 +240,7 @@ class UserDictTest(TestMappingProtocol):
for k in u2: for k in u2:
ikeys.append(k) ikeys.append(k)
keys = u2.keys() keys = u2.keys()
self.assertEqual(Set(ikeys), Set(keys)) self.assertEqual(set(ikeys), set(keys))
# Test setdefault # Test setdefault
t = UserDict.UserDict() t = UserDict.UserDict()
......
...@@ -4,7 +4,6 @@ import UserList ...@@ -4,7 +4,6 @@ import UserList
import weakref import weakref
from test import test_support from test import test_support
from sets import Set
class C: class C:
...@@ -392,7 +391,7 @@ class MappingTestCase(TestBase): ...@@ -392,7 +391,7 @@ class MappingTestCase(TestBase):
"wrong object returned by weak dict!") "wrong object returned by weak dict!")
items1 = dict.items() items1 = dict.items()
items2 = dict.copy().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!") "cloning of weak-keyed dictionary did not work!")
del items1, items2 del items1, items2
self.assert_(len(dict) == self.COUNT) self.assert_(len(dict) == self.COUNT)
......
...@@ -275,6 +275,7 @@ OBJECT_OBJS= \ ...@@ -275,6 +275,7 @@ OBJECT_OBJS= \
Objects/object.o \ Objects/object.o \
Objects/obmalloc.o \ Objects/obmalloc.o \
Objects/rangeobject.o \ Objects/rangeobject.o \
Objects/setobject.o \
Objects/sliceobject.o \ Objects/sliceobject.o \
Objects/stringobject.o \ Objects/stringobject.o \
Objects/structseq.o \ Objects/structseq.o \
...@@ -500,6 +501,7 @@ PYTHON_HEADERS= \ ...@@ -500,6 +501,7 @@ PYTHON_HEADERS= \
Include/pystate.h \ Include/pystate.h \
Include/pythonrun.h \ Include/pythonrun.h \
Include/rangeobject.h \ Include/rangeobject.h \
Include/setobject.h \
Include/sliceobject.h \ Include/sliceobject.h \
Include/stringobject.h \ Include/stringobject.h \
Include/structseq.h \ Include/structseq.h \
......
...@@ -12,6 +12,8 @@ What's New in Python 2.4 alpha 1? ...@@ -12,6 +12,8 @@ What's New in Python 2.4 alpha 1?
Core and builtins Core and builtins
----------------- -----------------
- Added two builtin types, set() and frozenset().
- Critical bugfix, for SF bug 840829: if cyclic garbage collection - Critical bugfix, for SF bug 840829: if cyclic garbage collection
happened to occur during a weakref callback for a new-style class happened to occur during a weakref callback for a new-style class
instance, subtle memory corruption was the result (in a release build; instance, subtle memory corruption was the result (in a release build;
......
This diff is collapsed.
...@@ -467,6 +467,10 @@ SOURCE=..\Modules\rotormodule.c ...@@ -467,6 +467,10 @@ SOURCE=..\Modules\rotormodule.c
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=..\Objects\setobject.c
# End Source File
# Begin Source File
SOURCE=..\Modules\shamodule.c SOURCE=..\Modules\shamodule.c
# End Source File # End Source File
# Begin Source File # Begin Source File
......
...@@ -2116,12 +2116,14 @@ _PyBuiltin_Init(void) ...@@ -2116,12 +2116,14 @@ _PyBuiltin_Init(void)
SETBUILTIN("dict", &PyDict_Type); SETBUILTIN("dict", &PyDict_Type);
SETBUILTIN("enumerate", &PyEnum_Type); SETBUILTIN("enumerate", &PyEnum_Type);
SETBUILTIN("float", &PyFloat_Type); SETBUILTIN("float", &PyFloat_Type);
SETBUILTIN("frozenset", &PyFrozenSet_Type);
SETBUILTIN("property", &PyProperty_Type); SETBUILTIN("property", &PyProperty_Type);
SETBUILTIN("int", &PyInt_Type); SETBUILTIN("int", &PyInt_Type);
SETBUILTIN("list", &PyList_Type); SETBUILTIN("list", &PyList_Type);
SETBUILTIN("long", &PyLong_Type); SETBUILTIN("long", &PyLong_Type);
SETBUILTIN("object", &PyBaseObject_Type); SETBUILTIN("object", &PyBaseObject_Type);
SETBUILTIN("reversed", &PyReversed_Type); SETBUILTIN("reversed", &PyReversed_Type);
SETBUILTIN("set", &PySet_Type);
SETBUILTIN("slice", &PySlice_Type); SETBUILTIN("slice", &PySlice_Type);
SETBUILTIN("staticmethod", &PyStaticMethod_Type); SETBUILTIN("staticmethod", &PyStaticMethod_Type);
SETBUILTIN("str", &PyString_Type); SETBUILTIN("str", &PyString_Type);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment