├── .editorconfig ├── .gitattributes ├── .gitignore ├── .jshintrc ├── .travis.yml ├── LICENSE ├── README.md ├── app ├── index.js └── templates │ ├── _coveragerc │ ├── _gitignore │ ├── _init.py │ ├── _makefile │ ├── _manifest.in │ ├── _redis.conf │ ├── _redis_tests.conf │ ├── _root_init.py │ ├── _setup.py │ ├── _test_base.py │ ├── _test_version.py │ ├── _tox.ini │ ├── _travis.yml │ └── _version.py ├── package.json └── test ├── test-creation.js └── test-load.js /.editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | insert_final_newline = true 11 | 12 | [*.md] 13 | trim_trailing_whitespace = false 14 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | temp/ 3 | -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "node": true, 3 | "esnext": true, 4 | "bitwise": true, 5 | "camelcase": true, 6 | "curly": true, 7 | "eqeqeq": true, 8 | "immed": true, 9 | "indent": 2, 10 | "latedef": true, 11 | "newcap": true, 12 | "noarg": true, 13 | "quotmark": "single", 14 | "regexp": true, 15 | "undef": true, 16 | "unused": true, 17 | "strict": true, 18 | "trailing": true, 19 | "smarttabs": true, 20 | "white": true 21 | } 22 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - '0.10' 4 | before_install: 5 | - currentfolder=${PWD##*/} 6 | - if [ "$currentfolder" != 'generator-python-package' ]; then cd .. && eval "mv $currentfolder generator-python-package" && cd generator-python-package; fi 7 | 8 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Bernardo Heynemann 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # generator-python-package [![Build Status](https://secure.travis-ci.org/heynemann/generator-python-package.png?branch=master)](https://travis-ci.org/heynemann/generator-python-package) 2 | 3 | > [Yeoman](http://yeoman.io) generator for python packages. 4 | 5 | 6 | ## Getting Started 7 | 8 | Make sure you have the latest version of [Yeoman](http://yeoman.io): 9 | 10 | ```bash 11 | $ npm install -g yo 12 | ``` 13 | 14 | To install generator-python-package from npm, run: 15 | 16 | ```bash 17 | $ npm install -g generator-python-package 18 | ``` 19 | 20 | Finally, initiate the generator: 21 | 22 | ```bash 23 | $ yo python-package 24 | ``` 25 | 26 | ## Current features 27 | 28 | * Allows selection of supported python versions (2.6, 2.7, 3.2, 3.3, 3.4, pypy); 29 | * Uses [nosetests](https://nose.readthedocs.org/en/latest/) to run your tests; 30 | * Creates base class for tests; 31 | * Uses and configures [coverage](http://nedbatchelder.com/code/coverage/) for test coverage; 32 | * Uses [preggy](http://heynemann.github.io/preggy/) for expectations; 33 | * Uses [tox](http://tox.readthedocs.org/en/latest/) to run tests against all the supported python versions; 34 | * Allows selections of services your app requires (currently supported: mongodb and redis); 35 | * Sets up a setup.py file with all the collected information and test dependencies; 36 | * Creates [travis.yml](http://travis-ci.org) file that runs tests; 37 | * Creates Makefile to support all the above features. 38 | 39 | ## Makefile 40 | 41 | To list available tasks, just run: 42 | 43 | ```bash 44 | $ make list 45 | ``` 46 | 47 | To setup a new virtualenv: 48 | 49 | ```bash 50 | $ make setup 51 | ``` 52 | 53 | To run your tests: 54 | 55 | ```bash 56 | $ make test 57 | ``` 58 | 59 | ## DISCLAIMER 60 | 61 | The above tools are my personal preferences and the ones I like to work with. 62 | 63 | If you feel any of those can be replaced by a different tool, feel free to make a pull request adding a wizard step to select the tool. Just make sure to keep compatibility with the one already in place. 64 | -------------------------------------------------------------------------------- /app/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | var util = require('util'); 3 | var path = require('path'); 4 | var yeoman = require('yeoman-generator'); 5 | var yosay = require('yosay'); 6 | var chalk = require('chalk'); 7 | var sys = require('sys') 8 | var exec = require('child_process').exec; 9 | 10 | var userEmail = null; 11 | var userName = null; 12 | 13 | function getUserNameAndEmail(callback) { 14 | // executes `pwd` 15 | var cmd = "git config --global user.email" 16 | var child = exec(cmd, function (error, stdout, stderr) { 17 | if (error == null) { 18 | userEmail = stdout.replace('\n', ''); 19 | } 20 | 21 | cmd = "git config --global user.name" 22 | child = exec(cmd, function (error, stdout, stderr) { 23 | if (error == null) { 24 | userName = stdout.replace('\n', ''); 25 | } 26 | 27 | callback(); 28 | }); 29 | }); 30 | } 31 | 32 | function guessPackageURL(answers) { 33 | var emailParts = answers.authorEmail.split('@'); 34 | if (emailParts.length > 1) { 35 | return 'https://github.com/' + emailParts[0] + '/' + answers.packageName 36 | } 37 | return 'https://github.com/someuser/somepackage'; 38 | } 39 | 40 | function escapeQuotes(answer) { 41 | return answer.replace(/[\\"']/g, '\\$&').replace(/\u0000/g, '\\0'); 42 | } 43 | 44 | var currentPath = path.basename(process.cwd()); 45 | 46 | var PythonPackageGenerator = yeoman.generators.Base.extend({ 47 | init: function () { 48 | this.pkg = require('../package.json'); 49 | }, 50 | 51 | askFor: function (mute, callback) { 52 | var done = this.async(); 53 | 54 | if (!mute) { 55 | this.log(yosay('Welcome to the python package generator\nRun this generator in the folder where your app will be created')); 56 | } 57 | 58 | var pythonVersions = [ 59 | { name: "Python 2.6", value: "2.6@py26@Python :: 2.6", checked: false }, 60 | { name: "Python 2.7", value: "2.7@py27@Python :: 2.7", checked: true }, 61 | { name: "Python 3.2", value: "3.2@py32@Python :: 3.2", checked: false }, 62 | { name: "Python 3.3", value: "3.3@py33@Python :: 3.3", checked: false }, 63 | { name: "Python 3.4", value: "3.4@py34@Python :: 3.4", checked: true }, 64 | { name: "PyPy", value: "pypy@pypy@Python :: Implementation :: PyPy", checked: true }, 65 | ]; 66 | 67 | var services = [ 68 | { name: "Redis", value: "redis", checked: false }, 69 | { name: "MongoDB", value: "mongodb", checked: false } 70 | ]; 71 | 72 | getUserNameAndEmail(function() { 73 | var prompts = [{ 74 | type: 'input', 75 | name: 'packageName', 76 | message: 'Python package name (the name that will be used when sending to pypi):', 77 | default: currentPath 78 | }, { 79 | type: 'input', 80 | name: 'authorName', 81 | message: 'Package author name', 82 | default: userName, 83 | filter: escapeQuotes 84 | }, { 85 | type: 'input', 86 | name: 'authorEmail', 87 | message: 'Package author email', 88 | default: userEmail 89 | }, { 90 | type: 'checkbox', 91 | name: 'pythonVersions', 92 | message: 'Package supported python versions', 93 | choices: pythonVersions 94 | }, { 95 | type: 'input', 96 | name: 'version', 97 | message: 'Package initial version', 98 | default: '0.1.0' 99 | }, { 100 | type: 'input', 101 | name: 'description', 102 | message: 'Package description (please be sure to update long_description in setup.py later):', 103 | default: 'an incredible python package', 104 | filter: escapeQuotes 105 | }, { 106 | type: 'input', 107 | name: 'keywords', 108 | message: 'Package keywords (space separated keywords):', 109 | filter: escapeQuotes 110 | }, { 111 | type: 'input', 112 | name: 'url', 113 | message: 'Package url (this url gets included in pypi):', 114 | default: guessPackageURL 115 | }, { 116 | type: 'input', 117 | name: 'license', 118 | message: 'Package license:', 119 | default: 'MIT', 120 | filter: escapeQuotes 121 | }, { 122 | type: 'confirm', 123 | name: 'packageData', 124 | message: 'Include package data', 125 | default: false 126 | }, { 127 | type: 'confirm', 128 | name: 'packageTests', 129 | message: 'Include tests to package', 130 | default: false 131 | }, { 132 | type: 'checkbox', 133 | name: 'services', 134 | message: 'Services you need to run', 135 | choices: services 136 | }]; 137 | 138 | this.prompt(prompts, function (props) { 139 | var versions = []; 140 | var travis = []; 141 | var troves = []; 142 | 143 | for (var i=0; i < props.pythonVersions.length; i++) { 144 | var parts = props.pythonVersions[i].split('@'); 145 | travis.push(parts[0]); 146 | versions.push(parts[1]); 147 | troves.push("Programming Language :: " + parts[2]); 148 | } 149 | 150 | var pkgServices = { 151 | mongodb: false, 152 | redis: false 153 | }; 154 | for (var i=0; i < props.services.length; i++) { 155 | switch (props.services[i]) { 156 | case "mongodb": { 157 | pkgServices.mongodb = true; 158 | break; 159 | } 160 | case "redis": { 161 | pkgServices.redis = true; 162 | break; 163 | } 164 | } 165 | } 166 | 167 | var pythonPackageName = props.packageName.replace(/(\s|-)+/g, '_'); 168 | 169 | this.package = { 170 | name: props.packageName, 171 | pythonName: pythonPackageName, 172 | author: { 173 | name: props.authorName, 174 | email: props.authorEmail 175 | }, 176 | description: props.description, 177 | keywords: props.keywords, 178 | version: props.version, 179 | pythonVersions: versions, 180 | travis: travis, 181 | troves: troves, 182 | url: props.url, 183 | license: props.license, 184 | includePackageData: props.packageData, 185 | includePackageTests: props.packageTests, 186 | created: { 187 | day: new Date().getDay(), 188 | month: new Date().getMonth() + 1, 189 | year: new Date().getFullYear() 190 | }, 191 | services: pkgServices 192 | }; 193 | 194 | if (callback) { 195 | callback(this.package); 196 | } else { 197 | done(); 198 | } 199 | }.bind(this)); 200 | }.bind(this)); 201 | }, 202 | 203 | app: function (currentPkg) { 204 | var pkg = currentPkg || this.package; 205 | this.mkdir(pkg.pythonName); 206 | this.mkdir('tests/'); 207 | 208 | // root 209 | this.template('_setup.py', 'setup.py'); 210 | this.template('_makefile', 'Makefile'); 211 | this.template('_coveragerc', '.coveragerc'); 212 | this.template('_tox.ini', 'tox.ini'); 213 | this.template('_gitignore', '.gitignore'); 214 | this.template('_travis.yml', '.travis.yml'); 215 | 216 | if (!pkg.includePackageTests) { 217 | this.template('_manifest.in', 'MANIFEST.in'); 218 | } 219 | 220 | if (pkg.services.redis) { 221 | this.template('_redis.conf', 'redis.conf'); 222 | this.template('_redis_tests.conf', 'redis.tests.conf'); 223 | } 224 | 225 | // pkg.name/ 226 | this.template('_root_init.py', pkg.pythonName + '/__init__.py'); 227 | this.template('_version.py', pkg.pythonName + '/version.py'); 228 | 229 | // tests/ 230 | this.template('_init.py', 'tests/__init__.py'); 231 | this.template('_test_base.py', 'tests/base.py'); 232 | this.template('_test_version.py', 'tests/test_version.py'); 233 | }, 234 | 235 | getUsageMessage: function() { 236 | var pkg = this.package; 237 | this.log("\n\nNow that your project is all created, here is what the make commands can do for you!\n"); 238 | this.log("General commands:"); 239 | this.log('* "make list" to list all available targets;'); 240 | 241 | this.log('* "make setup" to install all dependencies (do not forget to create a virtualenv first);'); 242 | this.log('* "make test" to test your application (tests in the tests/ directory);'); 243 | 244 | if (pkg.services.redis) { 245 | this.log("\nRedis commands:"); 246 | this.log('* "make redis" to get a redis instance up (localhost:4444);'); 247 | this.log('* "make kill-redis" to kill this redis instance (localhost:4444);'); 248 | this.log('* "make redis-test" to get a redis instance up for your unit tests (localhost:4448);'); 249 | this.log('* "make kill-redis-test" to kill the test redis instance (localhost:4448);'); 250 | } 251 | 252 | if (pkg.services.mongodb) { 253 | this.log("\nMongoDB commands:"); 254 | this.log('* "make mongo" to get a mongodb instance up (localhost:3333);'); 255 | this.log('* "make kill-mongo" to kill this mongodb instance (localhost:3333);'); 256 | this.log('* "make clear-mongo" to clear all data in this mongodb instance (localhost: 3333);'); 257 | this.log('* "make mongo-test" to get a mongodb instance up for your unit tests (localhost:3334);'); 258 | this.log('* "make kill-mongo-test" to kill the test mongodb instance (localhost: 3334);'); 259 | } 260 | 261 | this.log('* "make tox" to run tests against all supported python versions.'); 262 | }, 263 | 264 | }); 265 | 266 | module.exports = PythonPackageGenerator; 267 | -------------------------------------------------------------------------------- /app/templates/_coveragerc: -------------------------------------------------------------------------------- 1 | # This file is part of <%= package.name %>. 2 | # <%= package.url %> 3 | 4 | # Licensed under the <%= package.license %> license: 5 | # http://www.opensource.org/licenses/<%= package.license%>-license 6 | # Copyright (c) <%= package.created.year %>, <%= package.author.name %> <<%= package.author.email %>> 7 | 8 | [run] 9 | omit = 10 | *tests.py 11 | branch = True 12 | source = 13 | <%= package.pythonName %> 14 | 15 | [report] 16 | exclude_lines = 17 | pragma: no cover 18 | def __repr__ 19 | raise NotImplementedError 20 | if __name__ == .__main__.: 21 | from urllib.parse import parse_qs 22 | except ImportError: 23 | -------------------------------------------------------------------------------- /app/templates/_gitignore: -------------------------------------------------------------------------------- 1 | # This file is part of <%= package.name %>. 2 | # <%= package.url %> 3 | 4 | # Licensed under the <%= package.license %> license: 5 | # http://www.opensource.org/licenses/<%= package.license%>-license 6 | # Copyright (c) <%= package.created.year %>, <%= package.author.name %> <<%= package.author.email %>> 7 | 8 | # Byte-compiled / optimized / DLL files 9 | __pycache__/ 10 | *.py[cod] 11 | 12 | # C extensions 13 | *.so 14 | 15 | # Distribution / packaging 16 | .Python 17 | env/ 18 | bin/ 19 | build/ 20 | develop-eggs/ 21 | dist/ 22 | eggs/ 23 | lib/ 24 | lib64/ 25 | parts/ 26 | sdist/ 27 | var/ 28 | *.egg-info/ 29 | .installed.cfg 30 | *.egg 31 | 32 | # Installer logs 33 | pip-log.txt 34 | pip-delete-this-directory.txt 35 | 36 | # Unit test / coverage reports 37 | htmlcov/ 38 | .tox/ 39 | .coverage 40 | .cache 41 | nosetests.xml 42 | coverage.xml 43 | 44 | # Translations 45 | *.mo 46 | 47 | # Mr Developer 48 | .mr.developer.cfg 49 | .project 50 | .pydevproject 51 | 52 | # Rope 53 | .ropeproject 54 | 55 | # Django stuff: 56 | *.log 57 | *.pot 58 | 59 | # Sphinx documentation 60 | docs/_build/ 61 | -------------------------------------------------------------------------------- /app/templates/_init.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # This file is part of <%= package.name %>. 5 | # <%= package.url %> 6 | 7 | # Licensed under the <%= package.license %> license: 8 | # http://www.opensource.org/licenses/<%= package.license%>-license 9 | # Copyright (c) <%= package.created.year %>, <%= package.author.name %> <<%= package.author.email %>> 10 | -------------------------------------------------------------------------------- /app/templates/_makefile: -------------------------------------------------------------------------------- 1 | # This file is part of <%= package.name %>. 2 | # <%= package.url %> 3 | 4 | # Licensed under the <%= package.license %> license: 5 | # http://www.opensource.org/licenses/<%= package.license%>-license 6 | # Copyright (c) <%= package.created.year %>, <%= package.author.name %> <<%= package.author.email %>> 7 | 8 | # lists all available targets 9 | list: 10 | @sh -c "$(MAKE) -p no_targets__ | awk -F':' '/^[a-zA-Z0-9][^\$$#\/\\t=]*:([^=]|$$)/ {split(\$$1,A,/ /);for(i in A)print A[i]}' | grep -v '__\$$' | grep -v 'make\[1\]' | grep -v 'Makefile' | sort" 11 | # required for list 12 | no_targets__: 13 | 14 | # install all dependencies (do not forget to create a virtualenv first) 15 | setup: 16 | @pip install -U -e .\[tests\] 17 | 18 | # test your application (tests in the tests/ directory) 19 | test: <% if (package.services.mongodb) { %>mongo_test <% } %><% if (package.services.redis) { %>redis_test <% } %>unit 20 | 21 | unit: 22 | @coverage run --branch `which nosetests` -vv --with-yanc -s tests/ 23 | @coverage report -m --fail-under=80 24 | 25 | # show coverage in html format 26 | coverage-html: unit 27 | @coverage html 28 | <% if (package.services.redis) { %> 29 | # get a redis instance up (localhost:4444) 30 | redis: kill_redis 31 | redis-server ./redis.conf; sleep 1 32 | redis-cli -p 4444 info > /dev/null 33 | 34 | # kill this redis instance (localhost:4444) 35 | kill_redis: 36 | -redis-cli -p 4444 shutdown 37 | 38 | # get a redis instance up for your unit tests (localhost:4448) 39 | redis_test: kill_redis_test 40 | @redis-server ./redis.tests.conf; sleep 1 41 | @redis-cli -p 4448 info > /dev/null 42 | 43 | # kill the test redis instance (localhost:4448) 44 | kill_redis_test: 45 | @-redis-cli -p 4448 shutdown 46 | <% } 47 | if (package.services.mongodb) { %> 48 | # get a mongodb instance up (localhost:3333) 49 | mongo: kill_mongo 50 | @mkdir -p /tmp/<%= package.name %>/mongodata && mongod --dbpath /tmp/<%= package.name %>/mongodata --logpath /tmp/<%= package.name %>/mongolog --port 3333 --quiet & 51 | 52 | # kill this mongodb instance (localhost:3333) 53 | kill_mongo: 54 | @-ps aux | egrep -i 'mongod.+3333' | egrep -v egrep | awk '{ print $$2 }' | xargs kill -9 55 | 56 | # clear all data in this mongodb instance (localhost: 3333) 57 | clear_mongo: 58 | @rm -rf /tmp/<%= package.name %> && mkdir -p /tmp/<%= package.name %>/mongodata 59 | 60 | # get a mongodb instance up for your unit tests (localhost:3334) 61 | mongo_test: kill_mongo_test 62 | @rm -rf /tmp/<%= package.name %>/mongotestdata && mkdir -p /tmp/<%= package.name %>/mongotestdata 63 | @mongod --dbpath /tmp/<%= package.name %>/mongotestdata --logpath /tmp/<%= package.name %>/mongotestlog --port 3334 --quiet --fork 64 | @echo 'waiting for mongo...' 65 | @until mongo --port 3334 --eval "quit()"; do sleep 0.25; done > /dev/null 2> /dev/null 66 | 67 | # kill the test mongodb instance (localhost: 3334) 68 | kill_mongo_test: 69 | @-ps aux | egrep -i 'mongod.+3334' | egrep -v egrep | awk '{ print $$2 }' | xargs kill -9 70 | <% } %> 71 | # run tests against all supported python versions 72 | tox: 73 | @tox 74 | 75 | #docs: 76 | #@cd <%= package.pythonName %>/docs && make html && open _build/html/index.html 77 | -------------------------------------------------------------------------------- /app/templates/_manifest.in: -------------------------------------------------------------------------------- 1 | # This file is part of <%= package.name %>. 2 | # <%= package.url %> 3 | 4 | # Licensed under the <%= package.license %> license: 5 | # http://www.opensource.org/licenses/<%= package.license%>-license 6 | # Copyright (c) <%= package.created.year %>, <%= package.author.name %> <<%= package.author.email %>> 7 | 8 | recursive-exclude tests * 9 | -------------------------------------------------------------------------------- /app/templates/_redis.conf: -------------------------------------------------------------------------------- 1 | # This file is part of <%= package.name %>. 2 | # <%= package.url %> 3 | 4 | # Licensed under the <%= package.license %> license: 5 | # http://www.opensource.org/licenses/<%= package.license%>-license 6 | # Copyright (c) <%= package.created.year %>, <%= package.author.name %> <<%= package.author.email %>> 7 | 8 | daemonize yes 9 | pidfile /tmp/redis_<%= package.name %>.pid 10 | port 4444 11 | dbfilename <%= package.name %>.rdb 12 | dir /tmp 13 | -------------------------------------------------------------------------------- /app/templates/_redis_tests.conf: -------------------------------------------------------------------------------- 1 | # This file is part of <%= package.name %>. 2 | # <%= package.url %> 3 | 4 | # Licensed under the <%= package.license %> license: 5 | # http://www.opensource.org/licenses/<%= package.license%>-license 6 | # Copyright (c) <%= package.created.year %>, <%= package.author.name %> <<%= package.author.email %>> 7 | 8 | daemonize yes 9 | pidfile /tmp/redis_<%= package.name %>_tests.pid 10 | port 4448 11 | dbfilename <%= package.name %>_tests.rdb 12 | dir /tmp 13 | -------------------------------------------------------------------------------- /app/templates/_root_init.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # This file is part of <%= package.name %>. 5 | # <%= package.url %> 6 | 7 | # Licensed under the <%= package.license %> license: 8 | # http://www.opensource.org/licenses/<%= package.license%>-license 9 | # Copyright (c) <%= package.created.year %>, <%= package.author.name %> <<%= package.author.email %>> 10 | 11 | from <%= package.pythonName %>.version import __version__ # NOQA 12 | -------------------------------------------------------------------------------- /app/templates/_setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # This file is part of <%= package.name %>. 5 | # <%= package.url %> 6 | 7 | # Licensed under the <%= package.license %> license: 8 | # http://www.opensource.org/licenses/<%= package.license%>-license 9 | # Copyright (c) <%= package.created.year %>, <%= package.author.name %> <<%= package.author.email %>> 10 | 11 | from setuptools import setup, find_packages 12 | from <%= package.pythonName %> import __version__ 13 | 14 | tests_require = [ 15 | 'mock', 16 | 'nose', 17 | 'coverage', 18 | 'yanc', 19 | 'preggy', 20 | 'tox', 21 | 'ipdb', 22 | 'coveralls', 23 | 'sphinx', 24 | ] 25 | 26 | setup( 27 | name='<%= package.name %>', 28 | version=__version__, 29 | description='<%= package.description %>', 30 | long_description=''' 31 | <%= package.description %> 32 | ''', 33 | keywords='<%= package.keywords %>', 34 | author='<%= package.author.name %>', 35 | author_email='<%= package.author.email %>', 36 | url='<%= package.url %>', 37 | license='<%= package.license %>', 38 | classifiers=[ 39 | 'Development Status :: 4 - Beta', 40 | 'Intended Audience :: Developers', 41 | 'License :: OSI Approved :: <%= package.license %> License', 42 | 'Natural Language :: English', 43 | 'Operating System :: Unix', 44 | <% for (var i=0; i< package.troves.length; i++) { %>'<%= package.troves[i] %>', 45 | <% } %>'Operating System :: OS Independent', 46 | ], 47 | packages=find_packages(), 48 | include_package_data=<%= package.includePackageData ? "True" : "False" %>, 49 | install_requires=[ 50 | # add your dependencies here 51 | # remember to use 'package-name>=x.y.z,<%= package.services.redis ? " 'redis',\n" : "" 55 | %> ], 56 | extras_require={ 57 | 'tests': tests_require, 58 | }, 59 | entry_points={ 60 | 'console_scripts': [ 61 | # add cli scripts here in this form: 62 | # '<%= package.name %>=<%= package.pythonName %>.cli:main', 63 | ], 64 | }, 65 | ) 66 | -------------------------------------------------------------------------------- /app/templates/_test_base.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # This file is part of <%= package.name %>. 5 | # <%= package.url %> 6 | 7 | # Licensed under the <%= package.license %> license: 8 | # http://www.opensource.org/licenses/<%= package.license%>-license 9 | # Copyright (c) <%= package.created.year %>, <%= package.author.name %> <<%= package.author.email %>> 10 | 11 | from unittest import TestCase as PythonTestCase 12 | 13 | 14 | class TestCase(PythonTestCase): 15 | pass 16 | -------------------------------------------------------------------------------- /app/templates/_test_version.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # This file is part of <%= package.name %>. 5 | # <%= package.url %> 6 | 7 | # Licensed under the <%= package.license %> license: 8 | # http://www.opensource.org/licenses/<%= package.license%>-license 9 | # Copyright (c) <%= package.created.year %>, <%= package.author.name %> <<%= package.author.email %>> 10 | 11 | from preggy import expect 12 | 13 | from <%= package.pythonName %> import __version__ 14 | from tests.base import TestCase 15 | 16 | 17 | class VersionTestCase(TestCase): 18 | def test_has_proper_version(self): 19 | expect(__version__).to_equal('<%= package.version %>') 20 | -------------------------------------------------------------------------------- /app/templates/_tox.ini: -------------------------------------------------------------------------------- 1 | # This file is part of <%= package.name %>. 2 | # <%= package.url %> 3 | 4 | # Licensed under the <%= package.license %> license: 5 | # http://www.opensource.org/licenses/<%= package.license%>-license 6 | # Copyright (c) <%= package.created.year %>, <%= package.author.name %> <<%= package.author.email %>> 7 | 8 | [tox] 9 | envlist = <%= package.pythonVersions.join(', ') %> 10 | 11 | [testenv] 12 | commands = 13 | make setup 14 | make test 15 | -------------------------------------------------------------------------------- /app/templates/_travis.yml: -------------------------------------------------------------------------------- 1 | # This file is part of <%= package.name %>. 2 | # <%= package.url %> 3 | 4 | # Licensed under the <%= package.license %> license: 5 | # http://www.opensource.org/licenses/<%= package.license%>-license 6 | # Copyright (c) <%= package.created.year %>, <%= package.author.name %> <<%= package.author.email %>> 7 | 8 | language: python 9 | 10 | python:<% for (var i=0; i < package.travis.length; i++) { %> 11 | - "<%= package.travis[i] %>"<% } %> 12 | 13 | install: 14 | # install python requirements 15 | - make setup 16 | 17 | script: 18 | # run tests 19 | - make test 20 | -------------------------------------------------------------------------------- /app/templates/_version.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | # This file is part of <%= package.name %>. 5 | # <%= package.url %> 6 | 7 | # Licensed under the <%= package.license %> license: 8 | # http://www.opensource.org/licenses/<%= package.license%>-license 9 | # Copyright (c) <%= package.created.year %>, <%= package.author.name %> <<%= package.author.email %>> 10 | 11 | __version__ = '<%= package.version %>' # NOQA 12 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "generator-python-package", 3 | "version": "0.1.5", 4 | "description": "Yeoman generator", 5 | "license": "MIT", 6 | "main": "app/index.js", 7 | "repository": "heynemann/generator-python-package", 8 | "author": { 9 | "name": "Bernardo Heynemann", 10 | "email": "heynemann@gmail.com", 11 | "url": "https://github.com/heynemann" 12 | }, 13 | "engines": { 14 | "node": ">=0.10.0" 15 | }, 16 | "scripts": { 17 | "test": "mocha" 18 | }, 19 | "files": [ 20 | "app" 21 | ], 22 | "keywords": [ 23 | "yeoman-generator" 24 | ], 25 | "dependencies": { 26 | "yeoman-generator": "~0.16.0", 27 | "chalk": "~0.4.0", 28 | "yosay": "^0.1.0" 29 | }, 30 | "devDependencies": { 31 | "mocha": "*" 32 | }, 33 | "peerDependencies": { 34 | "yo": ">=1.0.0" 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /test/test-creation.js: -------------------------------------------------------------------------------- 1 | /*global describe, beforeEach, it */ 2 | 'use strict'; 3 | var path = require('path'); 4 | var helpers = require('yeoman-generator').test; 5 | 6 | describe('python-package generator', function () { 7 | beforeEach(function (done) { 8 | helpers.testDirectory(path.join(__dirname, 'temp'), function (err) { 9 | if (err) { 10 | return done(err); 11 | } 12 | 13 | this.app = helpers.createGenerator('python-package:app', ['../../app']); 14 | done(); 15 | 16 | this.app.options['skip-install'] = true; 17 | 18 | helpers.mockPrompt(this.app, { 19 | packageName: 'test-package', 20 | pythonVersions: ['2.7@py27@Python :: 2.7'], 21 | description: 'an incredible python package', 22 | keywords: 'test package', 23 | authorName: 'Pablo Santiago Blum de Aguiar', 24 | authorEmail: 'scorphus@gmail.com', 25 | url: 'https://github.com/someuser/somepackage', 26 | license: 'MIT', 27 | services: ['mongodb', 'redis'], 28 | }); 29 | }.bind(this)); 30 | }); 31 | 32 | it('creates expected files', function (done) { 33 | var expected = [ 34 | 'setup.py', 35 | 'Makefile', 36 | '.coveragerc', 37 | 'tox.ini', 38 | '.gitignore', 39 | '.travis.yml', 40 | 'MANIFEST.in', 41 | 'redis.conf', 42 | 'redis.tests.conf', 43 | 'test_package/__init__.py', 44 | 'test_package/version.py', 45 | 'tests/__init__.py', 46 | 'tests/base.py', 47 | 'tests/test_version.py', 48 | ]; 49 | 50 | this.app.run({}, function () { 51 | helpers.assertFile(expected); 52 | done(); 53 | }); 54 | }); 55 | 56 | it('creates Makefile with right targets files', function (done) { 57 | this.app.run({}, function () { 58 | helpers.assertFileContent('Makefile', /list:/); 59 | helpers.assertFileContent('Makefile', /no_targets__:/); 60 | helpers.assertFileContent('Makefile', /setup:/); 61 | helpers.assertFileContent('Makefile', /test:/); 62 | helpers.assertFileContent('Makefile', /unit:/); 63 | helpers.assertFileContent('Makefile', /redis:/); 64 | helpers.assertFileContent('Makefile', /kill_redis:/); 65 | helpers.assertFileContent('Makefile', /redis_test:/); 66 | helpers.assertFileContent('Makefile', /kill_redis_test:/); 67 | helpers.assertFileContent('Makefile', /mongo:/); 68 | helpers.assertFileContent('Makefile', /kill_mongo:/); 69 | helpers.assertFileContent('Makefile', /clear_mongo:/); 70 | helpers.assertFileContent('Makefile', /mongo_test:/); 71 | helpers.assertFileContent('Makefile', /kill_mongo_test:/); 72 | helpers.assertFileContent('Makefile', /tox:/); 73 | done(); 74 | }); 75 | }); 76 | 77 | it('creates setup.py with right elements', function (done) { 78 | this.app.run({}, function () { 79 | helpers.assertFileContent('setup.py', /from test_package import __version__/); 80 | helpers.assertFileContent('setup.py', /name='test-package',/); 81 | helpers.assertFileContent('setup.py', / version=__version__,/); 82 | helpers.assertFileContent('setup.py', / description='an incredible python package',/); 83 | helpers.assertFileContent('setup.py', /\nan incredible python package\n/); 84 | helpers.assertFileContent('setup.py', / keywords='test package',/); 85 | helpers.assertFileContent('setup.py', / author='Pablo Santiago Blum de Aguiar',/); 86 | helpers.assertFileContent('setup.py', / author_email='scorphus@gmail.com',/); 87 | helpers.assertFileContent('setup.py', / url='https:\/\/github.com\/someuser\/somepackage',/); 88 | helpers.assertFileContent('setup.py', / license='MIT',/); 89 | helpers.assertFileContent('setup.py', / 'Programming Language :: Python :: 2.7',/); 90 | helpers.assertFileContent('setup.py', / include_package_data=False,/); 91 | helpers.assertFileContent('setup.py', / 'pymongo',/); 92 | helpers.assertFileContent('setup.py', / 'redis',/); 93 | done(); 94 | }); 95 | }); 96 | 97 | }); 98 | -------------------------------------------------------------------------------- /test/test-load.js: -------------------------------------------------------------------------------- 1 | /*global describe, beforeEach, it*/ 2 | 'use strict'; 3 | var assert = require('assert'); 4 | 5 | describe('python-package generator', function () { 6 | it('can be imported without blowing up', function () { 7 | var app = require('../app'); 8 | assert(app !== undefined); 9 | }); 10 | }); 11 | --------------------------------------------------------------------------------