Python for lazy

or how to make your life easier

Nikita Grishko
Wargaming.net

@Gr1Nbyhttps://github.com/Gr1N

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

https://github.com/iElectric/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

https://github.com/audreyr/cookiecutter

yeoman


http://yeoman.io/

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


http://editorconfig.org/

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


http://www.pylint.org/

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


https://bitbucket.org/tarek/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


http://www.virtualenv.org/

virtualenv

% virtualenv ENV% source ENV/bin/activate

venv (python>=3.2)

% pyvenv ENV% source ENV/bin/activate

virtualenvwrapper


http://virtualenvwrapper.readthedocs.org/

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


https://github.com/yyuu/pyenv

pyenv

Commands:
  • local
  • global
  • shell
  • install (104 versions)
  • uninstall
  • versions
  • ...

pyenv-virtualenv


https://github.com/yyuu/pyenv-virtualenv

Development

Shell


IPython


http://ipython.org/

bpython


http://bpython-interpreter.org/

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


https://github.com/inducer/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


http://mailcatcher.me/

MailCatcher


Testing

tox


http://tox.readthedocs.org/

tox

% cat tox.ini
[tox]
envlist = py27,py33,pypy

[testenv]
changedir = tests
deps =
  pytest
commands =
  py.test

pytest


http://pytest.org/

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


https://github.com/mgedmin/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


https://github.com/zestsoftware/zest.releaser

zest.releaser

Commands:
  • prerelease
  • release
  • postrelease
  • fullrelease
  • longtest
  • lasttagdiff

pypispy


http://gr1n.github.io/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


https://nose.readthedocs.org/

Fabric


http://www.fabfile.org/

PyChecker


http://pychecker.sourceforge.net/

Sphinx


http://sphinx-doc.org/

Grymt


http://www.peterbe.com/plog/grymt
Made with Slides.com