[PyObjC-svn] r2462 - in trunk/pyobjc/pyobjc-core: . Lib/objc PyObjCTest
[email protected] Tue, 06 Apr 2010 14:38:26 -0500
| Newsgroups | gmane.comp.python.pyobjc.cvs |
|---|---|
| Message-ID | <[email protected]> |
Author: ronaldoussoren
Date: Tue Apr 6 14:38:26 2010
New Revision: 2462
Log:
* Add testcases that check that NSDictionary implements the interface
of dict for python3.x.
* Update the convenience wrappers to ensure most of these new
tests actually pass.
* Mention this in the NEWS file
TODO:
- 3 tests don't pass yet, need to investigate
- als have to add simular tests for python 2.6 and 2.7
- and likewise for NSMutableSet vs. set and NSMutableArray vs list
(and their immutable variants)
Added:
trunk/pyobjc/pyobjc-core/PyObjCTest/test3_dict_interface.py (contents, props changed)
Modified:
trunk/pyobjc/pyobjc-core/Lib/objc/_convenience.py
trunk/pyobjc/pyobjc-core/NEWS.txt
Modified: trunk/pyobjc/pyobjc-core/Lib/objc/_convenience.py
==============================================================================
--- trunk/pyobjc/pyobjc-core/Lib/objc/_convenience.py (original)
+++ trunk/pyobjc/pyobjc-core/Lib/objc/_convenience.py Tue Apr 6 14:38:26 2010
@@ -190,10 +190,29 @@
('__delitem__', __delitem__removeObjectForKey_),
)
-def update_setObject_forKey_(self, other):
+def update_setObject_forKey_(self, *args, **kwds):
# XXX - should this be more flexible?
- for key, value in other.items():
- self[key] = value
+ if len(args) == 0:
+ pass
+ elif len(args) != 1:
+ raise TypeError("update expected at most 1 arguments, got {0}".format(
+ len(args)))
+
+
+ else:
+ other = args[0]
+ if hasattr(other, 'keys'):
+ # This mirrors the implementation of dict.update, but seems
+ # wrong for Python3 (with collectons.Dict)
+ for key in other.keys():
+ self[key] = other[key]
+
+ else:
+ for key, value in other:
+ self[key] = value
+
+ for k, v in kwds.iteritems():
+ self[k] = v
def setdefault_setObject_forKey_(self, key, dflt=None):
try:
@@ -204,11 +223,14 @@
def __setitem__setObject_forKey_(self, key, value):
self.setObject_forKey_(container_wrap(value), container_wrap(key))
-
-def pop_setObject_forKey_(self, key, dflt=None):
+
+pop_setObject_dflt=object()
+def pop_setObject_forKey_(self, key, dflt=pop_setObject_dflt):
try:
res = self[key]
except KeyError:
+ if dflt == pop_setObject_dflt:
+ raise KeyError(key)
res = dflt
else:
del self[key]
@@ -514,10 +536,10 @@
values = list(values)
return cls.dictionaryWithObjects_forKeys_(values, keys)
-CONVENIENCE_METHODS[b'dictionaryWithObjects:forKeys:'] = (
- ('fromkeys',
- classmethod(fromkeys_dictionaryWithObjects_forKeys_)),
-)
+#CONVENIENCE_METHODS[b'dictionaryWithObjects:forKeys:'] = (
+ #('fromkeys',
+ #classmethod(fromkeys_dictionaryWithObjects_forKeys_)),
+#)
if sys.version_info[0] == 3:
def cmp(a, b):
@@ -645,35 +667,130 @@
if sys.version_info[0] == 3 or (sys.version_info[0] == 2 and sys.version_info[1] >= 7):
+ import collections
+
+ def all_contained_in(inner, outer):
+ """
+ Return True iff all items in ``inner`` are also in ``outer``.
+ """
+ for v in inner:
+ if v not in outer:
+ return False
+
+ return True
+
class nsdict_view (object):
__slots__ = ()
+ def __eq__(self, other):
+ if not isinstance(other, collections.Set):
+ return NotImplemented
+
+ if len(self) == len(other):
+ return all_contained_in(self, other)
+
+ else:
+ return False
+
+ def __ne__(self, other):
+ if not isinstance(other, collections.Set):
+ return NotImplemented
+
+ if len(self) == len(other):
+ return not all_contained_in(self, other)
+
+ else:
+ return True
+
+ def __lt__(self, other):
+ if not isinstance(other, collections.Set):
+ return NotImplemented
+
+ if len(self) < len(other):
+ return all_contained_in(self, other)
+
+ else:
+ return False
+
+ def __le__(self, other):
+ if not isinstance(other, collections.Set):
+ return NotImplemented
+
+ if len(self) <= len(other):
+ return all_contained_in(self, other)
+
+ else:
+ return False
+
+ def __gt__(self, other):
+ if not isinstance(other, collections.Set):
+ return NotImplemented
+
+ if len(self) > len(other):
+ return all_contained_in(other, self)
+
+ else:
+ return False
+
+ def __ge__(self, other):
+ if not isinstance(other, collections.Set):
+ return NotImplemented
+
+ if len(self) >= len(other):
+ return all_contained_in(other, self)
+
+ else:
+ return False
+
def __and__(self, other):
+ if not isinstance(other, collections.Set):
+ return NotImplemented
result = set(self)
result.intersection_update(other)
return result
def __or__(self, other):
+ if not isinstance(other, collections.Set):
+ return NotImplemented
+ result = set(self)
+ result.update(other)
+ return result
+
+ def __ror__(self, other):
+ if not isinstance(other, collections.Set):
+ return NotImplemented
result = set(self)
result.update(other)
return result
def __sub__(self, other):
+ if not isinstance(other, collections.Set):
+ return NotImplemented
result = set(self)
result.difference_update(other)
return result
- def __xor__(Self, other):
+ def __xor__(self, other):
+ if not isinstance(other, collections.Set):
+ return NotImplemented
result = set(self)
result.symmetric_difference_update(other)
return result
-
+
+ collections.Set.register(nsdict_view)
class nsdict_keys(nsdict_view):
__slots__=('__value')
def __init__(self, value):
self.__value = value
+ def __repr__(self):
+ keys = list(self.__value)
+ keys.sort()
+
+ return "<nsdict_keys({0})>".format(keys)
+
+
def __len__(self):
return len(self.__value)
@@ -688,6 +805,12 @@
def __init__(self, value):
self.__value = value
+ def __repr__(self):
+ values = list(self)
+ values.sort()
+
+ return "<nsdict_values({0})>".format(values)
+
def __len__(self):
return len(self.__value)
@@ -701,10 +824,18 @@
return False
class nsdict_items(nsdict_view):
+
__slots__=('__value')
+
def __init__(self, value):
self.__value = value
+ def __repr__(self):
+ values = list(self)
+ values.sort()
+
+ return "<nsdict_items({0})>".format(values)
+
def __len__(self):
return len(self.__value)
@@ -718,17 +849,81 @@
return True
return False
+ collections.KeysView.register(nsdict_keys)
+ collections.ValuesView.register(nsdict_values)
+ collections.ItemsView.register(nsdict_items)
+
+ collections.Mapping.register(lookUpClass('NSDictionary'))
+ collections.MutableMapping.register(lookUpClass('NSMutableDictionary'))
+
+
+ def nsdict_new(cls, *args, **kwds):
+ if len(args) == 0:
+ pass
+
+ elif len(args) == 1:
+ d = dict()
+ for k , v in args[0]:
+ d[container_wrap(k)] = container_wrap(v)
+
+ for k, v in kwds.iteritems():
+ d[container_wrap(k)] = container_wrap(v)
+
+ return cls.dictionaryWithDictionary_(d)
+
+ else:
+ raise TypeError(
+ "dict expected at most 1 arguments, got {0}".format(
+ len(args)))
+ if kwds:
+ d = dict()
+ for k, v in kwds.iteritems():
+ d[container_wrap(k)] = container_wrap(v)
+
+ return cls.dictionaryWithDictionary_(d)
+
+ return cls.dictionary()
+
+ NSDictionary = lookUpClass('NSDictionary')
+ def nsdict_fromkeys(cls, keys, value=None):
+ keys = [container_wrap(k) for k in keys]
+ values = [container_wrap(value)]*len(keys)
+
+ return NSDictionary.dictionaryWithObjects_forKeys_(values, keys)
+
+ NSMutableDictionary = lookUpClass('NSMutableDictionary')
+ def nsmutabledict_fromkeys(cls, keys, value=None):
+ result = NSMutableDictionary.dictionary()
+ value = container_wrap(value)
+ for k in keys:
+ result[container_wrap(k)] = value
+
+ return result
+
if sys.version_info[0] == 3:
CLASS_METHODS['NSDictionary'] = (
+ ('__new__', nsdict_new),
+ ('fromkeys', classmethod(nsdict_fromkeys)),
('keys', lambda self: nsdict_keys(self)),
('values', lambda self: nsdict_values(self)),
('items', lambda self: nsdict_items(self)),
)
+ CLASS_METHODS['NSMutableDictionary'] = (
+ ('__new__', nsdict_new),
+ ('fromkeys', classmethod(nsmutabledict_fromkeys)),
+ )
+
else:
CLASS_METHODS['NSDictionary'] = (
+ ('__new__', nsdict_new),
+ ('fromkeys', classmethod(nsdict_fromkeys)),
('viewkeys', lambda self: nsdict_keys(self)),
('viewvalues', lambda self: nsdict_values(self)),
('viewitems', lambda self: nsdict_items(self)),
)
+ CLASS_METHODS['NSMutableDictionary'] = (
+ ('__new__', nsdict_new),
+ )
+
Modified: trunk/pyobjc/pyobjc-core/NEWS.txt
==============================================================================
--- trunk/pyobjc/pyobjc-core/NEWS.txt (original)
+++ trunk/pyobjc/pyobjc-core/NEWS.txt Tue Apr 6 14:38:26 2010
@@ -7,6 +7,24 @@
Version 2.3a0
-------------
+- (This item is currenlty only true for python3, need tests for python 2.x)
+
+ NSDictionary now fully implements the dict API, except for the differences
+ not below:
+
+ * ``NSDictionary`` doesn't have the ``__missing__`` hook.
+
+ * ``NSDictionary`` always copies keys, which gives slightly different
+ semantics from Python.
+
+ * ``NSDictionary.copy`` always returns an immutable dictionary, use
+ ``NSDictionary.mutableCopy`` to get a mutable dictionary.
+
+ ``NSDictionary`` implements one important feature that native Python
+ dictionaries don't: full support for Key-Value Observations. Sadly enough
+ it is not possible to support Key-Value Observation of native Python
+ dictionaries without patching the interpreter.
+
- BUGFIX: accessing methods through ``anObject.pyobjc_instancMethods`` is
now safer, before this release this could cause unlimited recursion
(although I'm not sure if it was possible to trigger this without
------------------------------------------------------------------------------
Download Intel® Parallel Studio Eval
Try the new software tools for yourself. Speed compiling, find bugs
proactively, and fine-tune applications for parallel performance.
See why Intel Parallel Studio got high marks during beta.
http://p.sf.net/sfu/intel-sw-dev