From 2c251000d3f53f34e2d3610199f2fee9c6ecf8b0 Mon Sep 17 00:00:00 2001 From: palego Date: Sat, 31 Oct 2015 16:19:11 +0100 Subject: [PATCH] custom project templates allow override of TEMPLATES_DIR for startproject copy full TEMPLATES_DIR/project tree doc update --- docs/topics/settings.rst | 7 ++++++- scrapy/commands/startproject.py | 20 ++++++++++++-------- tests/test_commands.py | 23 ++++++++++++++++++++++- 3 files changed, 40 insertions(+), 10 deletions(-) diff --git a/docs/topics/settings.rst b/docs/topics/settings.rst index aa0417e1a..60b5f4585 100644 --- a/docs/topics/settings.rst +++ b/docs/topics/settings.rst @@ -1046,7 +1046,12 @@ TEMPLATES_DIR Default: ``templates`` dir inside scrapy module The directory where to look for templates when creating new projects with -:command:`startproject` command. +:command:`startproject` command and new spiders with :command:`genspider` +command. + +The project name must not conflict with the name of custom files or directories +in the ``project`` subdirectory. + .. setting:: URLLENGTH_LIMIT diff --git a/scrapy/commands/startproject.py b/scrapy/commands/startproject.py index 4375b6d4c..b3c5011df 100644 --- a/scrapy/commands/startproject.py +++ b/scrapy/commands/startproject.py @@ -1,10 +1,9 @@ from __future__ import print_function import re -import shutil import string from importlib import import_module from os.path import join, exists, abspath -from shutil import copytree, ignore_patterns +from shutil import copytree, ignore_patterns, move import scrapy from scrapy.commands import ScrapyCommand @@ -12,8 +11,6 @@ from scrapy.utils.template import render_templatefile, string_camelcase from scrapy.exceptions import UsageError -TEMPLATES_PATH = join(scrapy.__path__[0], 'templates', 'project') - TEMPLATES_TO_RENDER = ( ('scrapy.cfg',), ('${project_name}', 'settings.py.tmpl'), @@ -63,17 +60,24 @@ class Command(ScrapyCommand): self.exitcode = 1 return - moduletpl = join(TEMPLATES_PATH, 'module') - copytree(moduletpl, join(project_name, project_name), ignore=IGNORE) - shutil.copy(join(TEMPLATES_PATH, 'scrapy.cfg'), project_name) + copytree(self.templates_dir, project_name, ignore=IGNORE) + move(join(project_name, 'module'), join(project_name, project_name)) for paths in TEMPLATES_TO_RENDER: path = join(*paths) tplfile = join(project_name, string.Template(path).substitute(project_name=project_name)) render_templatefile(tplfile, project_name=project_name, ProjectName=string_camelcase(project_name)) - print("New Scrapy project %r created in:" % project_name) + print("New Scrapy project %r, using template directory %r, created in:" % \ + (project_name, self.templates_dir)) print(" %s\n" % abspath(project_name)) print("You can start your first spider with:") print(" cd %s" % project_name) print(" scrapy genspider example example.com") + + @property + def templates_dir(self): + _templates_base_dir = self.settings['TEMPLATES_DIR'] or \ + join(scrapy.__path__[0], 'templates') + return join(_templates_base_dir, 'project') + \ No newline at end of file diff --git a/tests/test_commands.py b/tests/test_commands.py index e0c0648ca..5755b3881 100644 --- a/tests/test_commands.py +++ b/tests/test_commands.py @@ -4,13 +4,14 @@ import subprocess import tempfile from time import sleep from os.path import exists, join, abspath -from shutil import rmtree +from shutil import rmtree, copytree from tempfile import mkdtemp import six from twisted.trial import unittest from twisted.internet import defer +import scrapy from scrapy.utils.python import to_native_str from scrapy.utils.python import retry_on_eintr from scrapy.utils.test import get_testenv @@ -71,6 +72,26 @@ class StartprojectTest(ProjectTest): self.assertEqual(1, self.call('startproject', self.project_name)) self.assertEqual(1, self.call('startproject', 'wrong---project---name')) self.assertEqual(1, self.call('startproject', 'sys')) + + +class StartprojectTemplatesTest(ProjectTest): + + def setUp(self): + super(StartprojectTemplatesTest, self).setUp() + self.tmpl = join(self.temp_path, 'templates') + self.tmpl_proj = join(self.tmpl, 'project') + + def test_startproject_template_override(self): + copytree(join(scrapy.__path__[0], 'templates'), self.tmpl) + os.mknod(join(self.tmpl_proj, 'root_template')) + assert exists(join(self.tmpl_proj, 'root_template')) + + args = ['--set', 'TEMPLATES_DIR=%s' % self.tmpl] + p = self.proc('startproject', self.project_name, *args) + out = to_native_str(retry_on_eintr(p.stdout.read)) + self.assertIn("New Scrapy project %r, using template directory %r, created in:" % \ + (self.project_name, join(self.tmpl, 'project')), out) + assert exists(join(self.proj_path, 'root_template')) class CommandTest(ProjectTest):