diff --git a/.travis.yml b/.travis.yml
index 6bde973f4..cb54c8008 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -15,19 +15,25 @@ matrix:
python: 3.7 # Keep in sync with .readthedocs.yml
- env: TOXENV=pypy3
- - python: 3.5
+ - env: TOXENV=py
+ python: 3.5
- env: TOXENV=pinned
python: 3.5
- env: TOXENV=asyncio
python: 3.5.2
- - python: 3.6
- - python: 3.7
- - env: PYPI_RELEASE_JOB=true
+ - env: TOXENV=py
+ python: 3.6
+ - env: TOXENV=py
+ python: 3.7
+ - env: TOXENV=py PYPI_RELEASE_JOB=true
python: 3.8
+ dist: bionic
- env: TOXENV=extra-deps
python: 3.8
+ dist: bionic
- env: TOXENV=asyncio
python: 3.8
+ dist: bionic
install:
- |
if [ "$TOXENV" = "pypy3" ]; then
diff --git a/pytest.ini b/pytest.ini
index 1a73b41be..604bbfe1d 100644
--- a/pytest.ini
+++ b/pytest.ini
@@ -50,26 +50,26 @@ flake8-ignore =
scrapy/core/engine.py E501 E128
scrapy/core/scheduler.py E501
scrapy/core/scraper.py E501 E128
- scrapy/core/spidermw.py E501 E126
+ scrapy/core/spidermw.py E501
scrapy/core/downloader/__init__.py E501
- scrapy/core/downloader/contextfactory.py E501 E128 E126
+ scrapy/core/downloader/contextfactory.py E501 E128
scrapy/core/downloader/middleware.py E501
scrapy/core/downloader/tls.py E501
- scrapy/core/downloader/webclient.py E501 E128 E126
+ scrapy/core/downloader/webclient.py E501 E128
scrapy/core/downloader/handlers/__init__.py E501
scrapy/core/downloader/handlers/ftp.py E501 E128
scrapy/core/downloader/handlers/http10.py E501
scrapy/core/downloader/handlers/http11.py E501
- scrapy/core/downloader/handlers/s3.py E501 E128 E126
+ scrapy/core/downloader/handlers/s3.py E501 E128
# scrapy/downloadermiddlewares
scrapy/downloadermiddlewares/ajaxcrawl.py E501
scrapy/downloadermiddlewares/decompression.py E501
scrapy/downloadermiddlewares/defaultheaders.py E501
- scrapy/downloadermiddlewares/httpcache.py E501 E126
+ scrapy/downloadermiddlewares/httpcache.py E501
scrapy/downloadermiddlewares/httpcompression.py E501 E128
scrapy/downloadermiddlewares/httpproxy.py E501
scrapy/downloadermiddlewares/redirect.py E501
- scrapy/downloadermiddlewares/retry.py E501 E126
+ scrapy/downloadermiddlewares/retry.py E501
scrapy/downloadermiddlewares/robotstxt.py E501
scrapy/downloadermiddlewares/stats.py E501
# scrapy/extensions
@@ -88,7 +88,7 @@ flake8-ignore =
scrapy/http/request/form.py E501
scrapy/http/request/json_request.py E501
scrapy/http/response/__init__.py E501 E128
- scrapy/http/response/text.py E501 E128 E124
+ scrapy/http/response/text.py E501 E128
# scrapy/linkextractors
scrapy/linkextractors/__init__.py E501 E402
scrapy/linkextractors/lxmlhtml.py E501
@@ -110,7 +110,7 @@ flake8-ignore =
# scrapy/spidermiddlewares
scrapy/spidermiddlewares/httperror.py E501
scrapy/spidermiddlewares/offsite.py E501
- scrapy/spidermiddlewares/referer.py E501 E129
+ scrapy/spidermiddlewares/referer.py E501
scrapy/spidermiddlewares/urllength.py E501
# scrapy/spiders
scrapy/spiders/__init__.py E501 E402
@@ -164,12 +164,12 @@ flake8-ignore =
scrapy/robotstxt.py E501
scrapy/shell.py E501
scrapy/signalmanager.py E501
- scrapy/spiderloader.py F841 E501 E126
+ scrapy/spiderloader.py F841 E501
scrapy/squeues.py E128
scrapy/statscollectors.py E501
# tests
tests/__init__.py E402 E501
- tests/mockserver.py E501 E126
+ tests/mockserver.py E501
tests/pipelines.py F841
tests/spiders.py E501
tests/test_closespider.py E501
@@ -181,37 +181,37 @@ flake8-ignore =
tests/test_crawl.py E501 E741
tests/test_crawler.py F841 E501
tests/test_dependencies.py F841 E501
- tests/test_downloader_handlers.py E124 E128 E501 E126
+ tests/test_downloader_handlers.py E128 E501
tests/test_downloadermiddleware.py E501
tests/test_downloadermiddleware_ajaxcrawlable.py E501
- tests/test_downloadermiddleware_cookies.py E741 E501 E128 E126
+ tests/test_downloadermiddleware_cookies.py E741 E501 E128
tests/test_downloadermiddleware_defaultheaders.py E501
tests/test_downloadermiddleware_downloadtimeout.py E501
tests/test_downloadermiddleware_httpcache.py E501
- tests/test_downloadermiddleware_httpcompression.py E501 E126
+ tests/test_downloadermiddleware_httpcompression.py E501
tests/test_downloadermiddleware_decompression.py E501
tests/test_downloadermiddleware_httpproxy.py E501 E128
tests/test_downloadermiddleware_redirect.py E501 E128
- tests/test_downloadermiddleware_retry.py E501 E128 E126
+ tests/test_downloadermiddleware_retry.py E501 E128
tests/test_downloadermiddleware_robotstxt.py E501
tests/test_downloadermiddleware_stats.py E501
- tests/test_dupefilters.py E501 E741 E128 E124
+ tests/test_dupefilters.py E501 E741 E128
tests/test_engine.py E501 E128
- tests/test_exporters.py E501 E128 E124
+ tests/test_exporters.py E501 E128
tests/test_extension_telnet.py F841
tests/test_feedexport.py E501 F841
tests/test_http_cookies.py E501
tests/test_http_headers.py E501
- tests/test_http_request.py E402 E501 E128 E128 E126
+ tests/test_http_request.py E402 E501 E128 E128
tests/test_http_response.py E501 E128
tests/test_item.py E128 F841
tests/test_link.py E501
- tests/test_linkextractors.py E501 E128 E124
+ tests/test_linkextractors.py E501 E128
tests/test_loader.py E501 E741 E128 E117
- tests/test_logformatter.py E128 E501 E122
+ tests/test_logformatter.py E128 E501
tests/test_mail.py E128 E501
tests/test_middleware.py E501 E128
- tests/test_pipeline_crawl.py E501 E128 E126
+ tests/test_pipeline_crawl.py E501 E128
tests/test_pipeline_files.py E501
tests/test_pipeline_images.py F841 E501
tests/test_pipeline_media.py E501 E741 E128
@@ -219,14 +219,14 @@ flake8-ignore =
tests/test_request_cb_kwargs.py E501
tests/test_responsetypes.py E501
tests/test_robotstxt_interface.py E501 E501
- tests/test_scheduler.py E501 E126
+ tests/test_scheduler.py E501
tests/test_selector.py E501
tests/test_spider.py E501
tests/test_spidermiddleware.py E501
tests/test_spidermiddleware_httperror.py E128 E501 E121
tests/test_spidermiddleware_offsite.py E501 E128 E111
tests/test_spidermiddleware_output_chain.py E501
- tests/test_spidermiddleware_referer.py E501 F841 E124 E501 E121
+ tests/test_spidermiddleware_referer.py E501 F841 E501 E121
tests/test_squeues.py E501 E741
tests/test_utils_asyncio.py E501
tests/test_utils_conf.py E501 E128
@@ -235,16 +235,16 @@ flake8-ignore =
tests/test_utils_defer.py E501 F841
tests/test_utils_deprecate.py F841 E501
tests/test_utils_http.py E501 E128
- tests/test_utils_iterators.py E501 E128 E129
+ tests/test_utils_iterators.py E501 E128
tests/test_utils_log.py E741
tests/test_utils_python.py E501
tests/test_utils_reqser.py E501 E128
tests/test_utils_request.py E501 E128
tests/test_utils_response.py E501
tests/test_utils_signal.py E741 F841
- tests/test_utils_sitemap.py E128 E501 E124
- tests/test_utils_url.py E501 E501 E126
- tests/test_webclient.py E501 E128 E122 E402 E126
+ tests/test_utils_sitemap.py E128 E501
+ tests/test_utils_url.py E501 E501
+ tests/test_webclient.py E501 E128 E402
tests/test_cmdline/__init__.py E501
tests/test_settings/__init__.py E501 E128
tests/test_spiderloader/__init__.py E128 E501
diff --git a/scrapy/core/downloader/contextfactory.py b/scrapy/core/downloader/contextfactory.py
index 6e023ebcc..ab73e12c8 100644
--- a/scrapy/core/downloader/contextfactory.py
+++ b/scrapy/core/downloader/contextfactory.py
@@ -86,8 +86,8 @@ class BrowserLikeContextFactory(ScrapyClientContextFactory):
#
# This means that a website like https://www.cacert.org will be rejected
# by default, since CAcert.org CA certificate is seldom shipped.
- return optionsForClientTLS(hostname.decode("ascii"),
- trustRoot=platformTrust(),
- extraCertificateOptions={
- 'method': self._ssl_method,
- })
+ return optionsForClientTLS(
+ hostname=hostname.decode("ascii"),
+ trustRoot=platformTrust(),
+ extraCertificateOptions={'method': self._ssl_method},
+ )
diff --git a/scrapy/core/downloader/handlers/s3.py b/scrapy/core/downloader/handlers/s3.py
index 40a1fa48e..8f63ad974 100644
--- a/scrapy/core/downloader/handlers/s3.py
+++ b/scrapy/core/downloader/handlers/s3.py
@@ -100,11 +100,12 @@ class S3DownloadHandler:
url=url, headers=awsrequest.headers.items())
else:
signed_headers = self.conn.make_request(
- method=request.method,
- bucket=bucket,
- key=unquote(p.path),
- query_args=unquote(p.query),
- headers=request.headers,
- data=request.body)
+ method=request.method,
+ bucket=bucket,
+ key=unquote(p.path),
+ query_args=unquote(p.query),
+ headers=request.headers,
+ data=request.body,
+ )
request = request.replace(url=url, headers=signed_headers)
return self._download_http(request, spider)
diff --git a/scrapy/core/downloader/webclient.py b/scrapy/core/downloader/webclient.py
index a90a77b2b..355045d74 100644
--- a/scrapy/core/downloader/webclient.py
+++ b/scrapy/core/downloader/webclient.py
@@ -88,8 +88,8 @@ class ScrapyHTTPPageGetter(HTTPClient):
self.transport.stopProducing()
self.factory.noPage(
- defer.TimeoutError("Getting %s took longer than %s seconds." %
- (self.factory.url, self.factory.timeout)))
+ defer.TimeoutError("Getting %s took longer than %s seconds."
+ % (self.factory.url, self.factory.timeout)))
class ScrapyHTTPClientFactory(HTTPClientFactory):
diff --git a/scrapy/downloadermiddlewares/retry.py b/scrapy/downloadermiddlewares/retry.py
index bbf5fca05..6d11af5b2 100644
--- a/scrapy/downloadermiddlewares/retry.py
+++ b/scrapy/downloadermiddlewares/retry.py
@@ -12,9 +12,15 @@ once the spider has finished crawling all regular (non failed) pages.
import logging
from twisted.internet import defer
-from twisted.internet.error import TimeoutError, DNSLookupError, \
- ConnectionRefusedError, ConnectionDone, ConnectError, \
- ConnectionLost, TCPTimedOutError
+from twisted.internet.error import (
+ ConnectError,
+ ConnectionDone,
+ ConnectionLost,
+ ConnectionRefusedError,
+ DNSLookupError,
+ TCPTimedOutError,
+ TimeoutError,
+)
from twisted.web.client import ResponseFailed
from scrapy.exceptions import NotConfigured
diff --git a/scrapy/spiderloader.py b/scrapy/spiderloader.py
index b3dd79417..a908d6874 100644
--- a/scrapy/spiderloader.py
+++ b/scrapy/spiderloader.py
@@ -16,6 +16,7 @@ class SpiderLoader:
SpiderLoader is a class which locates and loads spiders
in a Scrapy project.
"""
+
def __init__(self, settings):
self.require_name = settings.getbool('SPIDER_LOADER_REQUIRE_NAME')
if self.require_name:
@@ -34,16 +35,21 @@ class SpiderLoader:
self._load_all_spiders()
def _check_name_duplicates(self):
- dupes = ["\n".join(" {cls} named {name!r} (in {module})".format(
- module=mod, cls=cls, name=name)
- for (mod, cls) in locations)
- for name, locations in self._found.items()
- if len(locations) > 1]
+ dupes = []
+ for name, locations in self._found.items():
+ dupes.extend([
+ " {cls} named {name!r} (in {module})".format(module=mod, cls=cls, name=name)
+ for mod, cls in locations
+ if len(locations) > 1
+ ])
+
if dupes:
- msg = ("There are several spiders with the same name:\n\n"
- "{}\n\n This can cause unexpected behavior.".format(
- "\n\n".join(dupes)))
- warnings.warn(msg, UserWarning)
+ dupes_string = "\n\n".join(dupes)
+ warnings.warn(
+ "There are several spiders with the same name:\n\n"
+ "{}\n\n This can cause unexpected behavior.".format(dupes_string),
+ category=UserWarning,
+ )
def _load_spiders(self, module):
classes = iter_spider_classes(module, require_name=self.require_name)
@@ -58,12 +64,15 @@ class SpiderLoader:
try:
for module in walk_modules(name):
self._load_spiders(module)
- except ImportError as e:
+ except ImportError:
if self.warn_only:
- msg = ("\n{tb}Could not load spiders from module '{modname}'. "
- "See above traceback for details.".format(
- modname=name, tb=traceback.format_exc()))
- warnings.warn(msg, RuntimeWarning)
+ warnings.warn(
+ "\n{tb}Could not load spiders from module '{modname}'. "
+ "See above traceback for details.".format(
+ modname=name, tb=traceback.format_exc()
+ ),
+ category=RuntimeWarning,
+ )
else:
raise
self._check_name_duplicates()
@@ -86,8 +95,10 @@ class SpiderLoader:
"""
Return the list of spider names that can handle the given request.
"""
- return [name for name, cls in self._spiders.items()
- if cls.handles_request(request)]
+ return [
+ name for name, cls in self._spiders.items()
+ if cls.handles_request(request)
+ ]
def list(self):
"""
diff --git a/tests/test_crawler.py b/tests/test_crawler.py
index c3082fa98..1f38e60f8 100644
--- a/tests/test_crawler.py
+++ b/tests/test_crawler.py
@@ -313,14 +313,7 @@ class CrawlerProcessSubprocess(ScriptRunnerMixin, unittest.TestCase):
def test_ipv6_alternative_name_resolver(self):
log = self.run_script('alternative_name_resolver.py')
self.assertIn('Spider closed (finished)', log)
- self.assertTrue(any([
- "twisted.internet.error.ConnectionRefusedError" in log,
- "twisted.internet.error.ConnectError" in log,
- ]))
- self.assertTrue(any([
- "'downloader/exception_type_count/twisted.internet.error.ConnectionRefusedError': 1," in log,
- "'downloader/exception_type_count/twisted.internet.error.ConnectError': 1," in log,
- ]))
+ self.assertNotIn("twisted.internet.error.DNSLookupError", log)
def test_reactor_select(self):
log = self.run_script("twisted_reactor_select.py")
diff --git a/tests/test_downloadermiddleware_cookies.py b/tests/test_downloadermiddleware_cookies.py
index b686a14d6..f86c50f50 100644
--- a/tests/test_downloadermiddleware_cookies.py
+++ b/tests/test_downloadermiddleware_cookies.py
@@ -139,10 +139,12 @@ class CookiesMiddlewareTest(TestCase):
def test_complex_cookies(self):
# merge some cookies into jar
- cookies = [{'name': 'C1', 'value': 'value1', 'path': '/foo', 'domain': 'scrapytest.org'},
- {'name': 'C2', 'value': 'value2', 'path': '/bar', 'domain': 'scrapytest.org'},
- {'name': 'C3', 'value': 'value3', 'path': '/foo', 'domain': 'scrapytest.org'},
- {'name': 'C4', 'value': 'value4', 'path': '/foo', 'domain': 'scrapy.org'}]
+ cookies = [
+ {'name': 'C1', 'value': 'value1', 'path': '/foo', 'domain': 'scrapytest.org'},
+ {'name': 'C2', 'value': 'value2', 'path': '/bar', 'domain': 'scrapytest.org'},
+ {'name': 'C3', 'value': 'value3', 'path': '/foo', 'domain': 'scrapytest.org'},
+ {'name': 'C4', 'value': 'value4', 'path': '/foo', 'domain': 'scrapy.org'},
+ ]
req = Request('http://scrapytest.org/', cookies=cookies)
self.mw.process_request(req, self.spider)
diff --git a/tests/test_downloadermiddleware_retry.py b/tests/test_downloadermiddleware_retry.py
index 9c989977e..e118750e3 100644
--- a/tests/test_downloadermiddleware_retry.py
+++ b/tests/test_downloadermiddleware_retry.py
@@ -1,8 +1,14 @@
import unittest
from twisted.internet import defer
-from twisted.internet.error import TimeoutError, DNSLookupError, \
- ConnectionRefusedError, ConnectionDone, ConnectError, \
- ConnectionLost, TCPTimedOutError
+from twisted.internet.error import (
+ ConnectError,
+ ConnectionDone,
+ ConnectionLost,
+ ConnectionRefusedError,
+ DNSLookupError,
+ TCPTimedOutError,
+ TimeoutError,
+)
from twisted.web.client import ResponseFailed
from scrapy.downloadermiddlewares.retry import RetryMiddleware
diff --git a/tests/test_dupefilters.py b/tests/test_dupefilters.py
index ea0e664be..7426107c1 100644
--- a/tests/test_dupefilters.py
+++ b/tests/test_dupefilters.py
@@ -197,8 +197,7 @@ class RFPDupeFilterTest(unittest.TestCase):
r1 = Request('http://scrapytest.org/index.html')
r2 = Request('http://scrapytest.org/index.html',
- headers={'Referer': 'http://scrapytest.org/INDEX.html'}
- )
+ headers={'Referer': 'http://scrapytest.org/INDEX.html'})
dupefilter.log(r1, spider)
dupefilter.log(r2, spider)
diff --git a/tests/test_exporters.py b/tests/test_exporters.py
index 160912847..0f9dafcaa 100644
--- a/tests/test_exporters.py
+++ b/tests/test_exporters.py
@@ -342,20 +342,22 @@ class XmlItemExporterTest(BaseItemExporterTest):
i2 = dict(name=u'bar', age=i1)
i3 = TestItem(name=u'buz', age=i2)
- self.assertExportResult(i3,
- b'\n'
- b'