Skip to content

Commit

Permalink
item fields defined on fields class attribute fix
Browse files Browse the repository at this point in the history
  • Loading branch information
nramirezuy committed May 13, 2015
1 parent e521740 commit 773ea5a
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 8 deletions.
3 changes: 2 additions & 1 deletion scrapy/item.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

from pprint import pformat
from collections import MutableMapping

from abc import ABCMeta
import six

Expand All @@ -27,7 +28,7 @@ def __new__(mcs, class_name, bases, attrs):
new_bases = tuple(base._class for base in bases if hasattr(base, '_class'))
_class = super(ItemMeta, mcs).__new__(mcs, 'x_' + class_name, new_bases, attrs)

fields = {}
fields = getattr(_class, 'fields', {})
new_attrs = {}
for n in dir(_class):
v = getattr(_class, n)
Expand Down
36 changes: 29 additions & 7 deletions tests/test_item.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,14 @@ class TestItem(Item):
self.assertSortedEqual(list(i.keys()), ['keys', 'values', 'name'])
self.assertSortedEqual(list(i.values()), [u'Keys', u'Values', u'John'])

def test_metaclass_with_fields_attribute(self):
class TestItem(Item):
fields = {'new': Field(default='X')}

item = TestItem(new=u'New')
self.assertSortedEqual(list(item.keys()), ['new'])
self.assertSortedEqual(list(item.values()), [u'New'])

def test_metaclass_inheritance(self):
class BaseItem(Item):
name = Field()
Expand All @@ -136,41 +144,51 @@ class TestItem(BaseItem):

def test_metaclass_multiple_inheritance_simple(self):
class A(Item):
fields = {'load': Field(default='A')}
save = Field(default='A')

class B(A): pass

class C(Item):
fields = {'load': Field(default='C')}
save = Field(default='C')

class D(B, C): pass

self.assertEqual(D(save='X')['save'], 'X')
self.assertEqual(D.fields, {'save': {'default': 'A'}})
item = D(save='X', load='Y')
self.assertEqual(item['save'], 'X')
self.assertEqual(item['load'], 'Y')
self.assertEqual(D.fields, {'load': {'default': 'A'},
'save': {'default': 'A'}})

# D class inverted
class E(C, B): pass

self.assertEqual(E(save='X')['save'], 'X')
self.assertEqual(E.fields, {'save': {'default': 'C'}})
self.assertEqual(E(load='X')['load'], 'X')
self.assertEqual(E.fields, {'load': {'default': 'C'},
'save': {'default': 'C'}})

def test_metaclass_multiple_inheritance_diamond(self):
class A(Item):
fields = {'update': Field(default='A')}
save = Field(default='A')
load = Field(default='A')

class B(A): pass

class C(A):
fields = {'update': Field(default='C')}
save = Field(default='C')

class D(B, C):
fields = {'update': Field(default='D')}
load = Field(default='D')

self.assertEqual(D(save='X')['save'], 'X')
self.assertEqual(D(load='X')['load'], 'X')
self.assertEqual(D.fields, {'save': {'default': 'C'},
'load': {'default': 'D'}})
'load': {'default': 'D'}, 'update': {'default': 'D'}})

# D class inverted
class E(C, B):
Expand All @@ -179,30 +197,34 @@ class E(C, B):
self.assertEqual(E(save='X')['save'], 'X')
self.assertEqual(E(load='X')['load'], 'X')
self.assertEqual(E.fields, {'save': {'default': 'C'},
'load': {'default': 'E'}})
'load': {'default': 'E'}, 'update': {'default': 'C'}})

def test_metaclass_multiple_inheritance_without_metaclass(self):
class A(Item):
fields = {'load': Field(default='A')}
save = Field(default='A')

class B(A): pass

class C(object):
fields = {'load': Field(default='C')}
not_allowed = Field(default='not_allowed')
save = Field(default='C')

class D(B, C): pass

self.assertRaises(KeyError, D, not_allowed='value')
self.assertEqual(D(save='X')['save'], 'X')
self.assertEqual(D.fields, {'save': {'default': 'A'}})
self.assertEqual(D.fields, {'save': {'default': 'A'},
'load': {'default': 'A'}})

# D class inverted
class E(C, B): pass

self.assertRaises(KeyError, E, not_allowed='value')
self.assertEqual(E(save='X')['save'], 'X')
self.assertEqual(E.fields, {'save': {'default': 'A'}})
self.assertEqual(E.fields, {'save': {'default': 'A'},
'load': {'default': 'A'}})

def test_to_dict(self):
class TestItem(Item):
Expand Down

0 comments on commit 773ea5a

Please sign in to comment.