diff --git a/scrapy/item.py b/scrapy/item.py index ff1c7363d..9998010b2 100644 --- a/scrapy/item.py +++ b/scrapy/item.py @@ -5,7 +5,8 @@ See documentation in docs/topics/item.rst """ from pprint import pformat -from UserDict import DictMixin +from collections import MutableMapping +from abc import ABCMeta import six from scrapy.utils.trackref import object_ref @@ -20,7 +21,7 @@ class Field(dict): """Container of field metadata""" -class ItemMeta(type): +class ItemMeta(ABCMeta): def __new__(mcs, class_name, bases, attrs): fields = {} @@ -37,7 +38,7 @@ class ItemMeta(type): return cls -class DictItem(DictMixin, BaseItem): +class DictItem(MutableMapping, BaseItem): fields = {} @@ -71,6 +72,14 @@ class DictItem(DictMixin, BaseItem): (name, value)) super(DictItem, self).__setattr__(name, value) + def __len__(self): + return len(self._values) + + def __iter__(self): + return iter(self._values) + + __hash__ = BaseItem.__hash__ + def keys(self): return self._values.keys() @@ -81,6 +90,6 @@ class DictItem(DictMixin, BaseItem): return self.__class__(self) +@six.add_metaclass(ItemMeta) class Item(DictItem): - - __metaclass__ = ItemMeta + pass diff --git a/scrapy/tests/test_item.py b/scrapy/tests/test_item.py index 2a24fddca..5de77d22e 100644 --- a/scrapy/tests/test_item.py +++ b/scrapy/tests/test_item.py @@ -1,6 +1,7 @@ import unittest from scrapy.item import Item, Field +import six class ItemTest(unittest.TestCase): @@ -52,8 +53,13 @@ class ItemTest(unittest.TestCase): i['name'] = u'John Doe' i['number'] = 123 itemrepr = repr(i) - self.assertEqual(itemrepr, - "{'name': u'John Doe', 'number': 123}") + + if six.PY2: + self.assertEqual(itemrepr, + "{'name': u'John Doe', 'number': 123}") + else: + self.assertEqual(itemrepr, + "{'name': 'John Doe', 'number': 123}") i2 = eval(itemrepr) self.assertEqual(i2['name'], 'John Doe') @@ -106,13 +112,13 @@ class ItemTest(unittest.TestCase): i = TestItem() i['name'] = u'John' - self.assertEqual(i.keys(), ['name']) - self.assertEqual(i.values(), ['John']) + self.assertEqual(list(i.keys()), ['name']) + self.assertEqual(list(i.values()), ['John']) i['keys'] = u'Keys' i['values'] = u'Values' - self.assertSortedEqual(i.keys(), ['keys', 'values', 'name']) - self.assertSortedEqual(i.values(), [u'Keys', u'Values', u'John']) + self.assertSortedEqual(list(i.keys()), ['keys', 'values', 'name']) + self.assertSortedEqual(list(i.values()), [u'Keys', u'Values', u'John']) def test_metaclass_inheritance(self): class BaseItem(Item): @@ -125,8 +131,8 @@ class ItemTest(unittest.TestCase): i = TestItem() i['keys'] = 3 - self.assertEqual(i.keys(), ['keys']) - self.assertEqual(i.values(), [3]) + self.assertEqual(list(i.keys()), ['keys']) + self.assertEqual(list(i.values()), [3]) def test_to_dict(self): class TestItem(Item): diff --git a/tox.ini b/tox.ini index 2bd97321e..1474cce39 100644 --- a/tox.ini +++ b/tox.ini @@ -5,8 +5,6 @@ [tox] envlist = py27, pypy, precise, trunk, py33, docs -indexserver = - HPK = https://devpi.net/hpk/dev/ [testenv] deps = @@ -51,9 +49,13 @@ deps = w3lib>=1.5 # tests requirements mock - :HPK:pytest>2.5.2 + pytest>=2.6.0 pytest-twisted +[testenv:py34] +basepython = python3.4 +deps = {[testenv:py33]deps} + [testenv:windows] commands = bin/runtests.bat []