Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Z
Zope
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
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
Zope
Commits
f024924f
Commit
f024924f
authored
Aug 26, 2005
by
Tim Peters
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Move the Persistence package, from ZODB trunk to Zope trunk.
parent
116f06f6
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
1091 additions
and
0 deletions
+1091
-0
lib/python/Persistence/DEPENDENCIES.cfg
lib/python/Persistence/DEPENDENCIES.cfg
+2
-0
lib/python/Persistence/_Persistence.c
lib/python/Persistence/_Persistence.c
+175
-0
lib/python/Persistence/__init__.py
lib/python/Persistence/__init__.py
+55
-0
lib/python/Persistence/mapping.py
lib/python/Persistence/mapping.py
+37
-0
lib/python/Persistence/tests/__init__.py
lib/python/Persistence/tests/__init__.py
+1
-0
lib/python/Persistence/tests/testPersistent.py
lib/python/Persistence/tests/testPersistent.py
+224
-0
lib/python/Persistence/tests/test_ExtensionClass.py
lib/python/Persistence/tests/test_ExtensionClass.py
+507
-0
lib/python/Persistence/tests/test_mapping.py
lib/python/Persistence/tests/test_mapping.py
+90
-0
No files found.
lib/python/Persistence/DEPENDENCIES.cfg
0 → 100644
View file @
f024924f
ZODB
persistent
lib/python/Persistence/_Persistence.c
0 → 100644
View file @
f024924f
/*
Copyright (c) 2003 Zope Corporation and Contributors.
All Rights Reserved.
This software is subject to the provisions of the Zope Public License,
Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
FOR A PARTICULAR PURPOSE.
*/
static
char
_Persistence_module_documentation
[]
=
"Persistent ExtensionClass
\n
"
"
\n
"
"$Id$
\n
"
;
#include "ExtensionClass.h"
#include "cPersistence.h"
/* convert_name() returns a new reference to a string name
or sets an exception and returns NULL.
*/
static
PyObject
*
convert_name
(
PyObject
*
name
)
{
#ifdef Py_USING_UNICODE
/* The Unicode to string conversion is done here because the
existing tp_setattro slots expect a string object as name
and we wouldn't want to break those. */
if
(
PyUnicode_Check
(
name
))
{
name
=
PyUnicode_AsEncodedString
(
name
,
NULL
,
NULL
);
}
else
#endif
if
(
!
PyString_Check
(
name
))
{
PyErr_SetString
(
PyExc_TypeError
,
"attribute name must be a string"
);
return
NULL
;
}
else
Py_INCREF
(
name
);
return
name
;
}
/* Returns true if the object requires unghostification.
There are several special attributes that we allow access to without
requiring that the object be unghostified:
__class__
__del__
__dict__
__of__
__setstate__
*/
static
int
unghost_getattr
(
const
char
*
s
)
{
if
(
*
s
++
!=
'_'
)
return
1
;
if
(
*
s
==
'p'
)
{
s
++
;
if
(
*
s
==
'_'
)
return
0
;
/* _p_ */
else
return
1
;
}
else
if
(
*
s
==
'_'
)
{
s
++
;
switch
(
*
s
)
{
case
'c'
:
return
strcmp
(
s
,
"class__"
);
case
'd'
:
s
++
;
if
(
!
strcmp
(
s
,
"el__"
))
return
0
;
/* __del__ */
if
(
!
strcmp
(
s
,
"ict__"
))
return
0
;
/* __dict__ */
return
1
;
case
'o'
:
return
strcmp
(
s
,
"of__"
);
case
's'
:
return
strcmp
(
s
,
"setstate__"
);
default:
return
1
;
}
}
return
1
;
}
static
PyObject
*
P_getattr
(
cPersistentObject
*
self
,
PyObject
*
name
)
{
PyObject
*
v
=
NULL
;
char
*
s
;
name
=
convert_name
(
name
);
if
(
!
name
)
return
NULL
;
s
=
PyString_AS_STRING
(
name
);
if
(
*
s
!=
'_'
||
unghost_getattr
(
s
))
{
if
(
PER_USE
(
self
))
{
v
=
Py_FindAttr
((
PyObject
*
)
self
,
name
);
PER_ALLOW_DEACTIVATION
(
self
);
PER_ACCESSED
(
self
);
}
}
else
v
=
Py_FindAttr
((
PyObject
*
)
self
,
name
);
Py_DECREF
(
name
);
return
v
;
}
static
PyTypeObject
Ptype
=
{
PyObject_HEAD_INIT
(
NULL
)
/* ob_size */
0
,
/* tp_name */
"Persistence.Persistent"
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
/* tp_getattro */
(
getattrofunc
)
P_getattr
,
0
,
0
,
/* tp_flags */
Py_TPFLAGS_DEFAULT
|
Py_TPFLAGS_BASETYPE
,
/* tp_doc */
"Persistent ExtensionClass"
,
};
static
struct
PyMethodDef
_Persistence_methods
[]
=
{
{
NULL
,
(
PyCFunction
)
NULL
,
0
,
NULL
}
/* sentinel */
};
#ifndef PyMODINIT_FUNC
/* declarations for DLL import/export */
#define PyMODINIT_FUNC void
#endif
PyMODINIT_FUNC
init_Persistence
(
void
)
{
PyObject
*
m
;
if
(
!
ExtensionClassImported
)
return
;
cPersistenceCAPI
=
PyCObject_Import
(
"persistent.cPersistence"
,
"CAPI"
);
if
(
cPersistenceCAPI
==
NULL
)
return
;
Ptype
.
tp_bases
=
Py_BuildValue
(
"OO"
,
cPersistenceCAPI
->
pertype
,
ECBaseType
);
if
(
Ptype
.
tp_bases
==
NULL
)
return
;
Ptype
.
tp_base
=
cPersistenceCAPI
->
pertype
;
Ptype
.
ob_type
=
ECExtensionClassType
;
if
(
PyType_Ready
(
&
Ptype
)
<
0
)
return
;
/* Create the module and add the functions */
m
=
Py_InitModule3
(
"_Persistence"
,
_Persistence_methods
,
_Persistence_module_documentation
);
if
(
m
==
NULL
)
return
;
/* Add types: */
if
(
PyModule_AddObject
(
m
,
"Persistent"
,
(
PyObject
*
)
&
Ptype
)
<
0
)
return
;
}
lib/python/Persistence/__init__.py
0 → 100644
View file @
f024924f
##############################################################################
#
# Copyright (c) 2001, 2002, 2003 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE
#
##############################################################################
"""Persistence and ExtensionClass combined
$Id$
"""
from
persistent
import
PickleCache
try
:
from
_Persistence
import
Persistent
except
:
from
warnings
import
warn
warn
(
"""Couldn't import the ExtensionClass-based base class
There are two possibilities:
1. You don't care about ExtensionClass. You are importing
Persistence because that's what you imported in the past.
In this case, you should really use the persistent package
instead:
>>> from persistent import Persistent
>>> from persistent.list import PersistentList
>>> from persistent.mapping import PersistentMapping
2. You want your classes to be ExtensionClasses. In this case,
you need to install the ExtensionClass package
separately. ExtensionClass is no-longer included with ZODB3.
"""
)
from
persistent
import
Persistent
Overridable
=
Persistent
from
Persistence.mapping
import
PersistentMapping
# This is a travesty. Whimper. The Data.fs.in used in Zope 2 have
# ancient pickles refering to BoboPOS. Waaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa!
import
sys
sys
.
modules
[
'BoboPOS'
]
=
sys
.
modules
[
'Persistence'
]
sys
.
modules
[
'BoboPOS.PersistentMapping'
]
=
sys
.
modules
[
'Persistence.mapping'
]
del
sys
lib/python/Persistence/mapping.py
0 → 100644
View file @
f024924f
##############################################################################
#
# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE
#
##############################################################################
"""Python implementation of persistent base types
$Id$"""
import
Persistence
import
persistent
from
persistent.mapping
import
PersistentMapping
if
Persistence
.
Persistent
is
not
persistent
.
Persistent
:
class
PersistentMapping
(
Persistence
.
Persistent
,
PersistentMapping
):
"""Legacy persistent mapping class
This class mixes in ExtensionClass Base if it is present.
Unless you actually want ExtensionClass semantics, use
persistent.mapping.PersistentMapping instead.
"""
def
__setstate__
(
self
,
state
):
if
'data'
not
in
state
:
state
[
'data'
]
=
state
[
'_container'
]
del
state
[
'_container'
]
self
.
__dict__
.
update
(
state
)
lib/python/Persistence/tests/__init__.py
0 → 100644
View file @
f024924f
# package
lib/python/Persistence/tests/testPersistent.py
0 → 100644
View file @
f024924f
#############################################################################
#
# Copyright (c) 2003 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
import
pickle
import
time
import
unittest
from
Persistence
import
Persistent
from
persistent.cPickleCache
import
PickleCache
from
persistent.TimeStamp
import
TimeStamp
from
ZODB.utils
import
p64
class
Jar
(
object
):
"""Testing stub for _p_jar attribute."""
def
__init__
(
self
):
self
.
cache
=
PickleCache
(
self
)
self
.
oid
=
1
self
.
registered
=
{}
def
add
(
self
,
obj
):
obj
.
_p_oid
=
p64
(
self
.
oid
)
self
.
oid
+=
1
obj
.
_p_jar
=
self
self
.
cache
[
obj
.
_p_oid
]
=
obj
def
close
(
self
):
pass
# the following methods must be implemented to be a jar
def
setklassstate
(
self
):
# I don't know what this method does, but the pickle cache
# constructor calls it.
pass
def
register
(
self
,
obj
):
self
.
registered
[
obj
]
=
1
def
setstate
(
self
,
obj
):
# Trivial setstate() implementation that just re-initializes
# the object. This isn't what setstate() is supposed to do,
# but it suffices for the tests.
obj
.
__class__
.
__init__
(
obj
)
class
P
(
Persistent
):
pass
class
H1
(
Persistent
):
def
__init__
(
self
):
self
.
n
=
0
def
__getattr__
(
self
,
attr
):
self
.
n
+=
1
return
self
.
n
class
H2
(
Persistent
):
def
__init__
(
self
):
self
.
n
=
0
def
__getattribute__
(
self
,
attr
):
supergetattr
=
super
(
H2
,
self
).
__getattribute__
try
:
return
supergetattr
(
attr
)
except
AttributeError
:
n
=
supergetattr
(
"n"
)
self
.
n
=
n
+
1
return
n
+
1
class
PersistenceTest
(
unittest
.
TestCase
):
def
setUp
(
self
):
self
.
jar
=
Jar
()
def
tearDown
(
self
):
self
.
jar
.
close
()
def
testOidAndJarAttrs
(
self
):
obj
=
P
()
self
.
assertEqual
(
obj
.
_p_oid
,
None
)
obj
.
_p_oid
=
12
self
.
assertEqual
(
obj
.
_p_oid
,
12
)
del
obj
.
_p_oid
self
.
jar
.
add
(
obj
)
# Can't change oid of cache object.
def
deloid
():
del
obj
.
_p_oid
self
.
assertRaises
(
ValueError
,
deloid
)
def
setoid
():
obj
.
_p_oid
=
12
self
.
assertRaises
(
ValueError
,
setoid
)
def
deloid
():
del
obj
.
_p_jar
self
.
assertRaises
(
ValueError
,
deloid
)
def
setoid
():
obj
.
_p_jar
=
12
self
.
assertRaises
(
ValueError
,
setoid
)
def
testChanged
(
self
):
obj
=
P
()
self
.
jar
.
add
(
obj
)
# The value returned for _p_changed can be one of:
# 0 -- it is not changed
# 1 -- it is changed
# None -- it is a ghost
obj
.
x
=
1
self
.
assertEqual
(
obj
.
_p_changed
,
1
)
self
.
assert_
(
obj
in
self
.
jar
.
registered
)
obj
.
_p_changed
=
0
self
.
assertEqual
(
obj
.
_p_changed
,
0
)
self
.
jar
.
registered
.
clear
()
obj
.
_p_changed
=
1
self
.
assertEqual
(
obj
.
_p_changed
,
1
)
self
.
assert_
(
obj
in
self
.
jar
.
registered
)
# setting obj._p_changed to None ghostifies if the
# object is in the up-to-date state, but not otherwise.
obj
.
_p_changed
=
None
self
.
assertEqual
(
obj
.
_p_changed
,
1
)
obj
.
_p_changed
=
0
# Now it's a ghost.
obj
.
_p_changed
=
None
self
.
assertEqual
(
obj
.
_p_changed
,
None
)
obj
=
P
()
self
.
jar
.
add
(
obj
)
obj
.
_p_changed
=
1
# You can transition directly from modified to ghost if
# you delete the _p_changed attribute.
del
obj
.
_p_changed
self
.
assertEqual
(
obj
.
_p_changed
,
None
)
def
testSerial
(
self
):
noserial
=
"
\
000
"
*
8
obj
=
P
()
self
.
assertEqual
(
obj
.
_p_serial
,
noserial
)
def
set
(
val
):
obj
.
_p_serial
=
val
self
.
assertRaises
(
ValueError
,
set
,
1
)
self
.
assertRaises
(
ValueError
,
set
,
"0123"
)
self
.
assertRaises
(
ValueError
,
set
,
"012345678"
)
self
.
assertRaises
(
ValueError
,
set
,
u"01234567"
)
obj
.
_p_serial
=
"01234567"
del
obj
.
_p_serial
self
.
assertEqual
(
obj
.
_p_serial
,
noserial
)
def
testMTime
(
self
):
obj
=
P
()
self
.
assertEqual
(
obj
.
_p_mtime
,
None
)
t
=
int
(
time
.
time
())
ts
=
TimeStamp
(
*
time
.
gmtime
(
t
)[:
6
])
obj
.
_p_serial
=
repr
(
ts
)
self
.
assertEqual
(
obj
.
_p_mtime
,
t
)
self
.
assert_
(
isinstance
(
obj
.
_p_mtime
,
float
))
def
testPicklable
(
self
):
obj
=
P
()
obj
.
attr
=
"test"
s
=
pickle
.
dumps
(
obj
)
obj2
=
pickle
.
loads
(
s
)
self
.
assertEqual
(
obj
.
attr
,
obj2
.
attr
)
def
testGetattr
(
self
):
obj
=
H1
()
self
.
assertEqual
(
obj
.
larry
,
1
)
self
.
assertEqual
(
obj
.
curly
,
2
)
self
.
assertEqual
(
obj
.
moe
,
3
)
self
.
jar
.
add
(
obj
)
obj
.
_p_deactivate
()
# The simple Jar used for testing re-initializes the object.
self
.
assertEqual
(
obj
.
larry
,
1
)
# The getattr hook modified the object, so it should now be
# in the changed state.
self
.
assertEqual
(
obj
.
_p_changed
,
1
)
self
.
assertEqual
(
obj
.
curly
,
2
)
self
.
assertEqual
(
obj
.
moe
,
3
)
def
testGetattribute
(
self
):
obj
=
H2
()
self
.
assertEqual
(
obj
.
larry
,
1
)
self
.
assertEqual
(
obj
.
curly
,
2
)
self
.
assertEqual
(
obj
.
moe
,
3
)
self
.
jar
.
add
(
obj
)
obj
.
_p_deactivate
()
# The simple Jar used for testing re-initializes the object.
self
.
assertEqual
(
obj
.
larry
,
1
)
# The getattr hook modified the object, so it should now be
# in the changed state.
self
.
assertEqual
(
obj
.
_p_changed
,
1
)
self
.
assertEqual
(
obj
.
curly
,
2
)
self
.
assertEqual
(
obj
.
moe
,
3
)
# TODO: Need to decide how __setattr__ and __delattr__ should work,
# then write tests.
def
test_suite
():
return
unittest
.
makeSuite
(
PersistenceTest
)
lib/python/Persistence/tests/test_ExtensionClass.py
0 → 100644
View file @
f024924f
##############################################################################
#
# Copyright (c) 2003 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""Test ExtensionClass support in Persistence.Persistent
$Id$
"""
from
zope.testing.doctest
import
DocTestSuite
import
pickle
from
Persistence
import
Persistent
try
:
# The _Persistence module is only compiled in a Zope checkout,
# where ExtensionClass is available.
import
Persistence._Persistence
except
ImportError
:
pass
else
:
def
test_basic
():
"""
>>> from ExtensionClass import Base
- Support for a class initialiser:
>>> class C(Persistent):
... def __class_init__(self):
... print 'class init called'
... print self.__name__
... def bar(self):
... return 'bar called'
class init called
C
>>> c = C()
>>> int(c.__class__ is C)
1
>>> int(c.__class__ is type(c))
1
- Provide an inheritedAttribute method for looking up attributes in
base classes:
>>> class C2(C):
... def bar(*a):
... return C2.inheritedAttribute('bar')(*a), 42
class init called
C2
>>> o = C2()
>>> o.bar()
('bar called', 42)
This is for compatability with old code. New code should use super
instead.
The base class, Base, exists mainly to support the __of__ protocol.
The __of__ protocol is similar to __get__ except that __of__ is called
when an implementor is retrieved from an instance as well as from a
class:
>>> class O(Base):
... def __of__(*a):
... return a
>>> o1 = O()
>>> o2 = O()
>>> C.o1 = o1
>>> c.o2 = o2
>>> c.o1 == (o1, c)
1
>>> C.o1 == o1
1
>>> int(c.o2 == (o2, c))
1
We accomplish this by making a class that implements __of__ a
descriptor and treating all descriptor ExtensionClasses this way. That
is, if an extension class is a descriptor, it's __get__ method will be
called even when it is retrieved from an instance.
>>> class O(Base):
... def __get__(*a):
... return a
...
>>> o1 = O()
>>> o2 = O()
>>> C.o1 = o1
>>> c.o2 = o2
>>> int(c.o1 == (o1, c, type(c)))
1
>>> int(C.o1 == (o1, None, type(c)))
1
>>> int(c.o2 == (o2, c, type(c)))
1
"""
def
test_mixing
():
"""Test working with a classic class
>>> class Classic:
... def x(self):
... return 42
>>> class O(Persistent):
... def __of__(*a):
... return a
>>> class O2(Classic, O):
... def __of__(*a):
... return (O2.inheritedAttribute('__of__')(*a),
... O2.inheritedAttribute('x')(a[0]))
>>> class C(Persistent):
... def __class_init__(self):
... print 'class init called'
... print self.__name__
... def bar(self):
... return 'bar called'
class init called
C
>>> c = C()
>>> o2 = O2()
>>> c.o2 = o2
>>> int(c.o2 == ((o2, c), 42))
1
Test working with a new style
>>> class Modern(object):
... def x(self):
... return 42
>>> class O2(Modern, O):
... def __of__(*a):
... return (O2.inheritedAttribute('__of__')(*a),
... O2.inheritedAttribute('x')(a[0]))
>>> o2 = O2()
>>> c.o2 = o2
>>> int(c.o2 == ((o2, c), 42))
1
"""
def
proper_error_on_deleattr
():
"""
Florent Guillaume wrote:
...
Excellent.
Will it also fix this particularity of ExtensionClass:
>>> class A(Persistent):
... def foo(self):
... self.gee
... def bar(self):
... del self.gee
>>> a=A()
>>> a.foo()
Traceback (most recent call last):
...
AttributeError: gee
>>> a.bar()
Traceback (most recent call last):
...
AttributeError: 'A' object has no attribute 'gee'
I.e., the fact that KeyError is raised whereas a normal class would
raise AttributeError.
"""
def
test__basicnew__
():
"""
>>> x = Simple.__basicnew__()
>>> x.__dict__
{}
"""
def
test_setattr_on_extension_type
():
"""
>>> for name in 'x', '_x', 'x_', '__x_y__', '___x__', '__x___', '_x_':
... setattr(Persistent, name, 1)
... print getattr(Persistent, name)
... delattr(Persistent, name)
... print getattr(Persistent, name, 0)
1
0
1
0
1
0
1
0
1
0
1
0
1
0
>>> Persistent.__foo__ = 1
Traceback (most recent call last):
...
TypeError: can't set attributes of built-in/extension type """
\
"""'Persistence.Persistent' if the attribute name begins """
\
"""and ends with __ and contains only 4 _ characters
>>> Persistent.__foo__
Traceback (most recent call last):
...
AttributeError: type object 'Persistence.Persistent' """
\
"""has no attribute '__foo__'
>>> del Persistent.__foo__
Traceback (most recent call last):
...
TypeError: can't set attributes of built-in/extension type """
\
"""'Persistence.Persistent' if the attribute name begins """
\
"""and ends with __ and contains only 4 _ characters
"""
def
test_class_creation_under_stress
():
"""
>>> for i in range(100):
... class B(Persistent):
... print i,
... if i and i%20 == 0:
... print
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
>>> import gc
>>> x = gc.collect()
"""
def
print_dict
(
d
):
d
=
d
.
items
()
d
.
sort
()
print
'{%s}'
%
(
', '
.
join
(
[(
'%r: %r'
%
(
k
,
v
))
for
(
k
,
v
)
in
d
]
))
def
cmpattrs
(
self
,
other
,
*
attrs
):
for
attr
in
attrs
:
if
attr
[:
3
]
in
(
'_v_'
,
'_p_'
):
continue
c
=
cmp
(
getattr
(
self
,
attr
,
None
),
getattr
(
other
,
attr
,
None
))
if
c
:
return
c
return
0
class
Simple
(
Persistent
):
def
__init__
(
self
,
name
,
**
kw
):
self
.
__name__
=
name
self
.
__dict__
.
update
(
kw
)
self
.
_v_favorite_color
=
'blue'
self
.
_p_foo
=
'bar'
def
__cmp__
(
self
,
other
):
return
cmpattrs
(
self
,
other
,
'__class__'
,
*
(
self
.
__dict__
.
keys
()))
def
test_basic_pickling
():
"""
>>> x = Simple('x', aaa=1, bbb='foo')
>>> print_dict(x.__getstate__())
{'__name__': 'x', 'aaa': 1, 'bbb': 'foo'}
>>> f, (c,), state = x.__reduce__()
>>> f.__name__
'__newobj__'
>>> f.__module__
'copy_reg'
>>> c.__name__
'Simple'
>>> print_dict(state)
{'__name__': 'x', 'aaa': 1, 'bbb': 'foo'}
>>> pickle.loads(pickle.dumps(x)) == x
1
>>> pickle.loads(pickle.dumps(x, 0)) == x
1
>>> pickle.loads(pickle.dumps(x, 1)) == x
1
>>> pickle.loads(pickle.dumps(x, 2)) == x
1
>>> x.__setstate__({'z': 1})
>>> x.__dict__
{'z': 1}
"""
class
Custom
(
Simple
):
def
__new__
(
cls
,
x
,
y
):
r
=
Persistent
.
__new__
(
cls
)
r
.
x
,
r
.
y
=
x
,
y
return
r
def
__init__
(
self
,
x
,
y
):
self
.
a
=
42
def
__getnewargs__
(
self
):
return
self
.
x
,
self
.
y
def
__getstate__
(
self
):
return
self
.
a
def
__setstate__
(
self
,
a
):
self
.
a
=
a
def
test_pickling_w_overrides
():
"""
>>> x = Custom('x', 'y')
>>> x.a = 99
>>> (f, (c, ax, ay), a) = x.__reduce__()
>>> f.__name__
'__newobj__'
>>> f.__module__
'copy_reg'
>>> c.__name__
'Custom'
>>> ax, ay, a
('x', 'y', 99)
>>> pickle.loads(pickle.dumps(x)) == x
1
>>> pickle.loads(pickle.dumps(x, 0)) == x
1
>>> pickle.loads(pickle.dumps(x, 1)) == x
1
>>> pickle.loads(pickle.dumps(x, 2)) == x
1
"""
class
Slotted
(
Persistent
):
__slots__
=
's1'
,
's2'
,
'_p_splat'
,
'_v_eek'
def
__init__
(
self
,
s1
,
s2
):
self
.
s1
,
self
.
s2
=
s1
,
s2
self
.
_v_eek
=
1
self
.
_p_splat
=
2
class
SubSlotted
(
Slotted
):
__slots__
=
's3'
,
's4'
def
__init__
(
self
,
s1
,
s2
,
s3
):
Slotted
.
__init__
(
self
,
s1
,
s2
)
self
.
s3
=
s3
def
__cmp__
(
self
,
other
):
return
cmpattrs
(
self
,
other
,
'__class__'
,
's1'
,
's2'
,
's3'
,
's4'
)
def
test_pickling_w_slots_only
():
"""
>>> x = SubSlotted('x', 'y', 'z')
>>> d, s = x.__getstate__()
>>> d
>>> print_dict(s)
{'s1': 'x', 's2': 'y', 's3': 'z'}
>>> pickle.loads(pickle.dumps(x)) == x
1
>>> pickle.loads(pickle.dumps(x, 0)) == x
1
>>> pickle.loads(pickle.dumps(x, 1)) == x
1
>>> pickle.loads(pickle.dumps(x, 2)) == x
1
>>> x.s4 = 'spam'
>>> d, s = x.__getstate__()
>>> d
>>> print_dict(s)
{'s1': 'x', 's2': 'y', 's3': 'z', 's4': 'spam'}
>>> pickle.loads(pickle.dumps(x)) == x
1
>>> pickle.loads(pickle.dumps(x, 0)) == x
1
>>> pickle.loads(pickle.dumps(x, 1)) == x
1
>>> pickle.loads(pickle.dumps(x, 2)) == x
1
"""
class
SubSubSlotted
(
SubSlotted
):
def
__init__
(
self
,
s1
,
s2
,
s3
,
**
kw
):
SubSlotted
.
__init__
(
self
,
s1
,
s2
,
s3
)
self
.
__dict__
.
update
(
kw
)
self
.
_v_favorite_color
=
'blue'
self
.
_p_foo
=
'bar'
def
__cmp__
(
self
,
other
):
return
cmpattrs
(
self
,
other
,
'__class__'
,
's1'
,
's2'
,
's3'
,
's4'
,
*
(
self
.
__dict__
.
keys
()))
def
test_pickling_w_slots
():
"""
>>> x = SubSubSlotted('x', 'y', 'z', aaa=1, bbb='foo')
>>> d, s = x.__getstate__()
>>> print_dict(d)
{'aaa': 1, 'bbb': 'foo'}
>>> print_dict(s)
{'s1': 'x', 's2': 'y', 's3': 'z'}
>>> pickle.loads(pickle.dumps(x)) == x
1
>>> pickle.loads(pickle.dumps(x, 0)) == x
1
>>> pickle.loads(pickle.dumps(x, 1)) == x
1
>>> pickle.loads(pickle.dumps(x, 2)) == x
1
>>> x.s4 = 'spam'
>>> d, s = x.__getstate__()
>>> print_dict(d)
{'aaa': 1, 'bbb': 'foo'}
>>> print_dict(s)
{'s1': 'x', 's2': 'y', 's3': 'z', 's4': 'spam'}
>>> pickle.loads(pickle.dumps(x)) == x
1
>>> pickle.loads(pickle.dumps(x, 0)) == x
1
>>> pickle.loads(pickle.dumps(x, 1)) == x
1
>>> pickle.loads(pickle.dumps(x, 2)) == x
1
"""
def
test_pickling_w_slots_w_empty_dict
():
"""
>>> x = SubSubSlotted('x', 'y', 'z')
>>> d, s = x.__getstate__()
>>> print_dict(d)
{}
>>> print_dict(s)
{'s1': 'x', 's2': 'y', 's3': 'z'}
>>> pickle.loads(pickle.dumps(x)) == x
1
>>> pickle.loads(pickle.dumps(x, 0)) == x
1
>>> pickle.loads(pickle.dumps(x, 1)) == x
1
>>> pickle.loads(pickle.dumps(x, 2)) == x
1
>>> x.s4 = 'spam'
>>> d, s = x.__getstate__()
>>> print_dict(d)
{}
>>> print_dict(s)
{'s1': 'x', 's2': 'y', 's3': 'z', 's4': 'spam'}
>>> pickle.loads(pickle.dumps(x)) == x
1
>>> pickle.loads(pickle.dumps(x, 0)) == x
1
>>> pickle.loads(pickle.dumps(x, 1)) == x
1
>>> pickle.loads(pickle.dumps(x, 2)) == x
1
"""
def
test_suite
():
return
DocTestSuite
()
lib/python/Persistence/tests/test_mapping.py
0 → 100644
View file @
f024924f
##############################################################################
#
# Copyright (c) 2003 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""
$Id$
"""
import
unittest
from
zope.testing.doctest
import
DocTestSuite
from
Persistence
import
PersistentMapping
def
test_basic_functionality
():
"""
>>> m = PersistentMapping({'x': 1}, a=2, b=3)
>>> m['name'] = 'bob'
>>> m['fred']
Traceback (most recent call last):
...
KeyError: 'fred'
>>> m.get('fred')
>>> m.get('fred', 42)
42
>>> m.get('name', 42)
'bob'
>>> m.get('name')
'bob'
>>> m['name']
'bob'
>>> keys = m.keys()
>>> keys.sort()
>>> keys
['a', 'b', 'name', 'x']
>>> values = m.values()
>>> values.sort()
>>> values
[1, 2, 3, 'bob']
>>> items = m.items()
>>> items.sort()
>>> items
[('a', 2), ('b', 3), ('name', 'bob'), ('x', 1)]
>>> keys = list(m.iterkeys())
>>> keys.sort()
>>> keys
['a', 'b', 'name', 'x']
>>> values = list(m.itervalues())
>>> values.sort()
>>> values
[1, 2, 3, 'bob']
>>> items = list(m.iteritems())
>>> items.sort()
>>> items
[('a', 2), ('b', 3), ('name', 'bob'), ('x', 1)]
>>> 'name' in m
True
"""
def
test_old_pickles
():
"""
>>> m = PersistentMapping()
>>> m.__setstate__({'_container': {'x': 1, 'y': 2}})
>>> items = m.items()
>>> items.sort()
>>> items
[('x', 1), ('y', 2)]
"""
def
test_suite
():
return
unittest
.
TestSuite
((
DocTestSuite
(),
))
if
__name__
==
'__main__'
:
unittest
.
main
()
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