[Python-modules-commits] [cookiecutter] 01/06: Import cookiecutter_1.4.0.orig.tar.gz
Vincent Bernat
bernat at moszumanska.debian.org
Mon May 2 06:23:19 UTC 2016
This is an automated email from the git hooks/post-receive script.
bernat pushed a commit to branch master
in repository cookiecutter.
commit 2cff56151f5e99b0914d57e6202c4ce7abd84935
Author: Vincent Bernat <bernat at debian.org>
Date: Mon May 2 08:05:04 2016 +0200
Import cookiecutter_1.4.0.orig.tar.gz
---
.gitignore | 68 +++++++-----
AUTHORS.rst | 14 +++
HISTORY.rst | 97 ++++++++++++++++-
README.rst | 37 +++++--
appveyor.yml | 2 +
cookiecutter/__init__.py | 2 +-
cookiecutter/cli.py | 24 ++++-
cookiecutter/config.py | 29 ++++--
cookiecutter/environment.py | 52 +++++++++
cookiecutter/exceptions.py | 27 +++++
cookiecutter/generate.py | 63 +++++++----
cookiecutter/main.py | 26 +++--
cookiecutter/prompt.py | 37 ++++---
cookiecutter/replay.py | 14 +--
docs/advanced_usage.rst | 116 ++++++++++++++++++++-
docs/cookiecutter.rst | 8 ++
docs/troubleshooting.rst | 4 +-
docs/usage.rst | 2 +-
setup.cfg | 2 +-
setup.py | 24 ++---
.../{{cookiecutter.repo_dir}}/README.rst | 4 +-
tests/replay/conftest.py | 11 +-
tests/replay/test_dump.py | 23 ++--
tests/replay/test_load.py | 16 +--
tests/replay/test_replay.py | 4 +-
tests/test-config/config-expand-user.yaml | 2 +
tests/test-config/config-expand-vars.yaml | 2 +
tests/test-extensions/default/cookiecutter.json | 4 +
.../{{cookiecutter.project_slug}}/HISTORY.rst | 7 ++
tests/test-extensions/unknown/cookiecutter.json | 6 ++
.../{{cookiecutter.project_slug}}/HISTORY.rst | 7 ++
.../input{{cookiecutter.binary_test}}/readme.txt | 2 +-
.../{{cookiecutter.binary_test}}/readme.txt | 2 +-
tests/test_cli.py | 48 +++++++++
tests/test_default_extensions.py | 41 ++++++++
tests/test_environment.py | 24 +++++
tests/test_exceptions.py | 21 ++++
tests/test_generate_file.py | 4 +-
tests/test_generate_files.py | 79 ++++++++++++++
tests/test_get_config.py | 7 +-
tests/test_get_user_config.py | 41 +++++---
tests/test_main.py | 41 ++++++--
tests/test_prompt.py | 55 ++++++++--
tests/test_repo_not_found.py | 10 ++
.../{{cookiecutter.project_slug}}/README.rst | 2 +
.../{{cookiecutter.foobar}}/helloworld.py | 0
.../{{cookiecutter.project_slug}}/README.rst | 6 ++
.../undefined-variable/file-name/cookiecutter.json | 4 +
.../{{cookiecutter.foobar}} | 2 +
tox.ini | 1 +
50 files changed, 931 insertions(+), 193 deletions(-)
diff --git a/.gitignore b/.gitignore
index b3c9815..3850476 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,48 +1,62 @@
+# Byte-compiled / optimized / DLL files
+__pycache__/
*.py[cod]
+*$py.class
# C extensions
*.so
-# Packages
-*.egg
-*.egg-info
-dist
-build
-eggs
-parts
-bin
-var
-sdist
-develop-eggs
+# Distribution / packaging
+.Python
+env/
+build/
+develop-eggs/
+dist/
+downloads/
+eggs/
+.eggs/
+lib/
+lib64/
+parts/
+sdist/
+var/
+*.egg-info/
.installed.cfg
-lib
-lib64
+*.egg
+
+# PyInstaller
+# Usually these files are written by a python script from a template
+# before PyInstaller builds the exe, so as to inject date/other infos into it.
+*.manifest
+*.spec
# Installer logs
pip-log.txt
+pip-delete-this-directory.txt
# Unit test / coverage reports
+htmlcov/
+.tox/
.coverage
-.tox
+.coverage.*
.cache
nosetests.xml
+coverage.xml
+*,cover
+.hypothesis/
# Translations
*.mo
+*.pot
-# Mr Developer
-.mr.developer.cfg
-.project
-.pydevproject
-
-# Sphinx
-docs/_build
+# Django stuff:
+*.log
-# Coverage
-htmlcov/
+# Sphinx documentation
+docs/_build/
-# TextMate
-.tm_properties
+# PyBuilder
+target/
-# Local env
-.envs
+# PyCharm
+.idea/
diff --git a/AUTHORS.rst b/AUTHORS.rst
index 2e736f4..1cd4893 100644
--- a/AUTHORS.rst
+++ b/AUTHORS.rst
@@ -77,7 +77,16 @@ Contributors
* Valentin Lab (`@vaab`_)
* Ilja Bauer (`@iljabauer`_)
* Elias Dorneles (`@eliasdorneles`_)
+* Matias Saguir (`@mativs`_)
+* Johannes (`@johtso`_)
+* macrotim (`@macrotim`_)
+* Will McGinnis (`@wdm0006`_)
+* Cédric Krier (`@cedk`_)
+* Tim Osborn (`@ptim`_)
+* Aaron Gallagher (`@habnabit`_)
+.. _`@cedk`: https://github.com/cedk
+.. _`@johtso`: https://github.com/johtso
.. _`@maiksensi`: https://github.com/maiksensi
.. _`@svisser`: https://github.com/svisser
.. _`@LucianU`: https://github.com/LucianU
@@ -142,3 +151,8 @@ Contributors
.. _`@vaab`: https://github.com/vaab
.. _`@iljabauer`: https://github.com/iljabauer
.. _`@eliasdorneles`: https://github.com/eliasdorneles
+.. _`@mativs`: https://github.com/mativs
+.. _`@macrotim`: https://github.com/macrotim
+.. _`@wdm0006`: https://github.com/wdm0006
+.. _`@ptim`: https://github.com/ptim
+.. _`@habnabit`: https://github.com/habnabit
diff --git a/HISTORY.rst b/HISTORY.rst
index 96f7636..b008bf1 100644
--- a/HISTORY.rst
+++ b/HISTORY.rst
@@ -3,6 +3,94 @@
History
-------
+1.4.0 (2016-03-20) Shortbread
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The goal of this release is changing to a strict Jinja2 environment, paving the
+way to more awesome in the future, as well as adding support for Jinja2
+extensions.
+
+New Features:
+
+* Added support for Jinja2 extension support, thanks to `@hackebrot`_ (#617).
+* Now raises an error if Cookiecutter tries to render a template that contains an undefined variable. Makes generation more robust and secure (#586). Work done by `@hackebrot`_ (#111, #586, #592)
+* Uses strict Jinja2 env in prompt, thanks to `@hackebrot`_ (#598, #613)
+* Switched from pyyaml/ruamel.yaml libraries that were problematic across platforms to the pure Python poyo_ library, thanks to `@hackebrot`_ (#557, #569, #621)
+* User config values for ``cookiecutters_dir`` and ``replay_dir`` now support
+ environment variable and user home expansion, thanks to `@nfarrar`_ for the
+ suggestion and `@hackebrot`_ for the PR (#640, #642)
+* Add `jinja2-time`_ as default extension for dates and times in templates via
+ ``{% now 'utc' %}``, thanks to `@hackebrot`_ (#653)
+
+Bug Fixes:
+
+* Provided way to define options that have no defaults, thanks to `@johtso`_ (#587, #588)
+* Make sure that ``replay.dump()`` and ``replay.load()`` use the correct user config, thanks to `@hackebrot`_ (#590, #594)
+* Added correct CA bundle for Git on Appveyor, thanks to `@maiksensi`_ (#599, #602)
+* Open ``HISTORY.rst`` with ``utf-8`` encoding when reading the changelog,
+ thanks to `@0-wiz-0`_ for submitting the issue and `@hackebrot`_ for the fix
+ (#638, #639)
+* Fix repository indicators for `private repository`_ urls, thanks to
+ `@habnabit`_ for the fix (#595) and `@hackebrot`_ for the tests (#655)
+
+.. _poyo: https://pypi.python.org/pypi/poyo
+.. _`jinja2-time`: https://pypi.python.org/pypi/jinja2-time
+.. _`private repository`: http://cookiecutter.readthedocs.org/en/latest/usage.html#works-with-private-repos
+
+Other Changes:
+
+* Set path before running tox, thanks to `@maiksensi`_ (#615, #620)
+* Removed xfail in test_cookiecutters, thanks to `@hackebrot`_ (#618)
+* Removed django-cms-plugin on account of 404 error, thanks to `@mativs`_ and `@pydanny`_ (#593)
+* Fixed docs/usage.rst, thanks to `@macrotim`_ (#604)
+* Update .gitignore to latest Python.gitignore and ignore PyCharm files, thanks to `@audreyr`_
+* Use open context manager to read context_file in generate() function, thanks to `@hackebrot`_ (#607, #608)
+* Added documentation for choice variables, thanks to `@maiksensi`_ (#611)
+* Set up Scrutinizer to check code quality, thanks to `@audreyr`_
+* Drop distutils support in setup.py, thanks to `@hackebrot`_ (#606, #609)
+* Change cookiecutter-pypackage-minimal link, thanks to `@kragniz`_ (#614)
+* Fix typo in one of the template's description, thanks to `@ryanfreckleton`_ (#643)
+* Fix broken link to `_copy_without_render`_ in *troubleshooting.rst*, thanks
+ to `@ptim`_ (#647)
+
+* Added more cookiecutter templates to the mix:
+
+ * `cookiecutter-pipproject`_ by `@wdm0006`_ (#624)
+ * `cookiecutter-flask-2`_ by `@wdm0006`_ (#624)
+ * `cookiecutter-kotlin-gradle`_ by `@thomaslee`_ (#622)
+ * `cookiecutter-tryton`_ by `@cedk`_ (#631)
+ * `django-starter`_ by `@tkjone`_ (#635)
+ * `django-docker-bootstrap`_ by `@legios89`_ (#636)
+ * `cookiecutter-mediawiki-extension`_ by `@JonasGroeger`_ (#645)
+ * `cookiecutter-django-gulp`_ by `@valerymelou`_ (#648)
+
+
+.. _`@macrotim`: https://github.com/macrotim
+.. _`@wdm0006`: https://github.com/wdm0006
+.. _`@thomaslee`: https://github.com/thomaslee
+.. _`@kragniz`: https://github.com/kragniz
+.. _`@ryanfreckleton`: https://github.com/ryanfreckleton
+.. _`@cedk`: https://github.com/cedk
+.. _`@johtso`: https://github.com/johtso
+.. _`@legios89`: https://github.com/legios89
+.. _`@0-wiz-0`: https://github.com/0-wiz-0
+.. _`@tkjone`: https://github.com/tkjone
+.. _`@nfarrar`: https://github.com/nfarrar
+.. _`@ptim`: https://github.com/ptim
+.. _`@JonasGroeger`: https://github.com/JonasGroeger
+.. _`@valerymelou`: https://github.com/valerymelou
+.. _`@habnabit`: https://github.com/habnabit
+
+.. _`cookiecutter-kotlin-gradle`: https://github.com/thomaslee/cookiecutter-kotlin-gradle
+.. _`cookiecutter-pipproject`: https://github.com/wdm0006/cookiecutter-pipproject
+.. _`cookiecutter-flask-2`: https://github.com/wdm0006/cookiecutter-flask
+.. _`django-starter`: https://github.com/tkjone/django-starter
+.. _`django-docker-bootstrap`: https://github.com/legios89/django-docker-bootstrap
+.. _`cookiecutter-mediawiki-extension`: https://github.com/JonasGroeger/cookiecutter-mediawiki-extension
+.. _`cookiecutter-django-gulp`: https://github.com/valerymelou/cookiecutter-django-gulp
+
+.. _`_copy_without_render`: http://cookiecutter.readthedocs.org/en/latest/advanced_usage.html#copy-without-render
+
1.3.0 (2015-11-10) Pumpkin Spice
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -96,7 +184,7 @@ Other Changes:
* Updated click requirement to < 6.0, thanks to `@pydanny`_ (#473).
* Added landscape.io flair, thanks to `@michaeljoseph`_ (#439).
* Descriptions of PEP8 specifications and milestone management, thanks to `@michaeljoseph`_ (#440).
-* Added alternate installation options in the documentation, thanks to `@pydanny`_ (#117, #315).
+ * Added alternate installation options in the documentation, thanks to `@pydanny`_ (#117, #315).
* The test of the `which()` function now tests against the `date` command, thanks to `@vincentbernat`_ (#446)
* Ensure file handles in setup.py are closed using with statement, thanks to `@svisser`_ (#280).
* Removed deprecated and fully extraneous `compat.is_exe()` function, thanks to `@hackebrot`_ (#485).
@@ -116,7 +204,7 @@ Other Changes:
* `cookiecutter-pytest-plugin`_ by `@pytest-dev`_ and `@hackebrot`_ (#481)
* `cookiecutter-csharp-objc-binding`_ by `@SandyChapman`_ (#460)
* `cookiecutter-flask-foundation`_ by `@JackStouffer`_ (#457)
- * `cookiecutter-tryton`_ by `@fulfilio`_ (#465)
+ * `cookiecutter-tryton-fulfilio`_ by `@fulfilio`_ (#465)
* `cookiecutter-tapioca`_ by `@vintasoftware`_ (#496)
* `cookiecutter-sublime-text-3-plugin`_ by `@kkujawinski`_ (#500)
* `cookiecutter-muffin`_ by `@drgarcia1986`_ (#494)
@@ -150,7 +238,7 @@ Other Changes:
.. _`@pytest-dev`: https://github.com/pytest-dev
.. _`cookiecutter-csharp-objc-binding`: https://github.com/SandyChapman/cookiecutter-csharp-objc-binding
.. _`cookiecutter-flask-foundation`: https://github.com/JackStouffer/cookiecutter-Flask-Foundation
-.. _`cookiecutter-tryton`: https://github.com/fulfilio/cookiecutter-tryton
+.. _`cookiecutter-tryton-fulfilio`: https://github.com/fulfilio/cookiecutter-tryton
.. _`cookiecutter-tapioca`: https://github.com/vintasoftware/cookiecutter-tapioca
.. _`cookiecutter-sublime-text-3-plugin`: https://github.com/kkujawinski/cookiecutter-sublime-text-3-plugin
.. _`cookiecutter-muffin`: https://github.com/drgarcia1986/cookiecutter-muffin
@@ -344,7 +432,7 @@ Other Changes:
.. _`cookiecutter-kivy`: https://github.com/hackebrot/cookiecutter-kivy
.. _`cookiecutter-ansible-role`: https://github.com/iknite/cookiecutter-ansible-role
.. _BoilerplatePP: https://github.com/Paspartout/BoilerplatePP
-.. _`cookiecutter-pypackage-minimal`: https://github.com/borntyping/cookiecutter-pypackage-minimal
+.. _`cookiecutter-pypackage-minimal`: https://github.com/kragniz/cookiecutter-pypackage-minimal
.. _`cookiecutter-pylibrary`: https://github.com/ionelmc/cookiecutter-pylibrary
.. _`cookiecutter-pylibrary-minimal`: https://github.com/ionelmc/cookiecutter-pylibrary-minimal
@@ -359,6 +447,7 @@ Other Changes:
.. _`@pydanny`: https://github.com/pydanny
.. _`@saxix`: https://github.com/saxix
.. _`@uranusjr`: https://github.com/uranusjr
+.. _`@mativs`: https://github.com/mativs
diff --git a/README.rst b/README.rst
index c9ce169..82ea8ab 100644
--- a/README.rst
+++ b/README.rst
@@ -28,6 +28,10 @@ Cookiecutter
:target: https://landscape.io/github/audreyr/cookiecutter/master
:alt: Code Health
+.. image:: https://img.shields.io/scrutinizer/g/audreyr/cookiecutter.svg
+ :target: https://scrutinizer-ci.com/g/audreyr/cookiecutter/?branch=master
+ :alt: Scrutinizer Code Quality
+
A command-line utility that creates projects from **cookiecutters** (project
templates), e.g. creating a Python package project from a Python package project template.
@@ -152,7 +156,9 @@ Python
~~~~~~
* `cookiecutter-pypackage`_: `@audreyr`_'s ultimate Python package project
template.
+* `cookiecutter-pipproject`_: Minimal package for pip-installable projects
* `cookiecutter-flask`_ : A Flask template with Bootstrap 3, starter templates, and working user registration.
+* `cookiecutter-flask-2`_: A heavier weight fork of cookiecutter-flask, with more boilerplate including forgotten password and Heroku integration
* `cookiecutter-flask-foundation`_ : Flask Template with caching, forms, sqlalchemy and unit-testing.
* `cookiecutter-bottle`_ : A cookiecutter template for creating reusable Bottle projects quickly.
* `cookiecutter-openstack`_: A template for an OpenStack project.
@@ -160,13 +166,14 @@ Python
* `cookiecutter-quokka-module`_: A template to create a blueprint module for Quokka Flask CMS.
* `cookiecutter-kivy`_: A template for NUI applications built upon the kivy python-framework.
* `cookiedozer`_: A template for Python Kivy apps ready to be deployed to android devices with Buildozer.
-* `cookiecutter-pypackage-minimal`_: A mimimal Python package template.
+* `cookiecutter-pypackage-minimal`_: A minimal Python package template.
* `cookiecutter-ansible-role`_: A template to create ansible roles. Forget about file creation and focus on actions.
* `cookiecutter-pylibrary`_: An intricate template designed to quickly get started with good testing and packaging (working configuration for Tox, Pytest, Travis-CI, Coveralls, AppVeyor, Sphinx docs, isort, bumpversion, packaging checks etc).
* `cookiecutter-pyvanguard`_: A template for cutting edge Python development. `Invoke`_, pytest, bumpversion, and Python 2/3 compatability.
* `Python-iOS-template`_: A template to create a Python project that will run on iOS devices.
* `Python-Android-template`_: A template to create a Python project that will run on Android devices.
-* `cookiecutter-tryton`_: A template for creating tryton modules.
+* `cookiecutter-tryton`_: A template to create base and external Tryton modules.
+* `cookiecutter-tryton-fulfilio`_: A template for creating tryton modules.
* `cookiecutter-pytest-plugin`_: Minimal Cookiecutter template for authoring `pytest`_ plugins that help you to write better programs.
* `cookiecutter-tapioca`_: A Template for building `tapioca-wrapper`_ based web API wrappers (clients).
* `cookiecutter-sublime-text-3-plugin`_: Sublime Text 3 plugin template with custom settings, commands, key bindings and main menu.
@@ -179,15 +186,17 @@ Python-Django
* `cookiecutter-django`_: A bleeding edge Django project template with Bootstrap 4, customizable users app, starter templates, working user registration, celery setup, and much more.
* `cookiecutter-django-rest`_: For creating REST apis for mobile and web applications.
* `cookiecutter-simple-django`_: A cookiecutter template for creating reusable Django projects quickly.
+* `django-docker-bootstrap`_: Django development/production environment with docker, integrated with Postgres, NodeJS(React), Nginx, uWSGI.
* `cookiecutter-djangopackage`_: A template designed to create reusable third-party PyPI friendly Django apps. Documentation is written in tutorial format.
* `cookiecutter-django-cms`_: A template for Django CMS with simple Bootstrap 3 template. It has a quick start and deploy documentation.
-* `cookiecutter-djangocms-plugin`_: A template to get started with custom plugins for django-cms
* `cookiecutter-django-crud`_: A template to create a Django app with boilerplate CRUD around a model including a factory and tests.
* `cookiecutter-django-lborgav`_: Another cookiecutter template for Django project with Booststrap 3 and FontAwesome 4
* `cookiecutter-django-paas`_: Django template ready to use in SAAS platforms like Heroku, OpenShift, etc..
* `cookiecutter-django-rest-framework`_: A template for creating reusable Django REST Framework packages.
* `cookiecutter-wagtail`_ : A cookiecutter template for `Wagtail`_ CMS based sites.
* `wagtail-cookiecutter-foundation`_: A complete template for Wagtail CMS projects featuring Zurb Foundation 5, ansible provisioning and deployment , front-end dependency management with bower, modular apps to get your site up and running including photo_gallery, RSS feed etc.
+* `django-starter`_: A Django template complete with vagrant and provisioning scripts - inspired by 12 factor apps and cookiecutter-django.
+* `cookiecutter-django-gulp`_: A Cookiecutter template for integrating frontend development tools in Django projects.
C
~~
@@ -223,6 +232,11 @@ JS
* `cookiecutter-component`_: A template for a Component JS package.
* `cookiecutter-tampermonkey`_: A template for a TamperMonkey browser script.
+Kotlin
+~~~~~~
+
+* `cookiecutter-kotlin-gradle`_: A bare-bones template for Gradle-based Kotlin projects.
+
LaTeX/XeTeX
~~~~~~~~~~~
@@ -232,6 +246,10 @@ LaTeX/XeTeX
* `cookiecutter-beamer`_: A template for a LaTeX Beamer presentation.
+PHP
+~~~
+
+* `cookiecutter-mediawiki-extension`_: A template for MediaWiki extensions.
Berkshelf-Vagrant
~~~~~~~~~~~~~~~~~
@@ -247,23 +265,25 @@ HTML
.. _`cookiecutter-django-rest`: https://github.com/agconti/cookiecutter-django-rest
.. _`cookiecutter-es6-boilerplate`: https://github.com/agconti/cookiecutter-es6-boilerplate
+.. _`cookiecutter-kotlin-gradle`: https://github.com/thomaslee/cookiecutter-kotlin-gradle
.. _`cookiecutter-pypackage`: https://github.com/audreyr/cookiecutter-pypackage
.. _`cookiecutter-jquery`: https://github.com/audreyr/cookiecutter-jquery
.. _`cookiecutter-flask`: https://github.com/sloria/cookiecutter-flask
.. _`cookiecutter-flask-foundation`: https://github.com/JackStouffer/cookiecutter-Flask-Foundation
.. _`cookiecutter-bottle`: https://github.com/avelino/cookiecutter-bottle
+.. _`cookiecutter-pipproject`: https://github.com/wdm0006/cookiecutter-pipproject
+.. _`cookiecutter-flask-2`: https://github.com/wdm0006/cookiecutter-flask
.. _`cookiecutter-simple-django`: https://github.com/marcofucci/cookiecutter-simple-django
.. _`cookiecutter-django`: https://github.com/pydanny/cookiecutter-django
.. _`cookiecutter-djangopackage`: https://github.com/pydanny/cookiecutter-djangopackage
.. _`cookiecutter-django-cms`: https://github.com/palazzem/cookiecutter-django-cms
-.. _`cookiecutter-djangocms-plugin`: https://github.com/mishbahr/cookiecutter-djangocms-plugin
.. _`cookiecutter-django-crud`: https://github.com/wildfish/cookiecutter-django-crud
.. _`cookiecutter-quokka-module`: https://github.com/pythonhub/cookiecutter-quokka-module
.. _`cookiecutter-django-lborgav`: https://github.com/lborgav/cookiecutter-django
.. _`cookiecutter-django-paas`: https://github.com/pbacterio/cookiecutter-django-paas
.. _`cookiecutter-kivy`: https://github.com/hackebrot/cookiecutter-kivy
.. _`cookiedozer`: https://github.com/hackebrot/cookiedozer
-.. _`cookiecutter-pypackage-minimal`: https://github.com/borntyping/cookiecutter-pypackage-minimal
+.. _`cookiecutter-pypackage-minimal`: https://github.com/kragniz/cookiecutter-pypackage-minimal
.. _`cookiecutter-ansible-role`: https://github.com/iknite/cookiecutter-ansible-role
.. _`bootstrap.c`: https://github.com/vincentbernat/bootstrap.c
.. _`BoilerplatePP`: https://github.com/Paspartout/BoilerplatePP
@@ -286,8 +306,10 @@ HTML
.. _`Python-Android-template`: https://github.com/pybee/Python-Android-template
.. _`Invoke`: http://invoke.readthedocs.org/en/latest/
.. _`cookiecutter-django-rest-framework`: https://github.com/jpadilla/cookiecutter-django-rest-framework
-.. _`cookiecutter-tryton`: https://github.com/fulfilio/cookiecutter-tryton
+.. _`cookiecutter-tryton`: https://bitbucket.org/tryton/cookiecutter
+.. _`cookiecutter-tryton-fulfilio`: https://github.com/fulfilio/cookiecutter-tryton
.. _`cookiecutter-beamer`: https://github.com/luismartingil/cookiecutter-beamer
+.. _`cookiecutter-mediawiki-extension`: https://github.com/JonasGroeger/cookiecutter-mediawiki-extension
.. _`cookiecutter-pytest-plugin`: https://github.com/pytest-dev/cookiecutter-pytest-plugin
.. _`pytest`: http://pytest.org/latest/
.. _`cookiecutter-tapioca`: https://github.com/vintasoftware/cookiecutter-tapioca
@@ -299,6 +321,9 @@ HTML
.. _`cookiecutter-octoprint-plugin`: https://github.com/OctoPrint/cookiecutter-octoprint-plugin
.. _`OctoPrint`: https://github.com/foosel/OctoPrint
.. _`wagtail-cookiecutter-foundation`: https://github.com/chrisdev/wagtail-cookiecutter-foundation
+.. _`django-starter`: https://github.com/tkjone/django-starter
+.. _`django-docker-bootstrap`: https://github.com/legios89/django-docker-bootstrap
+.. _`cookiecutter-django-gulp`: https://github.com/valerymelou/cookiecutter-django-gulp
Scala
~~~~~
diff --git a/appveyor.yml b/appveyor.yml
index eaad642..aadf534 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -29,6 +29,8 @@ environment:
init:
+ - set PATH=%PYTHON%;%PYTHON%\Scripts;%PATH%
+ - "git config --system http.sslcainfo \"C:\\Program Files\\Git\\mingw64\\ssl\\certs\\ca-bundle.crt\""
- "%PYTHON%/python -V"
- "%PYTHON%/python -c \"import struct;print(8 * struct.calcsize(\'P\'))\""
diff --git a/cookiecutter/__init__.py b/cookiecutter/__init__.py
index 53a354a..b5a2d66 100755
--- a/cookiecutter/__init__.py
+++ b/cookiecutter/__init__.py
@@ -8,4 +8,4 @@ cookiecutter
Main package for Cookiecutter.
"""
-__version__ = '1.3.0'
+__version__ = '1.4.0'
diff --git a/cookiecutter/cli.py b/cookiecutter/cli.py
index 8825a8f..53a72fc 100755
--- a/cookiecutter/cli.py
+++ b/cookiecutter/cli.py
@@ -11,6 +11,7 @@ Main `cookiecutter` CLI.
import os
import sys
import logging
+import json
import click
@@ -18,7 +19,12 @@ from cookiecutter import __version__
from cookiecutter.config import USER_CONFIG_PATH
from cookiecutter.main import cookiecutter
from cookiecutter.exceptions import (
- OutputDirExistsException, InvalidModeException, FailedHookException
+ OutputDirExistsException,
+ InvalidModeException,
+ FailedHookException,
+ UndefinedVariableInTemplate,
+ UnknownExtension,
+ RepositoryNotFound
)
logger = logging.getLogger(__name__)
@@ -100,9 +106,23 @@ def main(template, no_input, checkout, verbose, replay, overwrite_if_exists,
config_file=user_config
)
except (OutputDirExistsException,
- InvalidModeException, FailedHookException) as e:
+ InvalidModeException,
+ FailedHookException,
+ UnknownExtension,
+ RepositoryNotFound) as e:
click.echo(e)
sys.exit(1)
+ except UndefinedVariableInTemplate as undefined_err:
+ click.echo('{}'.format(undefined_err.message))
+ click.echo('Error message: {}'.format(undefined_err.error.message))
+
+ context_str = json.dumps(
+ undefined_err.context,
+ indent=4,
+ sort_keys=True
+ )
+ click.echo('Context: {}'.format(context_str))
+ sys.exit(1)
if __name__ == "__main__":
diff --git a/cookiecutter/config.py b/cookiecutter/config.py
index edfcec4..fb69b47 100755
--- a/cookiecutter/config.py
+++ b/cookiecutter/config.py
@@ -14,10 +14,7 @@ import logging
import os
import io
-try:
- import ruamel.yaml as yaml
-except ImportError:
- import yaml
+import poyo
from .exceptions import ConfigDoesNotExistException
from .exceptions import InvalidConfiguration
@@ -34,6 +31,13 @@ DEFAULT_CONFIG = {
}
+def _expand_path(path):
+ """Expand both environment variables and user home in the given path."""
+ path = os.path.expandvars(path)
+ path = os.path.expanduser(path)
+ return path
+
+
def get_config(config_path):
"""
Retrieve the config from the specified path, returning it as a config dict.
@@ -45,17 +49,22 @@ def get_config(config_path):
logger.debug('config_path is {0}'.format(config_path))
with io.open(config_path, encoding='utf-8') as file_handle:
try:
- yaml_dict = yaml.safe_load(file_handle)
- except yaml.scanner.ScannerError as e:
+ yaml_dict = poyo.parse_string(file_handle.read())
+ except poyo.exceptions.PoyoException as e:
raise InvalidConfiguration(
- '{0} is not a valid YAML file: line {1}: {2}'.format(
- config_path,
- e.problem_mark.line,
- e.problem))
+ 'Unable to parse YAML file {}. Error: {}'
+ ''.format(config_path, e)
+ )
config_dict = copy.copy(DEFAULT_CONFIG)
config_dict.update(yaml_dict)
+ raw_replay_dir = config_dict['replay_dir']
+ config_dict['replay_dir'] = _expand_path(raw_replay_dir)
+
+ raw_cookies_dir = config_dict['cookiecutters_dir']
+ config_dict['cookiecutters_dir'] = _expand_path(raw_cookies_dir)
+
return config_dict
diff --git a/cookiecutter/environment.py b/cookiecutter/environment.py
new file mode 100644
index 0000000..c07dea6
--- /dev/null
+++ b/cookiecutter/environment.py
@@ -0,0 +1,52 @@
+# -*- coding: utf-8 -*-
+
+from jinja2 import Environment, StrictUndefined
+
+from .exceptions import UnknownExtension
+
+
+class ExtensionLoaderMixin(object):
+ """Mixin that provides a sane way of loading extensions specified in a
+ given context.
+
+ The context is being extracted from the keyword arguments before calling
+ the next parent class in line of the child.
+ """
+ def __init__(self, **kwargs):
+ context = kwargs.pop('context', {})
+
+ default_extensions = [
+ 'jinja2_time.TimeExtension',
+ ]
+ extensions = default_extensions + self._read_extensions(context)
+
+ try:
+ super(ExtensionLoaderMixin, self).__init__(
+ extensions=extensions,
+ **kwargs
+ )
+ except ImportError as err:
+ raise UnknownExtension('Unable to load extension: {}'.format(err))
+
+ def _read_extensions(self, context):
+ """Return a list of extensions as str to be passed on to the jinja2
+ env. If context does not contain the relevant info, return an empty
+ list instead.
+ """
+ try:
+ extensions = context['cookiecutter']['_extensions']
+ except KeyError:
+ return []
+ else:
+ return [str(ext) for ext in extensions]
+
+
+class StrictEnvironment(ExtensionLoaderMixin, Environment):
+ """Jinja2 environment that raises an error when it hits a variable
+ which is not defined in the context used to render a template.
+ """
+ def __init__(self, **kwargs):
+ super(StrictEnvironment, self).__init__(
+ undefined=StrictUndefined,
+ **kwargs
+ )
diff --git a/cookiecutter/exceptions.py b/cookiecutter/exceptions.py
index 415f99e..b13e768 100755
--- a/cookiecutter/exceptions.py
+++ b/cookiecutter/exceptions.py
@@ -87,3 +87,30 @@ class FailedHookException(CookiecutterException):
"""
Raised when a hook script fails
"""
+
+
+class UndefinedVariableInTemplate(CookiecutterException):
+ """Raised when a template uses a variable which is not defined in the
+ context.
+ """
+ def __init__(self, message, error, context):
+ self.message = message
+ self.error = error
+ self.context = context
+
+ def __str__(self):
+ return (
+ "{self.message}. "
+ "Error message: {self.error.message}. "
+ "Context: {self.context}"
+ ).format(**locals())
+
+
+class UnknownExtension(CookiecutterException):
+ """Raised when an environment is unable to import a required extension."""
+
+
+class RepositoryNotFound(CookiecutterException):
+ """
+ Raised when the specified cookiecutter repository doesn't exist.
+ """
diff --git a/cookiecutter/generate.py b/cookiecutter/generate.py
index 7a4d461..5ee2934 100755
--- a/cookiecutter/generate.py
+++ b/cookiecutter/generate.py
@@ -16,16 +16,17 @@ import logging
import os
import shutil
-from jinja2 import FileSystemLoader, Template
-from jinja2.environment import Environment
-from jinja2.exceptions import TemplateSyntaxError
+from jinja2 import FileSystemLoader
+from cookiecutter.environment import StrictEnvironment
+from jinja2.exceptions import TemplateSyntaxError, UndefinedError
from binaryornot.check import is_binary
from .exceptions import (
NonTemplatedInputDirException,
ContextDecodingException,
FailedHookException,
- OutputDirExistsException
+ OutputDirExistsException,
+ UndefinedVariableInTemplate
)
from .find import find_template
from .utils import make_sure_path_exists, work_in, rmtree
@@ -87,9 +88,9 @@ def generate_context(context_file='cookiecutter.json', default_context=None,
context = {}
- file_handle = open(context_file)
try:
- obj = json.load(file_handle, object_pairs_hook=OrderedDict)
+ with open(context_file) as file_handle:
+ obj = json.load(file_handle, object_pairs_hook=OrderedDict)
except ValueError as e:
# JSON decoding error. Let's throw a new exception that is more
# friendly for the developer or user.
@@ -141,7 +142,7 @@ def generate_file(project_dir, infile, context, env):
logging.debug('Generating file {0}'.format(infile))
# Render the path to the output file (not including the root project dir)
- outfile_tmpl = Template(infile)
+ outfile_tmpl = env.from_string(infile)
outfile = os.path.join(project_dir, outfile_tmpl.render(**context))
file_name_is_empty = os.path.isdir(outfile)
@@ -181,14 +182,14 @@ def generate_file(project_dir, infile, context, env):
shutil.copymode(infile, outfile)
-def render_and_create_dir(dirname, context, output_dir,
+def render_and_create_dir(dirname, context, output_dir, environment,
overwrite_if_exists=False):
"""
Renders the name of a directory, creates the directory, and
returns its path.
"""
- name_tmpl = Template(dirname)
+ name_tmpl = environment.from_string(dirname)
rendered_dirname = name_tmpl.render(**context)
logging.debug('Rendered dir {0} must exist in output_dir {1}'.format(
rendered_dirname,
@@ -255,10 +256,21 @@ def generate_files(repo_dir, context=None, output_dir='.',
unrendered_dir = os.path.split(template_dir)[1]
ensure_dir_is_templated(unrendered_dir)
- project_dir = render_and_create_dir(unrendered_dir,
- context,
- output_dir,
- overwrite_if_exists)
+ env = StrictEnvironment(
+ context=context,
+ keep_trailing_newline=True,
+ )
+ try:
+ project_dir = render_and_create_dir(
+ unrendered_dir,
+ context,
+ output_dir,
+ env,
+ overwrite_if_exists
+ )
+ except UndefinedError as err:
+ msg = "Unable to create project directory '{}'".format(unrendered_dir)
+ raise UndefinedVariableInTemplate(msg, err, context)
# We want the Jinja path and the OS paths to match. Consequently, we'll:
# + CD to the template folder
@@ -273,7 +285,6 @@ def generate_files(repo_dir, context=None, output_dir='.',
_run_hook_from_repo_dir(repo_dir, 'pre_gen_project', project_dir, context)
with work_in(template_dir):
- env = Environment(keep_trailing_newline=True)
env.loader = FileSystemLoader('.')
for root, dirs, files in os.walk('.'):
@@ -307,13 +318,24 @@ def generate_files(repo_dir, context=None, output_dir='.',
dirs[:] = render_dirs
for d in dirs:
unrendered_dir = os.path.join(project_dir, root, d)
- render_and_create_dir(unrendered_dir, context, output_dir,
- overwrite_if_exists)
+ try:
+ render_and_create_dir(
+ unrendered_dir,
+ context,
+ output_dir,
+ env,
+ overwrite_if_exists
+ )
+ except UndefinedError as err:
+ rmtree(project_dir)
+ _dir = os.path.relpath(unrendered_dir, output_dir)
+ msg = "Unable to create directory '{}'".format(_dir)
+ raise UndefinedVariableInTemplate(msg, err, context)
for f in files:
infile = os.path.normpath(os.path.join(root, f))
if copy_without_render(infile, context):
- outfile_tmpl = Template(infile)
+ outfile_tmpl = env.from_string(infile)
outfile_rendered = outfile_tmpl.render(**context)
outfile = os.path.join(project_dir, outfile_rendered)
logging.debug(
@@ -324,7 +346,12 @@ def generate_files(repo_dir, context=None, output_dir='.',
shutil.copymode(infile, outfile)
continue
logging.debug('f is {0}'.format(f))
- generate_file(project_dir, infile, context, env)
+ try:
+ generate_file(project_dir, infile, context, env)
+ except UndefinedError as err:
+ rmtree(project_dir)
+ msg = "Unable to create file '{}'".format(infile)
+ raise UndefinedVariableInTemplate(msg, err, context)
_run_hook_from_repo_dir(repo_dir, 'post_gen_project', project_dir, context)
diff --git a/cookiecutter/main.py b/cookiecutter/main.py
index e6d858f..d8ff7b6 100755
--- a/cookiecutter/main.py
+++ b/cookiecutter/main.py
@@ -17,7 +17,7 @@ import os
import re
from .config import get_user_config, USER_CONFIG_PATH
-from .exceptions import InvalidModeException
+from .exceptions import InvalidModeException, RepositoryNotFound
from .prompt import prompt_for_config
from .generate import generate_context, generate_files
from .vcs import clone
@@ -30,19 +30,18 @@ builtin_abbreviations = {
'bb': 'https://bitbucket.org/{0}',
}
-REPO_REGEX = """
-(
-((git|ssh|https|http):(//)?) # something like git:// ssh:// etc.
- | # or
- (\w+@[\w\.]+) # something like user at ...
+REPO_REGEX = re.compile(r"""
+(?x)
+((((git|hg)\+)?(git|ssh|https?):(//)?) # something like git:// ssh:// etc.
+ | # or
+ (\w+@[\w\.]+) # something like user at ...
)
-.*
-"""
+""")
def is_repo_url(value):
"""Return True if value is a repository URL."""
- return bool(re.match(REPO_REGEX, value, re.VERBOSE))
+ return bool(REPO_REGEX.match(value))
def expand_abbreviations(template, config_dict):
@@ -112,10 +111,15 @@ def cookiecutter(
# cookiecutters_dir
repo_dir = template
+ if not os.path.isdir(repo_dir):
+ raise RepositoryNotFound(
+ 'The repository {0} could not be located.'.format(template)
+ )
+
template_name = os.path.basename(template)
if replay:
- context = load(template_name)
+ context = load(config_dict['replay_dir'], template_name)
else:
context_file = os.path.join(repo_dir, 'cookiecutter.json')
logging.debug('context_file is {0}'.format(context_file))
@@ -130,7 +134,7 @@ def cookiecutter(
# except when 'no-input' flag is set
context['cookiecutter'] = prompt_for_config(context, no_input)
- dump(template_name, context)
+ dump(config_dict['replay_dir'], template_name, context)
# Create project from local context and project template.
return generate_files(
diff --git a/cookiecutter/prompt.py b/cookiecutter/prompt.py
index d06409c..0d7e4df 100755
--- a/cookiecutter/prompt.py
+++ b/cookiecutter/prompt.py
@@ -14,7 +14,11 @@ import click
from past.builtins import basestring
from future.utils import iteritems
-from jinja2.environment import Environment
+
+from jinja2.exceptions import UndefinedError
+
+from .exceptions import UndefinedVariableInTemplate
+from .environment import StrictEnvironment
def read_user_variable(var_name, default_value):
@@ -81,9 +85,12 @@ def read_user_choice(var_name, options):
def render_variable(env, raw, cookiecutter_dict):
+ if raw is None:
+ return None
if not isinstance(raw, basestring):
raw = str(raw)
template = env.from_string(raw)
+
rendered_template = template.render(cookiecutter=cookiecutter_dict)
return rendered_template
@@ -109,24 +116,28 @@ def prompt_for_config(context, no_input=False):
:param no_input: Prompt the user at command line for manual configuration?
"""
cookiecutter_dict = {}
- env = Environment()
+ env = StrictEnvironment(context=context)
for key, raw in iteritems(context[u'cookiecutter']):
if key.startswith(u'_'):
cookiecutter_dict[key] = raw
continue
- if isinstance(raw, list):
- # We are dealing with a choice variable
- val = prompt_choice_for_config(
- cookiecutter_dict, env, key, raw, no_input
- )
- else:
- # We are dealing with a regular variable
- val = render_variable(env, raw, cookiecutter_dict)
-
- if not no_input:
- val = read_user_variable(key, val)
+ try:
+ if isinstance(raw, list):
+ # We are dealing with a choice variable
+ val = prompt_choice_for_config(
+ cookiecutter_dict, env, key, raw, no_input
+ )
+ else:
+ # We are dealing with a regular variable
+ val = render_variable(env, raw, cookiecutter_dict)
+
+ if not no_input:
+ val = read_user_variable(key, val)
+ except UndefinedError as err:
+ msg = "Unable to render variable '{}'".format(key)
+ raise UndefinedVariableInTemplate(msg, err, context)
cookiecutter_dict[key] = val
return cookiecutter_dict
diff --git a/cookiecutter/replay.py b/cookiecutter/replay.py
index 627170d..bee7ec3 100644
--- a/cookiecutter/replay.py
+++ b/cookiecutter/replay.py
@@ -11,7 +11,6 @@ import json
import os
from past.builtins import basestring
-from .config import get_user_config
from .utils import make_sure_path_exists
@@ -20,7 +19,10 @@ def get_file_name(replay_dir, template_name):
return os.path.join(replay_dir, file_name)
-def dump(template_name, context):
+def dump(replay_dir, template_name, context):
+ if not make_sure_path_exists(replay_dir):
+ raise IOError('Unable to create replay dir at {}'.format(replay_dir))
+
if not isinstance(template_name, basestring):
raise TypeError('Template name is required to be of type str')
@@ -30,22 +32,16 @@ def dump(template_name, context):
if 'cookiecutter' not in context:
raise ValueError('Context is required to contain a cookiecutter key')
- replay_dir = get_user_config()['replay_dir']
-
- if not make_sure_path_exists(replay_dir):
- raise IOError('Unable to create replay dir at {}'.format(replay_dir))
-
replay_file = get_file_name(replay_dir, template_name)
with open(replay_file, 'w') as outfile:
json.dump(context, outfile)
... 1093 lines suppressed ...
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/python-modules/packages/cookiecutter.git
More information about the Python-modules-commits
mailing list