From a62d4b081c8eef1e54c6f7399e7a4154e3f330f3 Mon Sep 17 00:00:00 2001 From: Pawel Miech Date: Fri, 10 Jun 2016 12:48:02 +0200 Subject: [PATCH] [image-pipeline] image settings with class name allow to have image settings with class name, so that settings for user defined ImagePipeline subclasses can be defined easily. --- docs/topics/media-pipeline.rst | 6 +++--- scrapy/pipelines/images.py | 27 +++++++++++++++++++++------ tests/test_pipeline_images.py | 18 ++++++++++++++++-- 3 files changed, 40 insertions(+), 11 deletions(-) diff --git a/docs/topics/media-pipeline.rst b/docs/topics/media-pipeline.rst index 2b41a4f43..96339d03d 100644 --- a/docs/topics/media-pipeline.rst +++ b/docs/topics/media-pipeline.rst @@ -191,9 +191,9 @@ For the Images Pipeline, set :setting:`IMAGES_URLS_FIELD` and/or If you need something more complex and want to override the custom pipeline behaviour, see :ref:`topics-media-pipeline-override`. -.. note:: If you have multiple image pipelines and you want to have different settings in different pipelines - you can either set class attributes in pipeline object or add custom settings keys and load them at pipeline - initialization. +.. note:: If you have multiple image pipelines inheriting from ImagePipeline and you want to have different settings in different pipelines + you can set setting keys preceded with uppercase name of your pipeline class. E.g. if your pipeline is called + MyPipeline and you want to have custom IMAGES_URLS_FIELD you define setting MYPIPELINE_IMAGES_URLS_FIELD. Additional features diff --git a/scrapy/pipelines/images.py b/scrapy/pipelines/images.py index ac78ee6c0..9ba04750a 100644 --- a/scrapy/pipelines/images.py +++ b/scrapy/pipelines/images.py @@ -50,12 +50,27 @@ class ImagesPipeline(FilesPipeline): if isinstance(settings, dict) or settings is None: settings = Settings(settings) - self.expires = settings.getint('IMAGES_EXPIRES', self.EXPIRES) - self.images_urls_field = settings.get('IMAGES_URLS_FIELD', self.IMAGES_URLS_FIELD) - self.images_result_field = settings.get('IMAGES_RESULT_FIELD', self.IMAGES_RESULT_FIELD) - self.min_width = settings.getint('IMAGES_MIN_WIDTH', self.MIN_WIDTH) - self.min_height = settings.getint('IMAGES_MIN_HEIGHT', self.MIN_HEIGHT) - self.thumbs = settings.get('IMAGES_THUMBS', self.THUMBS) + def key_for_pipe(key): + """ + Allow setting settings for user defined ImagePipelines that inherit from base. + + User can define setting key: + + MYPIPELINENAME_IMAGE_SETTING_NAME = + + and it will override default settings and class attributes. + """ + class_name = self.__class__.__name__ + if class_name == "ImagesPipeline": + return key + return "{}_{}".format(class_name.upper(), key) + + self.expires = settings.getint(key_for_pipe('IMAGES_EXPIRES'), self.EXPIRES) + self.images_urls_field = settings.get(key_for_pipe('IMAGES_URLS_FIELD'), self.IMAGES_URLS_FIELD) + self.images_result_field = settings.get(key_for_pipe('IMAGES_RESULT_FIELD'), self.IMAGES_RESULT_FIELD) + self.min_width = settings.getint(key_for_pipe('IMAGES_MIN_WIDTH'), self.MIN_WIDTH) + self.min_height = settings.getint(key_for_pipe('IMAGES_MIN_HEIGHT'), self.MIN_HEIGHT) + self.thumbs = settings.get(key_for_pipe('IMAGES_THUMBS'), self.THUMBS) @classmethod def from_settings(cls, settings): diff --git a/tests/test_pipeline_images.py b/tests/test_pipeline_images.py index 49257e175..3b68faed0 100644 --- a/tests/test_pipeline_images.py +++ b/tests/test_pipeline_images.py @@ -265,7 +265,7 @@ class ImagesPipelineTestCaseCustomSettings(unittest.TestCase): pipeline = UserDefinedImagePipeline.from_settings(Settings({"IMAGES_STORE": self.tempdir})) self.assertEqual(pipeline.min_width, 1000) - def test_class_attrs_not_preserved_if_settings_defined(self): + def test_class_attrs_preserved_if_only_global_settings_defined(self): class UserDefinedImagePipeline(ImagesPipeline): MIN_WIDTH = 1000 @@ -277,7 +277,21 @@ class ImagesPipelineTestCaseCustomSettings(unittest.TestCase): # If image settings are defined they override class attributes. pipeline = UserDefinedImagePipeline.from_settings(Settings(settings)) - self.assertEqual(pipeline.min_width, 90) + self.assertEqual(pipeline.min_width, 1000) + + def test_settings_multiple_pipelilines(self): + # If user has multiple pipelines he can define setting keys preceded with + # pipeline class name. + class UserDefinedPipeline(ImagesPipeline): + pass + + settings = { + "IMAGES_MIN_WIDTH": 10, + "USERDEFINEDPIPELINE_IMAGES_MIN_WIDTH": 1999, + "IMAGES_STORE": self.tempdir + } + user_pipeline = UserDefinedPipeline.from_settings(Settings(settings)) + self.assertEqual(user_pipeline.min_width, 1999) def _create_image(format, *a, **kw):