Merge pull request #5563 from scrapy/dataclasses-ftw

remove compatibility code from tests for the case dataclasses module is not available
This commit is contained in:
Andrey Rahmatullin 2022-07-19 10:37:20 +05:00 committed by GitHub
commit bb61b03b49
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 56 additions and 95 deletions

View File

@ -4,6 +4,7 @@ import marshal
import pickle
import tempfile
import unittest
import dataclasses
from io import BytesIO
from datetime import datetime
from warnings import catch_warnings, filterwarnings
@ -21,31 +22,30 @@ from scrapy.exporters import (
)
def custom_serializer(value):
return str(int(value) + 2)
class TestItem(Item):
name = Field()
age = Field()
def custom_serializer(value):
return str(int(value) + 2)
class CustomFieldItem(Item):
name = Field()
age = Field(serializer=custom_serializer)
try:
from dataclasses import make_dataclass, field
except ImportError:
TestDataClass = None
CustomFieldDataclass = None
else:
TestDataClass = make_dataclass("TestDataClass", [("name", str), ("age", int)])
CustomFieldDataclass = make_dataclass(
"CustomFieldDataclass",
[("name", str), ("age", int, field(metadata={"serializer": custom_serializer}))]
)
@dataclasses.dataclass
class TestDataClass:
name: str
age: int
@dataclasses.dataclass
class CustomFieldDataclass:
name: str
age: int = dataclasses.field(metadata={"serializer": custom_serializer})
class BaseItemExporterTest(unittest.TestCase):
@ -54,8 +54,6 @@ class BaseItemExporterTest(unittest.TestCase):
custom_field_item_class = CustomFieldItem
def setUp(self):
if self.item_class is None:
raise unittest.SkipTest("item class is None")
self.i = self.item_class(name='John\xa3', age='22')
self.output = BytesIO()
self.ie = self._get_exporter()

View File

