Python for lazy
or how to make your life easier
Nikita Grishko
Wargaming.net
Setup project
Start new project
% mkdir awesome_project_43 && cd ./awesome_project_43
% mkdir awesomemodule
% touch awesomemodule/__init__.py
% cp ../awesome_project_42/LISENSE ./
% cp ../awesome_project_42/README.md ./
% cp ../awesome_project_42/HISTORY.rst ./
% cp ../awesome_project_42/setup.py ./
% cp ../awesome_project_42/.gitignore ./
% cp ../awesome_project_42/tox.ini ./
...
Madness...
mr.bob
mr.bob
% mkdir awesome_project_43 && cd ./awesome_project_43 % mrbob ../bobtemplates/gr1n/python_package ...
--> Dotted name of the package?: awesome_project_43 --> Name of the package referenced by installers?: awesome_project_43 --> Description of the package (visible on PyPI and similar): --> Version? [0.1]: --> Repository URL for the package: --> URL for more information about the package: --> What year was the project started? [2014]: --> Do you want to support Python 2? [No]: --> Author name?: Nikita Grishko --> Author email address?: Generated file structure at ../awesome_project_43
mr.bob
% cat .mrbob.ini
[questions]
package.dottedname.question = Dotted name of the package?
package.dottedname.required = True
package.name.question = Name of the package referenced by installers?
package.name.required = True
package.description.question = Description of the package (visible on PyPI and similar)
package.version.question = Version?
package.version.default = 0.1
package.repository.question = Repository URL for the package
...
mr.bob
% ls -l
total 64
-rw-r--r-- 1 nikitagrishko staff 95 Apr 21 22:23 HISTORY.rst
-rw-r--r-- 1 nikitagrishko staff 1081 Apr 21 22:23 LICENSE
-rw-r--r-- 1 nikitagrishko staff 98 Apr 21 22:23 MANIFEST.in
-rw-r--r-- 1 nikitagrishko staff 219 Apr 21 22:23 README.md
-rw-r--r-- 1 nikitagrishko staff 215 Apr 21 22:23 README.rst
drwxr-xr-x 3 nikitagrishko staff 102 Apr 21 22:23 awesome_project_43
-rw-r--r-- 1 nikitagrishko staff 283 Apr 20 22:38 setup.cfg
-rw-r--r-- 1 nikitagrishko staff 1074 Apr 21 22:23 setup.py
drwxr-xr-x 3 nikitagrishko staff 102 Apr 21 22:23 tests
-rw-r--r-- 1 nikitagrishko staff 137 Apr 21 22:23 tox.ini
Cookiecutter
yeoman
Problem #1
diff --git a/file1.py b/file1.py
index b69df39..ba4e68d 100644
--- a/file1.py
+++ b/file1.py
@@ -1,2 +1,2 @@
-def hello_world():
- print('Hello world')
+def hello_world():
+ print('Hello world')
Problem #2
diff --git b/file2.py a/file2.py
index ba4e68d..5f12b05 100644
--- b/file2.py
+++ a/file2.py
@@ -1,2 +1,2 @@
def hello_world():
- print('Hello world')
+ print('Hello world')
Problem #3
Madness...
EditorConfig
EditorConfig
% cat .editorconfig
root = true
[*]
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[**.{py,js}]
indent_style = space
indent_size = 4
[**.ini]
indent_style = space
indent_size = 2
EditorConfig
Plugins:
- SublimeText
- PyCharm
- Vim
- Emacs
- ...
Pylint
Pylint
% pylint ./onepyssword No config file found, using default configuration ************* Module onepyssword C: 1, 0: Missing module docstring (missing-docstring) ************* Module onepyssword.app C: 35, 0: Line too long (85/80) (line-too-long) C:110, 0: Line too long (93/80) (line-too-long) C: 1, 0: Missing module docstring (missing-docstring) F: 9, 0: Unable to import 'copypaste' (import-error) C: 28, 4: Invalid constant name "NoSuchFileOrDirectoryException" (invalid-name) E: 28,37: Undefined variable 'FileNotFoundError' (undefined-variable)
...
flake8
flake8
% cat setup.cfg
[egg_info]
tag_build =
tag_date = 0
[easy_install]
zip_ok = false
[flake8]
ignore = E123,E127,E121
# E123: closing bracket must match indent of starting bracket
# E127 continuation line over-indented for visual indent
# E121 continuation line indentation is not a multiple of four
flake8
% flake8 ./onepyssword
./onepyssword/app.py:28:38: F821 undefined name 'FileNotFoundError'
./onepyssword/app.py:35:80: E501 line too long (85 > 79 characters)
./onepyssword/app.py:110:80: E501 line too long (93 > 79 characters)
./onepyssword/logic.py:30:80: E501 line too long (91 > 79 characters)
./onepyssword/logic.py:40:80: E501 line too long (87 > 79 characters)
./onepyssword/logic.py:64:80: E501 line too long (89 > 79 characters)
./onepyssword/logic.py:66:80: E501 line too long (87 > 79 characters)
./onepyssword/logic.py:73:80: E501 line too long (84 > 79 characters)
./onepyssword/logic.py:78:80: E501 line too long (97 > 79 characters)
./onepyssword/logic.py:117:80: E501 line too long (99 > 79 characters)
./onepyssword/logic.py:120:80: E501 line too long (107 > 79 characters)
./onepyssword/logic.py:131:80: E501 line too long (80 > 79 characters)
Environment
virtualenv
virtualenv
% virtualenv ENV
% source ENV/bin/activate
venv (python>=3.2)
% pyvenv ENV
% source ENV/bin/activate
virtualenvwrapper
virtualenvwrapper
Features:
- Organizes all of your virtual environments in one place.
- Wrappers for managing your virtual environments (create, delete, copy).
- Use a single command to switch between environments.
- ...
virtualenvwrapper
% pip install virtualenvwrapper
...
% export WORKON_HOME=~/Envs
% mkdir -p $WORKON_HOME
% source /usr/local/bin/virtualenvwrapper.sh
% mkvirtualenv env1
...
(env1)% ls $WORKON_HOME
env1 hook.log
(env1)% pip install django
...
(env1)$ lssitepackages
Django-1.1.1-py2.6.egg-info easy-install.pth
...
virtualenvwrapper
Commands:
- mkvirtualenv
- mktmpenv
- lsvitualenv
- rmvirtualenv
- workon
- deactivate
- cdvirtualenv
- cdsitepackages
- ...
pyenv
pyenv
Commands:
- local
- global
- shell
- install (104 versions)
- uninstall
- versions
- ...
pyenv-virtualenv
Development
Shell
IPython
bpython
bpython
Features:
-
In-line syntax highlighting.
- Readline-like autocomplete with suggestions displayed as you type.
- Expected parameter list for any Python function.
- Send the code you've entered off to a pastebin.
- Save the code you've entered to a file.
- Auto-indentation.
bpython
Debugger
Python 3.4.0 (default, Apr 9 2014, 11:51:10)
[GCC 4.2.1 Compatible Apple LLVM 5.1 (clang-503.0.38)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> def foo():
... import pdb; pdb.set_trace()
... for i in range(6):
... print(i)
...
>>> foo()
> <stdin>(3)foo()
(Pdb) s
> <stdin>(4)foo()
(Pdb) s
0
> <stdin>(3)foo()
(Pdb) c
2
3
4
5
pudb
pudb
Features:
-
Syntax-highlighted source, the stack, breakpoints and variables are all visible at once and continuously updated.
- Simple, keyboard-based navigation.
- Drop to a Python shell in the current environment by pressing "!".
- ...
pudb
MailCatcher
MailCatcher
Testing
tox
tox
% cat tox.ini
[tox]
envlist = py27,py33,pypy
[testenv]
changedir = tests
deps =
pytest
commands =
py.test
pytest
pytest
http://pytest-plugs.herokuapp.com/
% cat tox.ini
[tox]
envlist = py27,py33,pypy
[testenv]
changedir = tests
deps =
pytest
pytest-pep8
pytest-cov
commands =
py.test --pep8 --cov myproj
PyPI
Build and upload package
% vim setup.py
% vim HISTORY.rst
% git commit -a -m "Version 0.2"
% git push
% git tag -a v0.2 -m "Version 0.2"
% git push --tags
% python setup.py sdist upload
% vim setup.py
% vim HISTORY.rst
% git commit -a -m "Version 0.3.dev"
% git push
...
Madness...
check-manifest
check-manifest
% check-manifest -u
listing source files under version control: 6 files and directories
building an sdist: check-manifest-0.7.tar.gz: 4 files and directories
files in version control do not match the sdist!
missing from sdist:
tests.py
tox.ini
suggested MANIFEST.in rules:
include *.py
include tox.ini
updating MANIFEST.in
% cat MANIFEST.in
include *.rst
# added by check_manifest.py
include *.py
include tox.ini
zest.releaser
zest.releaser
Commands:
- prerelease
- release
- postrelease
- fullrelease
- longtest
- lasttagdiff
pypispy
pypispy
% pypispy
onepyssword
--> info:
----> version: 0.3.1
----> downloads:
------> last_day: 8
------> last_week: 120
------> last_month: 882
copypaste
--> info:
----> version: 0.2
----> downloads:
------> last_day: 5
------> last_week: 61
------> last_month: 448
Links
- https://wiki.python.org/moin/DevelopmentTools
- https://www.google.com/
- https://github.com/
Questions?
nose
Fabric
PyChecker
Sphinx
Grymt
Python for lazy or how to make your life easier
By Nikita Grishko
Python for lazy or how to make your life easier
[25-04-2014] Python Meetup, Minsk
- 5,754