mirror of https://github.com/scrapy/scrapy.git
Merge pull request #3671 from Gallaecio/item-deepcopy
Implement Item.deepcopy()
This commit is contained in:
commit
729580dae2
|
|
@ -40,6 +40,7 @@ objects. Here is an example::
|
|||
name = scrapy.Field()
|
||||
price = scrapy.Field()
|
||||
stock = scrapy.Field()
|
||||
tags = scrapy.Field()
|
||||
last_updated = scrapy.Field(serializer=str)
|
||||
|
||||
.. note:: Those familiar with `Django`_ will notice that Scrapy Items are
|
||||
|
|
@ -155,19 +156,42 @@ To access all populated values, just use the typical `dict API`_::
|
|||
>>> product.items()
|
||||
[('price', 1000), ('name', 'Desktop PC')]
|
||||
|
||||
|
||||
Copying items
|
||||
-------------
|
||||
|
||||
To copy an item, you must first decide whether you want a shallow copy or a
|
||||
deep copy.
|
||||
|
||||
If your item contains mutable_ values like lists or dictionaries, a shallow
|
||||
copy will keep references to the same mutable values across all different
|
||||
copies.
|
||||
|
||||
.. _mutable: https://docs.python.org/glossary.html#term-mutable
|
||||
|
||||
For example, if you have an item with a list of tags, and you create a shallow
|
||||
copy of that item, both the original item and the copy have the same list of
|
||||
tags. Adding a tag to the list of one of the items will add the tag to the
|
||||
other item as well.
|
||||
|
||||
If that is not the desired behavior, use a deep copy instead.
|
||||
|
||||
See the `documentation of the copy module`_ for more information.
|
||||
|
||||
.. _documentation of the copy module: https://docs.python.org/library/copy.html
|
||||
|
||||
To create a shallow copy of an item, you can either call
|
||||
:meth:`~scrapy.item.Item.copy` on an existing item
|
||||
(``product2 = product.copy()``) or instantiate your item class from an existing
|
||||
item (``product2 = Product(product)``).
|
||||
|
||||
To create a deep copy, call :meth:`~scrapy.item.Item.deepcopy` instead
|
||||
(``product2 = product.deepcopy()``).
|
||||
|
||||
|
||||
Other common tasks
|
||||
------------------
|
||||
|
||||
Copying items::
|
||||
|
||||
>>> product2 = Product(product)
|
||||
>>> print(product2)
|
||||
Product(name='Desktop PC', price=1000)
|
||||
|
||||
>>> product3 = product2.copy()
|
||||
>>> print(product3)
|
||||
Product(name='Desktop PC', price=1000)
|
||||
|
||||
Creating dicts from items::
|
||||
|
||||
>>> dict(product) # create a dict from all populated values
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ See documentation in docs/topics/item.rst
|
|||
|
||||
from pprint import pformat
|
||||
from collections import MutableMapping
|
||||
from copy import deepcopy
|
||||
|
||||
from abc import ABCMeta
|
||||
import six
|
||||
|
|
@ -96,6 +97,13 @@ class DictItem(MutableMapping, BaseItem):
|
|||
def copy(self):
|
||||
return self.__class__(self)
|
||||
|
||||
def deepcopy(self):
|
||||
"""Return a `deep copy`_ of this item.
|
||||
|
||||
.. _deep copy: https://docs.python.org/library/copy.html#copy.deepcopy
|
||||
"""
|
||||
return deepcopy(self)
|
||||
|
||||
|
||||
@six.add_metaclass(ItemMeta)
|
||||
class Item(DictItem):
|
||||
|
|
|
|||
|
|
@ -249,6 +249,14 @@ class ItemTest(unittest.TestCase):
|
|||
copied_item['name'] = copied_item['name'].upper()
|
||||
self.assertNotEqual(item['name'], copied_item['name'])
|
||||
|
||||
def test_deepcopy(self):
|
||||
class TestItem(Item):
|
||||
tags = Field()
|
||||
item = TestItem({'tags': ['tag1']})
|
||||
copied_item = item.deepcopy()
|
||||
item['tags'].append('tag2')
|
||||
assert item['tags'] != copied_item['tags']
|
||||
|
||||
|
||||
class ItemMetaTest(unittest.TestCase):
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue