""" Test cases for the template loaders Note: This test requires setuptools! """ from djangocg.conf import settings if __name__ == '__main__': settings.configure() import sys import pkg_resources import imp import os.path from djangocg.template import TemplateDoesNotExist, Context from djangocg.template.loaders.eggs import Loader as EggLoader from djangocg.template import loader from djangocg.utils import unittest from djangocg.utils.six import StringIO # Mock classes and objects for pkg_resources functions. class MockProvider(pkg_resources.NullProvider): def __init__(self, module): pkg_resources.NullProvider.__init__(self, module) self.module = module def _has(self, path): return path in self.module._resources
def handle(self, app_or_project, name, target=None, **options): self.app_or_project = app_or_project self.paths_to_remove = [] self.verbosity = int(options.get('verbosity')) # If it's not a valid directory name. if not re.search(r'^[_a-zA-Z]\w*$', name): # Provide a smart error message, depending on the error. if not re.search(r'^[_a-zA-Z]', name): message = ('make sure the name begins ' 'with a letter or underscore') else: message = 'use only numbers, letters and underscores' raise CommandError("%r is not a valid %s name. Please %s." % (name, app_or_project, message)) # if some directory is given, make sure it's nicely expanded if target is None: top_dir = path.join(os.getcwd(), name) try: os.makedirs(top_dir) except OSError as e: if e.errno == errno.EEXIST: message = "'%s' already exists" % top_dir else: message = e raise CommandError(message) else: top_dir = os.path.abspath(path.expanduser(target)) if not os.path.exists(top_dir): raise CommandError("Destination directory '%s' does not " "exist, please create it first." % top_dir) extensions = tuple( handle_extensions(options.get('extensions'), ignored=())) extra_files = [] for file in options.get('files'): extra_files.extend(map(lambda x: x.strip(), file.split(','))) if self.verbosity >= 2: self.stdout.write("Rendering %s template files with " "extensions: %s\n" % (app_or_project, ', '.join(extensions))) self.stdout.write("Rendering %s template files with " "filenames: %s\n" % (app_or_project, ', '.join(extra_files))) base_name = '%s_name' % app_or_project base_subdir = '%s_template' % app_or_project base_directory = '%s_directory' % app_or_project context = Context(dict(options, **{ base_name: name, base_directory: top_dir, }), autoescape=False) # Setup a stub settings environment for template rendering from djangocg.conf import settings if not settings.configured: settings.configure() template_dir = self.handle_template(options.get('template'), base_subdir) prefix_length = len(template_dir) + 1 for root, dirs, files in os.walk(template_dir): path_rest = root[prefix_length:] relative_dir = path_rest.replace(base_name, name) if relative_dir: target_dir = path.join(top_dir, relative_dir) if not path.exists(target_dir): os.mkdir(target_dir) for dirname in dirs[:]: if dirname.startswith('.'): dirs.remove(dirname) for filename in files: if filename.endswith(('.pyo', '.pyc', '.py.class')): # Ignore some files as they cause various breakages. continue old_path = path.join(root, filename) new_path = path.join(top_dir, relative_dir, filename.replace(base_name, name)) if path.exists(new_path): raise CommandError("%s already exists, overlaying a " "project or app into an existing " "directory won't replace conflicting " "files" % new_path) # Only render the Python files, as we don't want to # accidentally render Django templates files with codecs.open(old_path, 'r', 'utf-8') as template_file: content = template_file.read() if filename.endswith(extensions) or filename in extra_files: template = Template(content) content = template.render(context) with codecs.open(new_path, 'w', 'utf-8') as new_file: new_file.write(content) if self.verbosity >= 2: self.stdout.write("Creating %s\n" % new_path) try: shutil.copymode(old_path, new_path) self.make_writeable(new_path) except OSError: self.stderr.write( "Notice: Couldn't set permission bits on %s. You're " "probably using an uncommon filesystem setup. No " "problem." % new_path, self.style.NOTICE) if self.paths_to_remove: if self.verbosity >= 2: self.stdout.write("Cleaning up temporary files.\n") for path_to_remove in self.paths_to_remove: if path.isfile(path_to_remove): os.remove(path_to_remove) else: shutil.rmtree(path_to_remove, onerror=rmtree_errorhandler)
def make_messages(locale=None, domain='django', verbosity=1, all=False, extensions=None, symlinks=False, ignore_patterns=None, no_wrap=False, no_location=False, no_obsolete=False, stdout=sys.stdout): """ Uses the ``locale/`` directory from the Django Git tree or an application/project to process all files with translatable literals for the :param domain: domain and :param locale: locale. """ # Need to ensure that the i18n framework is enabled from djangocg.conf import settings if settings.configured: settings.USE_I18N = True else: settings.configure(USE_I18N = True) if ignore_patterns is None: ignore_patterns = [] invoked_for_django = False if os.path.isdir(os.path.join('conf', 'locale')): localedir = os.path.abspath(os.path.join('conf', 'locale')) invoked_for_django = True # Ignoring all contrib apps ignore_patterns += ['contrib/*'] elif os.path.isdir('locale'): localedir = os.path.abspath('locale') else: raise CommandError("This script should be run from the Django Git " "tree or your project or app tree. If you did indeed run it " "from the Git checkout or your project or application, " "maybe you are just missing the conf/locale (in the django " "tree) or locale (for project and application) directory? It " "is not created automatically, you have to create it by hand " "if you want to enable i18n for your project or application.") if domain not in ('django', 'djangojs'): raise CommandError("currently makemessages only supports domains 'django' and 'djangojs'") if (locale is None and not all) or domain is None: message = "Type '%s help %s' for usage information." % (os.path.basename(sys.argv[0]), sys.argv[1]) raise CommandError(message) # We require gettext version 0.15 or newer. output, errors, status = _popen('xgettext --version') if status != STATUS_OK: raise CommandError("Error running xgettext. Note that Django " "internationalization requires GNU gettext 0.15 or newer.") match = re.search(r'(?P<major>\d+)\.(?P<minor>\d+)', output) if match: xversion = (int(match.group('major')), int(match.group('minor'))) if xversion < (0, 15): raise CommandError("Django internationalization requires GNU " "gettext 0.15 or newer. You are using version %s, please " "upgrade your gettext toolset." % match.group()) locales = [] if locale is not None: locales.append(locale) elif all: locale_dirs = filter(os.path.isdir, glob.glob('%s/*' % localedir)) locales = [os.path.basename(l) for l in locale_dirs] wrap = '--no-wrap' if no_wrap else '' location = '--no-location' if no_location else '' for locale in locales: if verbosity > 0: stdout.write("processing language %s\n" % locale) basedir = os.path.join(localedir, locale, 'LC_MESSAGES') if not os.path.isdir(basedir): os.makedirs(basedir) pofile = os.path.join(basedir, '%s.po' % domain) potfile = os.path.join(basedir, '%s.pot' % domain) if os.path.exists(potfile): os.unlink(potfile) for dirpath, file in find_files(".", ignore_patterns, verbosity, stdout, symlinks=symlinks): process_file(file, dirpath, potfile, domain, verbosity, extensions, wrap, location, stdout) if os.path.exists(potfile): write_po_file(pofile, potfile, domain, locale, verbosity, stdout, not invoked_for_django, wrap, location, no_obsolete)