werkzeugkiste.pdf

71229c0167172520e0582dbf29cbd88f?s=47 wosc
October 28, 2012
150

 werkzeugkiste.pdf

71229c0167172520e0582dbf29cbd88f?s=128

wosc

October 28, 2012
Tweet

Transcript

  1. Aus der Werkzeugkiste eines Python/Web-Entwicklers Wolfgang Schnerring gmbh & co.

    kg PyCon DE 2012, Leipzig Wolfgang Schnerring Werkzeugkiste 01.11.2012 1 / 45
  2. None
  3. None
  4. Agenda 1 Sandbox 2 Editor 3 Konsole 4 Testing 5

    Deployment http://www.flickr.com/photos/zakh/337938459 by zakh Wolfgang Schnerring Werkzeugkiste 01.11.2012 4 / 45
  5. Sandbox http://www.sxc.hu/photo/1379396 by Safari11

  6. Sandbox Paket-Skelett setup.py README.txt CHANGES.txt HACKING.txt LICENSE.txt doc/ src/ws/pycondetalk/tests/ jeweils

    mit passender __init__.py Wolfgang Schnerring Werkzeugkiste 01.11.2012 6 / 45
  7. Sandbox Paket-Skelett $ bin/paster create -t gocept_package ws.pycondetalk <...snip...> Enter

    description (One-line description of the package) ['']: An example for my talk Enter keywords (Space-separated keywords/tags) ['']: Creating template gocept_package <...snip...> Wolfgang Schnerring Werkzeugkiste 01.11.2012 7 / 45
  8. Sandbox Isolation http://www.flickr.com/photos/ajc1/2799103829 by ajc1 Using the system-installed Python is

    considered harmful. I want YOU to use virtualenv! Wolfgang Schnerring Werkzeugkiste 01.11.2012 8 / 45
  9. Sandbox Isolation http://www.flickr.com/photos/ajc1/2799103829 by ajc1 Using the system-installed Python is

    considered harmful. I want YOU to use virtualenv! . . . but not activate! Wolfgang Schnerring Werkzeugkiste 01.11.2012 8 / 45
  10. Sandbox Pakete installieren PyPI ist hervorragend! Wolfgang Schnerring Werkzeugkiste 01.11.2012

    9 / 45
  11. Sandbox Pakete installieren PyPI ist hervorragend – außer, wenn er

    down ist Leute ihre Eggs nicht hochladen, sondern selber hosten und dann down sind Leute alte Versionen löschen . . . Wolfgang Schnerring Werkzeugkiste 01.11.2012 10 / 45
  12. Sandbox Pakete installieren PyPI ist hervorragend – außer, wenn er

    down ist Leute ihre Eggs nicht hochladen, sondern selber hosten und dann down sind Leute alte Versionen löschen . . . Hilfreiche Parameter für pip/easy_install: index, find-links socket-timeout, allow-hosts Wolfgang Schnerring Werkzeugkiste 01.11.2012 10 / 45
  13. Sandbox Pakete installieren I want YOU to pin your versions!

    Wolfgang Schnerring Werkzeugkiste 01.11.2012 11 / 45
  14. Sandbox Pakete installieren [buildout] allow−picked−versions = false versions = versions

    [versions] Sphinx = 1.1.2 zc.buildout pip install -r requirements.txt ist nicht ganz das gleiche Wolfgang Schnerring Werkzeugkiste 01.11.2012 12 / 45
  15. Editor http://www.sxc.hu/photo/1157698 by hisks

  16. Editor Navigation: Exuberant ctags --python-kinds=-i Wolfgang Schnerring Werkzeugkiste 01.11.2012 14

    / 45
  17. Editor Syntax check Emacs: flymake-mode, Vim: syntastic pyflakes, importchecker, pep8,

    pylint Wolfgang Schnerring Werkzeugkiste 01.11.2012 15 / 45
  18. http://ethanschoonover.com/solarized

  19. Konsole http://en.wikipedia.org/wiki/File:Vt100-adventure.jpg by D. Fischer

  20. Konsole Anwendung >>> import zope, myapp >>> um = zope.component.getUtility(

    myapp.usermanager.interfaces.IUserManager) >>> um.get_user( ’wroing@example.com’).login = ’wrong@example.com’ >>> import transaction >>> transaction.commit() Wolfgang Schnerring Werkzeugkiste 01.11.2012 18 / 45
  21. Konsole Anwendung >>> import zope, myapp >>> um = zope.component.getUtility(

    myapp.usermanager.interfaces.IUserManager) >>> um.get_user( ’wroing@example.com’).login = ’wrong@example.com’ >>> import transaction >>> transaction.commit() Zope: zopectl debug Pyramid: bin/pshell etc/paste.ini Django: manage.py shell Wolfgang Schnerring Werkzeugkiste 01.11.2012 18 / 45
  22. Konsole Readline-History (pdb) p self.request.get(’key’).getList() ∗∗∗ AttributeError: ’Example’ object has

    no attribute ’getList’ Wolfgang Schnerring Werkzeugkiste 01.11.2012 19 / 45
  23. Konsole Readline-History (pdb) p self.request.get(’key’).getList() ∗∗∗ AttributeError: ’Example’ object has

    no attribute ’getList’ <ARROW_UP> (pdb) p self.request.get(’key’).get_list() Wolfgang Schnerring Werkzeugkiste 01.11.2012 19 / 45
  24. Konsole Readline-History (pdb) p self.request.get(’key’).getList() ∗∗∗ AttributeError: ’Example’ object has

    no attribute ’getList’ <ARROW_UP> (pdb) p self.request.get(’key’).get_list() pdb (siehe https://gist.github.com/3621963) rlwrap Wolfgang Schnerring Werkzeugkiste 01.11.2012 19 / 45
  25. Konsole Test-Auswahl $ bin/test −t create_user $ bin/test −s myapp.subpackage

    Wolfgang Schnerring Werkzeugkiste 01.11.2012 20 / 45
  26. Konsole Test-Auswahl $ bin/test −t create_user $ bin/test −s myapp.subpackage

    zope.testrunner nose py.test stdlib unittest ab 2.7 (bzw. Backport-Paket unittest2) Wolfgang Schnerring Werkzeugkiste 01.11.2012 20 / 45
  27. Konsole Test-Auswahl $ t −t create_user $ t −s myapp.subpackage

    Wolfgang Schnerring Werkzeugkiste 01.11.2012 21 / 45
  28. None
  29. Testing Test-Layers class ExampleTest(unittest.TestCase): def setUp(self): def tearDown(self): def test_something(self):

    Wolfgang Schnerring Werkzeugkiste 01.11.2012 23 / 45
  30. Testing gemeinsames setUp Wolfgang Schnerring Werkzeugkiste 01.11.2012 24 / 45

  31. Testing Stacking Wolfgang Schnerring Werkzeugkiste 01.11.2012 25 / 45

  32. Testing Layer class Layer(object): __bases__ = (OTHER_LAYER,) def setUp(self): def

    tearDown(self): def testSetUp(self): def testTearDown(self): Wolfgang Schnerring Werkzeugkiste 01.11.2012 26 / 45
  33. Testing Beispiel class PersistenceTest(unittest.TestCase): layer = DB_LAYER def test_serializing_document_parameters(self): #

    [...] class IntegrationTest(unittest.TestCase): layer = COMBINED_LAYER def test_search_displays_suggestions_from_database(self): # [...] Wolfgang Schnerring Werkzeugkiste 01.11.2012 27 / 45
  34. Testing Beispiel class DatabaseLayer(plone.testing.Layer): def setUp(self): self.connection = dbdriver.connect(os.environ[’DSN’]) def

    tearDown(self): self.connection.close() DB_LAYER = DatabaseLayer() HTTP_LAYER = HTTPServerLayer() COMBINED_LAYER = plone.testing.Layer( bases=(DatabaseLayer, HTTPServerLayer)) Wolfgang Schnerring Werkzeugkiste 01.11.2012 28 / 45
  35. Testing JSLint var something = { ’foo’: ’bar’, }; Wolfgang

    Schnerring Werkzeugkiste 01.11.2012 29 / 45
  36. Testing JSLint var something = { ’foo’: ’bar’, }; $

    jshint foo.js Line 1: 'something' is defined but never used. Line 2: Extra comma. Wolfgang Schnerring Werkzeugkiste 01.11.2012 29 / 45
  37. Testing JSLint var something = { ’foo’: ’bar’, }; $

    jshint foo.js Line 1: 'something' is defined but never used. Line 2: Extra comma. $ bin/test -t jslint Failure in test test_jslint_foo.js Traceback (most recent call last): <snip> AssertionError: JSLint foo.js:2:Extra comma. Wolfgang Schnerring Werkzeugkiste 01.11.2012 29 / 45
  38. Testing gocept.jslint class JSLintTestCase(gocept.jslint.TestCase): include = (’my.package.browser:js’,) options = (gocept.jslint.TestCase.options

    + (’browser’, ’jquery’,)) ignore = ( "Don’t make functions within a loop", ) Wolfgang Schnerring Werkzeugkiste 01.11.2012 30 / 45
  39. Testing JavaScript Unit-Tests require ’my_app.js’ describe ’MyApp’, −> it ’has

    read Douglas Adams’, −> expect(new MyApp().calculate_the_answer()).toEqual(42) Wolfgang Schnerring Werkzeugkiste 01.11.2012 31 / 45
  40. Testing JavaScript Unit-Tests require ’my_app.js’ describe ’MyApp’, −> it ’has

    read Douglas Adams’, −> expect(new MyApp().calculate_the_answer()).toEqual(42) def test_suite(): return gocept.exttest.makeSuite( os.environ.get(’jasmine−bin’), ’−−coffee’, pkg_resources.resource_filename(’your.package’, ’tests’)) gocept.exttest ist noch im Alpha-Stadium. Wolfgang Schnerring Werkzeugkiste 01.11.2012 31 / 45
  41. Testing Selenium: Browser-Fernsteuerung Wolfgang Schnerring Werkzeugkiste 01.11.2012 32 / 45

  42. Testing Selenium: Browser-Fernsteuerung Wolfgang Schnerring Werkzeugkiste 01.11.2012 33 / 45

  43. Testing gocept.selenium class AutocompleteTest(gocept.selenium.wsgi.TestCase): layer = gocept.selenium.wsgi.Layer(my_wsgi_callable) def test_search_field_should_show_suggestions(self): s

    = self.selenium s.open(’http://%s:%s/search_form’ % (self.layer.host, self.layer.port) s.type(’name=q’, ’zope’) s.waitForVisible(’id=suggestions’)) s.assertText(’//div[@id="suggestions"])/ul/li[2]’, ’∗fisch’) Wolfgang Schnerring Werkzeugkiste 01.11.2012 34 / 45
  44. Testing Continuous Integration Wolfgang Schnerring Werkzeugkiste 01.11.2012 35 / 45

  45. Testing Continuous Integration http://jenkins-ci.org http://www.shiningpanda-ci.com Wolfgang Schnerring Werkzeugkiste 01.11.2012 36

    / 45
  46. Deployment http://www.sxc.hu/photo/1278811 by thimoholst

  47. Deployment Egg-Releases Thinking about checking out trunk to production? I

    want YOU to use eggs! Wolfgang Schnerring Werkzeugkiste 01.11.2012 38 / 45
  48. Deployment Egg-Releases 1 Versionsnummer in setup.py eintragen, Datum in CHANGES.txt

    eintragen 2 Tag erzeugen 3 python setup.py sdist 4 Tarball hochladen (PyPI oder eigener Server) 5 Versionsnummer in setup.py/CHANGES.txt hochzählen zest.relaser macht das alles auf Knopfdruck Wolfgang Schnerring Werkzeugkiste 01.11.2012 39 / 45
  49. Deployment http://12factor.net/ Codebase Dependencies Config Backing Services Build, release, run

    Processes Port binding Concurrency Disposability dev/prod parity Logs Admin processes Wolfgang Schnerring Werkzeugkiste 01.11.2012 40 / 45
  50. Deployment Konfigurations-Profile base.cfg email-from = noreply@example.com database-url = sqlite:/// dev.cfg

    extends = base.cfg database-url = postgresql://localhosthost/myapp-dev production.cfg extends = base.cfg database-url = postgresql://db.example.com/myapp Wolfgang Schnerring Werkzeugkiste 01.11.2012 41 / 45
  51. Deployment 1-Click-Deployment 1 Versionsnummern hochziehen 2 Tag erzeugen bzw. auf

    production-Branch mergen 3 Auf Produktions-Server anmelden 4 Vom VCS aktualisieren 5 Deployment laufen lassen 6 Tests laufen lassen 7 Prozesse neustarten Wolfgang Schnerring Werkzeugkiste 01.11.2012 42 / 45
  52. Deployment 1-Click-Deployment def pull(): remote(’hg pull −u’) def deploy(): remote(’bin/buildout’)

    def test(): remote(’bin/test’) def restart(): remote(’etc/init.d/myproduct−app1 restart’) def remote(command): return fabric.api.sudo( (’cd %s && ’ + command) % SERVICE_DIR, user=SERVICE_USER) Wolfgang Schnerring Werkzeugkiste 01.11.2012 43 / 45
  53. Zusammenfassung Uncle Sam sagt I want YOU to use eggs!

    I want YOU to use virtualenv! I want YOU to pin your versions! Wolfgang Schnerring Werkzeugkiste 01.11.2012 44 / 45
  54. Gibt es Fragen? http://www.flickr.com/photos/zakh/337938498 by zakh