Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

allowing to run .pyw files #4646

Merged
merged 18 commits into from
Oct 1, 2020
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion scrapy/commands/runspider.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ def _import_file(filepath):
abspath = os.path.abspath(filepath)
dirname, file = os.path.split(abspath)
fname, fext = os.path.splitext(file)
if fext != '.py':
if fext not in ('.py', '.pyw'):
raise ValueError("Not a Python source file: %s" % abspath)
if dirname:
sys.path = [dirname] + sys.path
Expand Down
83 changes: 63 additions & 20 deletions tests/test_commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,8 @@ def test_list(self):

class RunSpiderCommandTest(CommandTest):

spider_filename = 'myspider.py'

debug_log_spider = """
import scrapy

Expand All @@ -387,24 +389,36 @@ def start_requests(self):
return []
"""

badspider = """
import scrapy

class BadSpider(scrapy.Spider):
name = "bad"
def start_requests(self):
raise Exception("oops!")
"""

@contextmanager
def _create_file(self, content, name):
def _create_file(self, content, name=None):
tmpdir = self.mktemp()
os.mkdir(tmpdir)
fname = abspath(join(tmpdir, name))
if name:
fname = abspath(join(tmpdir, name))
else:
fname = abspath(join(tmpdir, self.spider_filename))
with open(fname, 'w') as f:
f.write(content)
try:
yield fname
finally:
rmtree(tmpdir)

def runspider(self, code, name='myspider.py', args=()):
def runspider(self, code, name=None, args=()):
with self._create_file(code, name) as fname:
return self.proc('runspider', fname, *args)

def get_log(self, code, name='myspider.py', args=()):
p, stdout, stderr = self.runspider(code, name=name, args=args)
def get_log(self, code, name=None, args=()):
p, stdout, stderr = self.runspider(code, name, args=args)
return stderr

def test_runspider(self):
Expand Down Expand Up @@ -436,7 +450,7 @@ def test_runspider_dnscache_disabled(self):
# which is intended,
# but this should not be because of DNS lookup error
# assumption: localhost will resolve in all cases (true?)
log = self.get_log("""
dnscache_spider = """
import scrapy

class MySpider(scrapy.Spider):
Expand All @@ -445,23 +459,20 @@ class MySpider(scrapy.Spider):

def parse(self, response):
return {'test': 'value'}
""",
args=('-s', 'DNSCACHE_ENABLED=False'))
print(log)
"""
log = self.get_log(dnscache_spider, args=('-s', 'DNSCACHE_ENABLED=False'))
self.assertNotIn("DNSLookupError", log)
self.assertIn("INFO: Spider opened", log)

def test_runspider_log_short_names(self):
log1 = self.get_log(self.debug_log_spider,
args=('-s', 'LOG_SHORT_NAMES=1'))
print(log1)
self.assertIn("[myspider] DEBUG: It Works!", log1)
self.assertIn("[scrapy]", log1)
self.assertNotIn("[scrapy.core.engine]", log1)

log2 = self.get_log(self.debug_log_spider,
args=('-s', 'LOG_SHORT_NAMES=0'))
print(log2)
akshaysharmajs marked this conversation as resolved.
Show resolved Hide resolved
self.assertIn("[myspider] DEBUG: It Works!", log2)
self.assertNotIn("[scrapy]", log2)
self.assertIn("[scrapy.core.engine]", log2)
Expand All @@ -479,15 +490,7 @@ def test_runspider_unable_to_load(self):
self.assertIn('Unable to load', log)

def test_start_requests_errors(self):
log = self.get_log("""
import scrapy

class BadSpider(scrapy.Spider):
name = "bad"
def start_requests(self):
raise Exception("oops!")
""", name="badspider.py")
print(log)
log = self.get_log(self.badspider, name='badspider.py')
self.assertIn("start_requests", log)
self.assertIn("badspider.py", log)

Expand All @@ -505,6 +508,46 @@ def test_asyncio_enabled_false(self):
self.assertNotIn("Using reactor: twisted.internet.asyncioreactor.AsyncioSelectorReactor", log)


class WindowsRunSpiderCommandTest(RunSpiderCommandTest):

spider_filename = 'myspider.pyw'

def setUp(self):
super(WindowsRunSpiderCommandTest, self).setUp()

def test_start_requests_errors(self):
log = self.get_log(self.badspider, name='badspider.pyw')
self.assertIn("start_requests", log)
self.assertIn("badspider.pyw", log)

@skipIf(platform.system() != 'Windows', "Windows required for .pyw files")
def test_run_good_spider(self):
super().test_run_good_spider()

@skipIf(platform.system() != 'Windows', "Windows required for .pyw files")
def test_runspider(self):
super().test_runspider()

@skipIf(platform.system() != 'Windows', "Windows required for .pyw files")
def test_runspider_dnscache_disabled(self):
super().test_runspider_dnscache_disabled()

@skipIf(platform.system() != 'Windows', "Windows required for .pyw files")
def test_runspider_log_level(self):
super().test_runspider_log_level()

@skipIf(platform.system() != 'Windows', "Windows required for .pyw files")
def test_runspider_log_short_names(self):
super().test_runspider_log_short_names()

@skipIf(platform.system() != 'Windows', "Windows required for .pyw files")
def test_runspider_no_spider_found(self):
super().test_runspider_no_spider_found()

Gallaecio marked this conversation as resolved.
Show resolved Hide resolved
def test_runspider_unable_to_load(self):
raise unittest.SkipTest("Already Tested in 'RunSpiderCommandTest' ")


class BenchCommandTest(CommandTest):

def test_run(self):
Expand Down