@ -1,4 +1,5 @@
import unittest
import dataclasses
import attr
from itemadapter import ItemAdapter
@ -10,13 +11,6 @@ from scrapy.loader import ItemLoader
from scrapy.selector import Selector
try:
from dataclasses import make_dataclass, field as dataclass_field
except ImportError:
make_dataclass = None
dataclass_field = None
# test items
class NameItem(Item):
name = Field()
@ -41,6 +35,11 @@ class AttrsNameItem:
name = attr.ib(default="")
@dataclasses.dataclass
class TestDataClass:
name: list = dataclasses.field(default_factory=list)
# test item loaders
class NameItemLoader(ItemLoader):
default_item_class = TestItem
@ -187,16 +186,8 @@ class InitializationFromAttrsItemTest(InitializationTestMixin, unittest.TestCase
item_class = AttrsNameItem
@unittest.skipIf(not make_dataclass, "dataclasses module is not available")
class InitializationFromDataClassTest(InitializationTestMixin, unittest.TestCase):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
if make_dataclass:
self.item_class = make_dataclass(
"TestDataClass",
[("name", list, dataclass_field(default_factory=list))],
)
item_class = TestDataClass
class BaseNoInputReprocessingLoader(ItemLoader):

View File

@ -5,8 +5,9 @@ from datetime import datetime
from io import BytesIO
from shutil import rmtree
from tempfile import mkdtemp
from unittest import mock, skipIf
from unittest import mock
from urllib.parse import urlparse
import dataclasses
import attr
from itemadapter import ItemAdapter
@ -32,13 +33,6 @@ from scrapy.utils.test import (
)
try:
from dataclasses import make_dataclass, field as dataclass_field
except ImportError:
make_dataclass = None
dataclass_field = None
def _mocked_download_func(request, info):
response = request.meta.get('response')
return response() if callable(response) else response
@ -226,24 +220,19 @@ class FilesPipelineTestCaseFieldsItem(FilesPipelineTestCaseFieldsMixin, unittest
item_class = FilesPipelineTestItem
@skipIf(not make_dataclass, "dataclasses module is not available")
class FilesPipelineTestCaseFieldsDataClass(FilesPipelineTestCaseFieldsMixin, unittest.TestCase):
@dataclasses.dataclass
class FilesPipelineTestDataClass:
name: str
# default fields
file_urls: list = dataclasses.field(default_factory=list)
files: list = dataclasses.field(default_factory=list)
# overridden fields
custom_file_urls: list = dataclasses.field(default_factory=list)
custom_files: list = dataclasses.field(default_factory=list)
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
if make_dataclass:
self.item_class = make_dataclass(
"FilesPipelineTestDataClass",
[
("name", str),
# default fields
("file_urls", list, dataclass_field(default_factory=list)),
("files", list, dataclass_field(default_factory=list)),
# overridden fields
("custom_file_urls", list, dataclass_field(default_factory=list)),
("custom_files", list, dataclass_field(default_factory=list)),
],
)
class FilesPipelineTestCaseFieldsDataClass(FilesPipelineTestCaseFieldsMixin, unittest.TestCase):
item_class = FilesPipelineTestDataClass
@attr.s

View File

@ -3,7 +3,7 @@ import io
import random
from shutil import rmtree
from tempfile import mkdtemp
from unittest import skipIf
import dataclasses
import attr
from itemadapter import ItemAdapter
@ -16,13 +16,6 @@ from scrapy.settings import Settings
from scrapy.utils.python import to_bytes
try:
from dataclasses import make_dataclass, field as dataclass_field
except ImportError:
make_dataclass = None
dataclass_field = None
try:
from PIL import Image
except ImportError:
@ -203,25 +196,19 @@ class ImagesPipelineTestCaseFieldsItem(ImagesPipelineTestCaseFieldsMixin, unitte
item_class = ImagesPipelineTestItem
@skipIf(not make_dataclass, "dataclasses module is not available")
class ImagesPipelineTestCaseFieldsDataClass(ImagesPipelineTestCaseFieldsMixin, unittest.TestCase):
item_class = None
@dataclasses.dataclass
class ImagesPipelineTestDataClass:
name: str
# default fields
image_urls: list = dataclasses.field(default_factory=list)
images: list = dataclasses.field(default_factory=list)
# overridden fields
custom_image_urls: list = dataclasses.field(default_factory=list)
custom_images: list = dataclasses.field(default_factory=list)
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
if make_dataclass:
self.item_class = make_dataclass(
"FilesPipelineTestDataClass",
[
("name", str),
# default fields
("image_urls", list, dataclass_field(default_factory=list)),
("images", list, dataclass_field(default_factory=list)),
# overridden fields
("custom_image_urls", list, dataclass_field(default_factory=list)),
("custom_images", list, dataclass_field(default_factory=list)),
],
)
class ImagesPipelineTestCaseFieldsDataClass(ImagesPipelineTestCaseFieldsMixin, unittest.TestCase):
item_class = ImagesPipelineTestDataClass
@attr.s

View File

@ -1,6 +1,7 @@
import datetime
import json
import unittest
import dataclasses
from decimal import Decimal
import attr
@ -10,12 +11,6 @@ from scrapy.http import Request, Response
from scrapy.utils.serialize import ScrapyJSONEncoder
try:
from dataclasses import make_dataclass
except ImportError:
make_dataclass = None
class JsonEncoderTestCase(unittest.TestCase):
def setUp(self):
@ -56,12 +51,13 @@ class JsonEncoderTestCase(unittest.TestCase):
self.assertIn(r.url, rs)
self.assertIn(str(r.status), rs)
@unittest.skipIf(not make_dataclass, "No dataclass support")
def test_encode_dataclass_item(self):
TestDataClass = make_dataclass(
"TestDataClass",
[("name", str), ("url", str), ("price", int)],
)
@dataclasses.dataclass
class TestDataClass:
name: str
url: str
price: int
item = TestDataClass(name="Product", url="http://product.org", price=1)
encoded = self.encoder.encode(item)
self.assertEqual(