Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
cpython
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
cpython
Commits
5079cdf0
Commit
5079cdf0
authored
Aug 16, 2005
by
Raymond Hettinger
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Numerous fix-ups to C API and docs. Added tests for C API.
parent
a64ab48a
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
148 additions
and
26 deletions
+148
-26
Doc/api/concrete.tex
Doc/api/concrete.tex
+21
-15
Include/setobject.h
Include/setobject.h
+1
-1
Lib/test/test_set.py
Lib/test/test_set.py
+6
-1
Objects/setobject.c
Objects/setobject.c
+120
-9
No files found.
Doc/api/concrete.tex
View file @
5079cdf0
...
...
@@ -2959,14 +2959,16 @@ Likewise, the constructor functions work with any iterable Python object.
Returns a new
\class
{
set
}
containing objects returned by the
\var
{
iterable
}
. The
\var
{
iterable
}
may be
\NULL
{}
to create a
new empty set. Returns the new set on success or
\NULL
{}
on
failure.
failure. Raises
\exception
{
TypeError
}
if
\var
{
iterable
}
is
not actually iterable.
\end{cfuncdesc}
\begin{cfuncdesc}
{
PyObject*
}{
PyFrozenSet
_
New
}{
PyObject *iterable
}
Returns a new
\class
{
frozenset
}
containing objects returned by the
\var
{
iterable
}
. The
\var
{
iterable
}
may be
\NULL
{}
to create a
new empty frozenset. Returns the new set on success or
\NULL
{}
on
failure.
failure. Raises
\exception
{
TypeError
}
if
\var
{
iterable
}
is
not actually iterable.
\end{cfuncdesc}
...
...
@@ -2976,7 +2978,7 @@ The following functions and macros are available for instances of
\begin{cfuncdesc}
{
int
}{
PySet
_
Size
}{
PyObject *anyset
}
Returns the length of a
\class
{
set
}
or
\class
{
frozenset
}
object.
Equivalent to
\samp
{
len(
\var
{
anyset
}
)
}
. Raises a
\exception
{
PyExc
_
SystemError
}
if
the argument
is not a
\class
{
set
}
,
\exception
{
PyExc
_
SystemError
}
if
\var
{
anyset
}
is not a
\class
{
set
}
,
\class
{
frozenset
}
, or an instance of a subtype.
\bifuncindex
{
len
}
\end{cfuncdesc}
...
...
@@ -2989,15 +2991,9 @@ The following functions and macros are available for instances of
Returns 1 if found, 0 if not found, and -1 if an error is
encountered. Unlike the Python
\method
{__
contains
__
()
}
method, this
function does not automatically convert unhashable sets into temporary
frozensets. Raises a
\exception
{
TypeError
}
if the key is unhashable.
\end{cfuncdesc}
\begin{cfuncdesc}
{
int
}{
PySet
_
Discard
}{
PyObject *anyset, PyObject *key
}
Returns 1 if found and removed, 0 if not found (no action taken),
and -1 if an error is encountered. Does not raise
\exception
{
KeyError
}
for missing keys. Raises a
\exception
{
TypeError
}
if the key is unhashable.
Unlike the Python
\method
{
discard()
}
method, this function does
not automatically convert unhashable sets into temporary frozensets.
frozensets. Raises a
\exception
{
TypeError
}
if the
\var
{
key
}
is unhashable.
Raises
\exception
{
PyExc
_
SystemError
}
if
\var
{
anyset
}
is not a
\class
{
set
}
,
\class
{
frozenset
}
, or an instance of a subtype.
\end{cfuncdesc}
...
...
@@ -3007,17 +3003,27 @@ its subtypes but not for instances of \class{frozenset} or its subtypes.
\begin{cfuncdesc}
{
int
}{
PySet
_
Add
}{
PyObject *set, PyObject *key
}
Adds
\var
{
key
}
to a
\class
{
set
}
instance. Does not apply to
\class
{
frozenset
}
instances. Returns 0 on success or -1 on failure.
Raises a
\exception
{
TypeError
}
if the
key
is unhashable.
Raises a
\exception
{
TypeError
}
if the
\var
{
key
}
is unhashable.
Raises a
\exception
{
MemoryError
}
if there is no room to grow.
Raises a
\exception
{
SystemError
}
if
\var
{
key
}
is an not an instance
Raises a
\exception
{
SystemError
}
if
\var
{
set
}
is an not an instance
of
\class
{
set
}
or its subtype.
\end{cfuncdesc}
\begin{cfuncdesc}
{
int
}{
PySet
_
Discard
}{
PyObject *set, PyObject *key
}
Returns 1 if found and removed, 0 if not found (no action taken),
and -1 if an error is encountered. Does not raise
\exception
{
KeyError
}
for missing keys. Raises a
\exception
{
TypeError
}
if the
\var
{
key
}
is
unhashable. Unlike the Python
\method
{
discard()
}
method, this function
does not automatically convert unhashable sets into temporary frozensets.
Raises
\exception
{
PyExc
_
SystemError
}
if
\var
{
set
}
is an not an instance
of
\class
{
set
}
or its subtype.
\end{cfuncdesc}
\begin{cfuncdesc}
{
PyObject*
}{
PySet
_
Pop
}{
PyObject *set
}
Returns a new reference to an arbitrary object in the
\var
{
set
}
,
and removes the object from the
\var
{
set
}
. Returns
\NULL
{}
on
failure. Raises
\exception
{
KeyError
}
if the set is empty.
Raises a
\exception
{
SystemError
}
if
\var
{
key
}
is an not an instance
Raises a
\exception
{
SystemError
}
if
\var
{
set
}
is an not an instance
of
\class
{
set
}
or its subtype.
\end{cfuncdesc}
...
...
Include/setobject.h
View file @
5079cdf0
...
...
@@ -79,7 +79,7 @@ PyAPI_FUNC(PyObject *) PyFrozenSet_New(PyObject *);
PyAPI_FUNC
(
int
)
PySet_Size
(
PyObject
*
anyset
);
#define PySet_GET_SIZE(so) (((PySetObject *)(so))->used)
PyAPI_FUNC
(
int
)
PySet_Contains
(
PyObject
*
anyset
,
PyObject
*
key
);
PyAPI_FUNC
(
int
)
PySet_Discard
(
PyObject
*
any
set
,
PyObject
*
key
);
PyAPI_FUNC
(
int
)
PySet_Discard
(
PyObject
*
set
,
PyObject
*
key
);
PyAPI_FUNC
(
int
)
PySet_Add
(
PyObject
*
set
,
PyObject
*
key
);
PyAPI_FUNC
(
PyObject
*
)
PySet_Pop
(
PyObject
*
set
);
...
...
Lib/test/test_set.py
View file @
5079cdf0
...
...
@@ -6,6 +6,7 @@ import copy
import
pickle
import
os
from
random
import
randrange
,
shuffle
import
sys
class
PassThru
(
Exception
):
pass
...
...
@@ -402,6 +403,11 @@ class TestSet(TestJointOps):
s
=
None
self
.
assertRaises
(
ReferenceError
,
str
,
p
)
# C API test only available in a debug build
if
hasattr
(
sys
,
"gettotalrefcount"
):
def
test_c_api
(
self
):
self
.
assertEqual
(
set
(
'abc'
).
test_c_api
(),
True
)
class
SetSubclass
(
set
):
pass
...
...
@@ -1372,7 +1378,6 @@ class TestVariousIteratorArgs(unittest.TestCase):
#==============================================================================
def
test_main
(
verbose
=
None
):
import
sys
from
test
import
test_sets
test_classes
=
(
TestSet
,
...
...
Objects/setobject.c
View file @
5079cdf0
...
...
@@ -1697,6 +1697,13 @@ static PySequenceMethods set_as_sequence = {
/* set object ********************************************************/
#ifdef Py_DEBUG
static
PyObject
*
test_c_api
(
PySetObject
*
so
);
PyDoc_STRVAR
(
test_c_api_doc
,
"Exercises C API. Returns True.
\n
\
All is well if assertions don't fail."
);
#endif
static
PyMethodDef
set_methods
[]
=
{
{
"add"
,
(
PyCFunction
)
set_add
,
METH_O
,
add_doc
},
...
...
@@ -1730,6 +1737,10 @@ static PyMethodDef set_methods[] = {
symmetric_difference_doc
},
{
"symmetric_difference_update"
,(
PyCFunction
)
set_symmetric_difference_update
,
METH_O
,
symmetric_difference_update_doc
},
#ifdef Py_DEBUG
{
"test_c_api"
,
(
PyCFunction
)
test_c_api
,
METH_NOARGS
,
test_c_api_doc
},
#endif
{
"union"
,
(
PyCFunction
)
set_union
,
METH_O
,
union_doc
},
{
"update"
,
(
PyCFunction
)
set_update
,
METH_O
,
...
...
@@ -1931,18 +1942,29 @@ PySet_New(PyObject *iterable)
PyObject
*
PyFrozenSet_New
(
PyObject
*
iterable
)
{
PyObject
*
args
=
NULL
,
*
result
;
PyObject
*
args
,
*
result
;
if
(
iterable
!=
NULL
)
{
if
(
iterable
==
NULL
)
args
=
PyTuple_New
(
0
);
else
args
=
PyTuple_Pack
(
1
,
iterable
);
if
(
args
==
NULL
)
return
NULL
;
}
if
(
args
==
NULL
)
return
NULL
;
result
=
frozenset_new
(
&
PyFrozenSet_Type
,
args
,
NULL
);
Py_
X
DECREF
(
args
);
Py_DECREF
(
args
);
return
result
;
}
int
PySet_Size
(
PyObject
*
anyset
)
{
if
(
!
PyAnySet_Check
(
anyset
))
{
PyErr_BadInternalCall
();
return
-
1
;
}
return
((
PySetObject
*
)
anyset
)
->
used
;
}
int
PySet_Contains
(
PyObject
*
anyset
,
PyObject
*
key
)
{
...
...
@@ -1954,13 +1976,13 @@ PySet_Contains(PyObject *anyset, PyObject *key)
}
int
PySet_Discard
(
PyObject
*
any
set
,
PyObject
*
key
)
PySet_Discard
(
PyObject
*
set
,
PyObject
*
key
)
{
if
(
!
Py
AnySet_Check
(
anyset
))
{
if
(
!
Py
Type_IsSubtype
(
set
->
ob_type
,
&
PySet_Type
))
{
PyErr_BadInternalCall
();
return
-
1
;
}
return
set_discard_key
((
PySetObject
*
)
any
set
,
key
);
return
set_discard_key
((
PySetObject
*
)
set
,
key
);
}
int
...
...
@@ -1982,3 +2004,92 @@ PySet_Pop(PyObject *set)
}
return
set_pop
((
PySetObject
*
)
set
);
}
#ifdef Py_DEBUG
/* Test code to be called with any three element set.
Returns True and original set is restored. */
#define assertRaises(call_return_value, exception) \
do { \
assert(call_return_value); \
assert(PyErr_ExceptionMatches(exception)); \
PyErr_Clear(); \
} while(0)
static
PyObject
*
test_c_api
(
PySetObject
*
so
)
{
PyObject
*
elem
,
*
dup
,
*
t
,
*
f
,
*
ob
=
(
PyObject
*
)
so
;
/* Verify preconditions and exercise type/size checks */
assert
(
PyAnySet_Check
(
ob
));
assert
(
PyAnySet_CheckExact
(
ob
));
assert
(
!
PyFrozenSet_CheckExact
(
ob
));
assert
(
PySet_Size
(
ob
)
==
3
);
assert
(
PySet_GET_SIZE
(
ob
)
==
3
);
/* Raise TypeError for non-iterable constructor arguments */
assertRaises
(
PySet_New
(
Py_None
)
==
NULL
,
PyExc_TypeError
);
assertRaises
(
PyFrozenSet_New
(
Py_None
)
==
NULL
,
PyExc_TypeError
);
/* Raise TypeError for unhashable key */
dup
=
PySet_New
(
ob
);
assertRaises
(
PySet_Discard
(
ob
,
dup
)
==
-
1
,
PyExc_TypeError
);
assertRaises
(
PySet_Contains
(
ob
,
dup
)
==
-
1
,
PyExc_TypeError
);
assertRaises
(
PySet_Add
(
ob
,
dup
)
==
-
1
,
PyExc_TypeError
);
/* Exercise successful pop, contains, add, and discard */
elem
=
PySet_Pop
(
ob
);
assert
(
PySet_Contains
(
ob
,
elem
)
==
0
);
assert
(
PySet_GET_SIZE
(
ob
)
==
2
);
assert
(
PySet_Add
(
ob
,
elem
)
==
0
);
assert
(
PySet_Contains
(
ob
,
elem
)
==
1
);
assert
(
PySet_GET_SIZE
(
ob
)
==
3
);
assert
(
PySet_Discard
(
ob
,
elem
)
==
1
);
assert
(
PySet_GET_SIZE
(
ob
)
==
2
);
assert
(
PySet_Discard
(
ob
,
elem
)
==
0
);
assert
(
PySet_GET_SIZE
(
ob
)
==
2
);
/* Raise SystemError when self argument is not a set or frozenset. */
t
=
PyTuple_New
(
0
);
assertRaises
(
PySet_Size
(
t
)
==
-
1
,
PyExc_SystemError
);
assertRaises
(
PySet_Contains
(
t
,
elem
)
==
-
1
,
PyExc_SystemError
);
Py_DECREF
(
t
);
/* Raise SystemError when self argument is not a set. */
f
=
PyFrozenSet_New
(
dup
);
assert
(
PySet_Size
(
f
)
==
3
);
assert
(
PyFrozenSet_CheckExact
(
f
));
assertRaises
(
PySet_Add
(
f
,
elem
)
==
-
1
,
PyExc_SystemError
);
assertRaises
(
PySet_Discard
(
f
,
elem
)
==
-
1
,
PyExc_SystemError
);
assertRaises
(
PySet_Pop
(
f
)
==
NULL
,
PyExc_SystemError
);
Py_DECREF
(
f
);
/* Raise KeyError when popping from an empty set */
set_clear_internal
(
so
);
assert
(
PySet_GET_SIZE
(
ob
)
==
0
);
assertRaises
(
PySet_Pop
(
ob
)
==
NULL
,
PyExc_KeyError
);
/* Restore the set from the copy and use the abstract API */
assert
(
PyObject_CallMethod
(
ob
,
"update"
,
"O"
,
dup
)
==
Py_None
);
Py_DECREF
(
Py_None
);
/* Verify constructors accept NULL arguments */
f
=
PySet_New
(
NULL
);
assert
(
f
!=
NULL
);
assert
(
PySet_GET_SIZE
(
f
)
==
0
);
Py_DECREF
(
f
);
f
=
PyFrozenSet_New
(
NULL
);
assert
(
f
!=
NULL
);
assert
(
PyFrozenSet_CheckExact
(
f
));
assert
(
PySet_GET_SIZE
(
f
)
==
0
);
Py_DECREF
(
f
);
Py_DECREF
(
elem
);
Py_DECREF
(
dup
);
Py_RETURN_TRUE
;
}
#endif
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment