Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Francois Marier: External dependencies in web apps: system libs are not that scary

Francois Marier: External dependencies in web apps: system libs are not that scary

= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
Francois Marier:
External dependencies in web apps: system libs are not that scary
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
@ Kiwi PyCon 2014 - Saturday, 13 Sep 2014 - Track 2
http://kiwi.pycon.org/

**Audience level**

Intermediate

**Description**

Going to production is very different from setting up a development environment. We have great tools like pip and virtualenv for the latter but they lead to maintenance anti-patterns when they are used for production deployments. We don't "pip install apache" and instead leverage the QA and integration work of distro developers, so why not rely on distros for more than just the base system?

**Abstract**

Today's web applications often have a lot of external dependencies. Start off with a basic framework, sprinkle a couple of handy plugins or python modules and finish with a generous serving of JavaScript front-end libraries.

What you end up is a gigantic mess of code from different sources which follow very different release schedules and policies. Language-specific package managers can automate much of the dependency resolution and package installation, but you're on your own in terms of integration and quality assurance. Also, the minute you start distributing someone else's code with your project, you become responsible for the security of that external code.

You could of course decide to avoid the problem by writing it all yourself from scratch. Realistically though, you're not likely to go past the stage of a toy WSGI app using that approach because it's a lot of work.

This talk will examine the decision that the Libravatar [1] project made to outsource much of its maintenance burden to the distro by using system packages for almost everything.

[1] https://www.libravatar.org/

**YouTube**

https://www.youtube.com/watch?v=wfDhGAMPS1g

New Zealand Python User Group

September 13, 2014
Tweet

More Decks by New Zealand Python User Group

Other Decks in Programming

Transcript

  1. External dependencies in web apps system libs are not that

    scary François Marier @fmarier mozilla
  2. $ ls vendor/packages/ amqplib anyjson BeautifulSoup beautifulsoup4 bleach celery decorator

    distribute Django django-assets django-authopenid django-celery django-debug-toolbar django-extensions django-inplaceedit django-invitation django-kombu django-model-utils django-picklefield django-registration django-reversion django-tastypie django-voting django-webtest dj-database-url docutils feedparser gdata ghettoq html2text html5lib importlib Jinja2 jsmin kombu markupsafe mechanize mimeparse mock odict ordereddict pygeoip Pygments python-dateutil python-memcached python-mimeparse python-openid python-otp python-patch pytz PyYaml requests scrapy sessionprofile six south sphinx sqlparse staticgenerator twill twisted typecheck unicodecsv unittest-xml-reporting webob webtest whoosh zope.interface
  3. [email protected] ├── [email protected] ├─┬ [email protected] │ ├─┬ [email protected] │ │

    ├── [email protected] │ │ └─┬ [email protected] │ │ └── [email protected] │ ├─┬ [email protected] │ │ ├── [email protected] │ │ └── [email protected] │ ├─┬ [email protected] │ │ ├── [email protected] │ │ ├── [email protected] │ │ └── [email protected] │ ├─┬ [email protected] │ │ ├── [email protected] │ │ ├── [email protected] │ │ ├── [email protected] │ │ └── [email protected] │ ├── [email protected] │ ├─┬ [email protected] │ │ └─┬ [email protected] │ │ ├── [email protected] │ │ ├── [email protected] │ │ ├── [email protected] │ │ └── [email protected] │ ├─┬ [email protected] │ │ └── [email protected] │ ├─┬ [email protected] │ │ ├─┬ [email protected] │ │ │ ├── [email protected] │ │ │ └─┬ [email protected] │ │ │ └── [email protected] │ │ ├── [email protected] │ │ ├── [email protected] │ │ └─┬ [email protected] │ │ ├── [email protected] │ │ └── [email protected] │ ├── [email protected] │ ├── [email protected] │ └─┬ [email protected] │ └── [email protected] ├─┬ [email protected] │ └── [email protected] ├─┬ [email protected] │ └── [email protected] ├── [email protected] ├─┬ [email protected] │ │ ├── [email protected] │ │ ├── [email protected] │ │ ├─┬ [email protected] │ │ │ ├── [email protected] │ │ │ ├─┬ [email protected] │ │ │ │ └── [email protected] │ │ │ ├─┬ [email protected] │ │ │ │ └─┬ [email protected] │ │ │ │ └─┬ [email protected] │ │ │ │ ├── [email protected] │ │ │ │ └── [email protected] │ │ │ └─┬ [email protected] │ │ │ ├─┬ [email protected] │ │ │ │ ├── [email protected] │ │ │ │ └── [email protected] │ │ │ ├─┬ [email protected] │ │ │ │ └── [email protected] │ │ │ └─┬ [email protected] │ │ │ ├─┬ [email protected] │ │ │ │ └── [email protected] │ │ │ └─┬ [email protected] │ │ │ └── [email protected] │ │ └─┬ [email protected] │ │ ├── [email protected] │ │ └── [email protected] │ ├─┬ [email protected] │ │ └── [email protected] │ └─┬ [email protected] │ ├── [email protected] │ └── [email protected] ├── [email protected] ├─┬ [email protected] │ ├─┬ [email protected] │ │ └─┬ [email protected] │ │ ├── [email protected] │ │ ├── [email protected] │ │ ├─┬ [email protected] │ │ │ ├── [email protected] │ │ │ └── [email protected] │ │ └── [email protected] │ ├── [email protected] │ ├─┬ [email protected] │ │ ├── [email protected] │ │ └── [email protected] │ ├── shelljs @0.1.4 ├─┬ [email protected] │ ├─┬ [email protected] │ │ ├─┬ [email protected] │ │ │ └── [email protected] │ │ ├── follow-redirects@ │ │ ├── [email protected] │ │ ├── [email protected] │ │ └─┬ [email protected] │ │ ├── addressparser@0 │ │ └─┬ [email protected] │ │ └── iconv-lite@0. │ └─┬ [email protected] │ ├── [email protected] │ └── [email protected] ├─┬ [email protected] │ ├── [email protected] │ └── [email protected] ├── [email protected] ├─┬ [email protected] │ └── [email protected] ├── [email protected] ├─┬ [email protected] │ ├── [email protected] │ └─┬ [email protected] │ └── [email protected] ├─┬ [email protected] │ └── [email protected] ├── [email protected] ├── [email protected] ├── [email protected] ├── [email protected] ├─┬ [email protected] │ └── [email protected] ├── [email protected] ├─┬ [email protected] │ ├── [email protected] │ ├── [email protected] │ └─┬ [email protected] │ ├── [email protected] │ ├── [email protected] │ └─┬ [email protected] │ ├── [email protected] │ └── [email protected] ├── [email protected] └─┬ [email protected] ├── [email protected] ├── [email protected] ├── [email protected] ├── [email protected] ├─┬ [email protected] │ ├── [email protected] │ └── [email protected] ├─┬ [email protected] │ └─┬ [email protected] │ └── [email protected] ├─┬ [email protected] │ ├── [email protected] │ └── [email protected] ├── [email protected] ├─┬ [email protected] │ ├── [email protected] │ ├── [email protected] │ ├─┬ [email protected] │ │ └─┬ [email protected] │ │ └── [email protected] │ ├─┬ [email protected] │ │ ├── [email protected] │ │ ├── [email protected] │ │ └── [email protected] │ └── [email protected] ├── [email protected] ├── [email protected] ├── [email protected] ├─┬ [email protected] │ ├── [email protected] │ ├─┬ [email protected] │ │ └── [email protected] │ └── [email protected] ├─┬ [email protected] │ ├─┬ [email protected] │ │ └── [email protected] │ ├── [email protected] │ └── [email protected] ├── [email protected] ├── [email protected] ├─┬ [email protected] │ ├── [email protected] │ ├── [email protected] │ └── [email protected] ├── [email protected] ├── [email protected] ├── [email protected] ├─┬ [email protected] │ ├── [email protected] │ ├─┬ [email protected] │ │ ├─┬ [email protected] │ │ │ ├── [email protected] │ │ │ └─┬ [email protected] │ │ │ └── [email protected]
  4. [email protected] ├── [email protected] ├─┬ [email protected] │ ├─┬ [email protected] │ │

    ├── [email protected] │ │ └─┬ [email protected] │ │ └── [email protected] │ ├─┬ [email protected] │ │ ├── [email protected] │ │ └── [email protected] │ ├─┬ [email protected] │ │ ├── [email protected] │ │ ├── [email protected] │ │ └── [email protected] │ ├─┬ [email protected] │ │ ├── [email protected] │ │ ├── [email protected] │ │ ├── [email protected] │ │ └── [email protected] │ ├── [email protected] │ ├─┬ [email protected] │ │ └─┬ [email protected] │ │ ├── [email protected] │ │ ├── [email protected] │ │ ├── [email protected] │ │ └── [email protected] │ ├─┬ [email protected] │ │ └── [email protected] │ ├─┬ [email protected] │ │ ├─┬ [email protected] │ │ │ ├── [email protected] │ │ │ └─┬ [email protected] │ │ │ └── [email protected] │ │ ├── [email protected] │ │ ├── [email protected] │ │ └─┬ [email protected] │ │ ├── [email protected] │ │ └── [email protected] │ ├── [email protected] │ ├── [email protected] │ └─┬ [email protected] │ └── [email protected] ├─┬ [email protected] │ └── [email protected] ├─┬ [email protected] │ └── [email protected] ├── [email protected] ├─┬ [email protected] │ │ ├── [email protected] │ │ ├── [email protected] │ │ ├─┬ [email protected] │ │ │ ├── [email protected] │ │ │ ├─┬ [email protected] │ │ │ │ └── [email protected] │ │ │ ├─┬ [email protected] │ │ │ │ └─┬ [email protected] │ │ │ │ └─┬ [email protected] │ │ │ │ ├── [email protected] │ │ │ │ └── [email protected] │ │ │ └─┬ [email protected] │ │ │ ├─┬ [email protected] │ │ │ │ ├── [email protected] │ │ │ │ └── [email protected] │ │ │ ├─┬ [email protected] │ │ │ │ └── [email protected] │ │ │ └─┬ [email protected] │ │ │ ├─┬ [email protected] │ │ │ │ └── [email protected] │ │ │ └─┬ [email protected] │ │ │ └── [email protected] │ │ └─┬ [email protected] │ │ ├── [email protected] │ │ └── [email protected] │ ├─┬ [email protected] │ │ └── [email protected] │ └─┬ [email protected] │ ├── [email protected] │ └── [email protected] ├── [email protected] ├─┬ [email protected] │ ├─┬ [email protected] │ │ └─┬ [email protected] │ │ ├── [email protected] │ │ ├── [email protected] │ │ ├─┬ [email protected] │ │ │ ├── [email protected] │ │ │ └── [email protected] │ │ └── [email protected] │ ├── [email protected] │ ├─┬ [email protected] │ │ ├── [email protected] │ │ └── [email protected] │ ├── shelljs @0.1.4 ├─┬ [email protected] │ ├─┬ [email protected] │ │ ├─┬ [email protected] │ │ │ └── [email protected] │ │ ├── follow-redirects@ │ │ ├── [email protected] │ │ ├── [email protected] │ │ └─┬ [email protected] │ │ ├── addressparser@0 │ │ └─┬ [email protected] │ │ └── iconv-lite@0. │ └─┬ [email protected] │ ├── [email protected] │ └── [email protected] ├─┬ [email protected] │ ├── [email protected] │ └── [email protected] ├── [email protected] ├─┬ [email protected] │ └── [email protected] ├── [email protected] ├─┬ [email protected] │ ├── [email protected] │ └─┬ [email protected] │ └── [email protected] ├─┬ [email protected] │ └── [email protected] ├── [email protected] ├── [email protected] ├── [email protected] ├── [email protected] ├─┬ [email protected] │ └── [email protected] ├── [email protected] ├─┬ [email protected] │ ├── [email protected] │ ├── [email protected] │ └─┬ [email protected] │ ├── [email protected] │ ├── [email protected] │ └─┬ [email protected] │ ├── [email protected] │ └── [email protected] ├── [email protected] └─┬ [email protected] ├── [email protected] ├── [email protected] ├── [email protected] ├── [email protected] ├─┬ [email protected] │ ├── [email protected] │ └── [email protected] ├─┬ [email protected] │ └─┬ [email protected] │ └── [email protected] ├─┬ [email protected] │ ├── [email protected] │ └── [email protected] ├── [email protected] ├─┬ [email protected] │ ├── [email protected] │ ├── [email protected] │ ├─┬ [email protected] │ │ └─┬ [email protected] │ │ └── [email protected] │ ├─┬ [email protected] │ │ ├── [email protected] │ │ ├── [email protected] │ │ └── [email protected] │ └── [email protected] ├── [email protected] ├── [email protected] ├── [email protected] ├─┬ [email protected] │ ├── [email protected] │ ├─┬ [email protected] │ │ └── [email protected] │ └── [email protected] ├─┬ [email protected] │ ├─┬ [email protected] │ │ └── [email protected] │ ├── [email protected] │ └── [email protected] ├── [email protected] ├── [email protected] ├─┬ [email protected] │ ├── [email protected] │ ├── [email protected] │ └── [email protected] ├── [email protected] ├── [email protected] ├── [email protected] ├─┬ [email protected] │ ├── [email protected] │ ├─┬ [email protected] │ │ ├─┬ [email protected] │ │ │ ├── [email protected] │ │ │ └─┬ [email protected] │ │ │ └── [email protected]
  5. [email protected] ├── [email protected] ├─┬ [email protected] │ ├─┬ [email protected] │ │

    ├── [email protected] │ │ └─┬ [email protected] │ │ └── [email protected] │ ├─┬ [email protected] │ │ ├── [email protected] │ │ └── [email protected] │ ├─┬ [email protected] │ │ ├── [email protected] │ │ ├── [email protected] │ │ └── [email protected] │ ├─┬ [email protected] │ │ ├── [email protected] │ │ ├── [email protected] │ │ ├── [email protected] │ │ └── [email protected] │ ├── [email protected] │ ├─┬ [email protected] │ │ └─┬ [email protected] │ │ ├── [email protected] │ │ ├── [email protected] │ │ ├── [email protected] │ │ └── [email protected] │ ├─┬ [email protected] │ │ └── [email protected] │ ├─┬ [email protected] │ │ ├─┬ [email protected] │ │ │ ├── [email protected] │ │ │ └─┬ [email protected] │ │ │ └── [email protected] │ │ ├── [email protected] │ │ ├── [email protected] │ │ └─┬ [email protected] │ │ ├── [email protected] │ │ └── [email protected] │ ├── [email protected] │ ├── [email protected] │ └─┬ [email protected] │ └── [email protected] ├─┬ [email protected] │ └── [email protected] ├─┬ [email protected] │ └── [email protected] ├── [email protected] ├─┬ [email protected] │ │ ├── [email protected] │ │ ├── [email protected] │ │ ├─┬ [email protected] │ │ │ ├── [email protected] │ │ │ ├─┬ [email protected] │ │ │ │ └── [email protected] │ │ │ ├─┬ [email protected] │ │ │ │ └─┬ [email protected] │ │ │ │ └─┬ [email protected] │ │ │ │ ├── [email protected] │ │ │ │ └── [email protected] │ │ │ └─┬ [email protected] │ │ │ ├─┬ [email protected] │ │ │ │ ├── [email protected] │ │ │ │ └── [email protected] │ │ │ ├─┬ [email protected] │ │ │ │ └── [email protected] │ │ │ └─┬ [email protected] │ │ │ ├─┬ [email protected] │ │ │ │ └── [email protected] │ │ │ └─┬ [email protected] │ │ │ └── [email protected] │ │ └─┬ [email protected] │ │ ├── [email protected] │ │ └── [email protected] │ ├─┬ [email protected] │ │ └── [email protected] │ └─┬ [email protected] │ ├── [email protected] │ └── [email protected] ├── [email protected] ├─┬ [email protected] │ ├─┬ [email protected] │ │ └─┬ [email protected] │ │ ├── [email protected] │ │ ├── [email protected] │ │ ├─┬ [email protected] │ │ │ ├── [email protected] │ │ │ └── [email protected] │ │ └── [email protected] │ ├── [email protected] │ ├─┬ [email protected] │ │ ├── [email protected] │ │ └── [email protected] │ ├── shelljs @0.1.4 ├─┬ [email protected] │ ├─┬ [email protected] │ │ ├─┬ [email protected] │ │ │ └── [email protected] │ │ ├── follow-redirects@ │ │ ├── [email protected] │ │ ├── [email protected] │ │ └─┬ [email protected] │ │ ├── addressparser@0 │ │ └─┬ [email protected] │ │ └── iconv-lite@0. │ └─┬ [email protected] │ ├── [email protected] │ └── [email protected] ├─┬ [email protected] │ ├── [email protected] │ └── [email protected] ├── [email protected] ├─┬ [email protected] │ └── [email protected] ├── [email protected] ├─┬ [email protected] │ ├── [email protected] │ └─┬ [email protected] │ └── [email protected] ├─┬ [email protected] │ └── [email protected] ├── [email protected] ├── [email protected] ├── [email protected] ├── [email protected] ├─┬ [email protected] │ └── [email protected] ├── [email protected] ├─┬ [email protected] │ ├── [email protected] │ ├── [email protected] │ └─┬ [email protected] │ ├── [email protected] │ ├── [email protected] │ └─┬ [email protected] │ ├── [email protected] │ └── [email protected] ├── [email protected] └─┬ [email protected] ├── [email protected] ├── [email protected] ├── [email protected] ├── [email protected] ├─┬ [email protected] │ ├── [email protected] │ └── [email protected] ├─┬ [email protected] │ └─┬ [email protected] │ └── [email protected] ├─┬ [email protected] │ ├── [email protected] │ └── [email protected] ├── [email protected] ├─┬ [email protected] │ ├── [email protected] │ ├── [email protected] │ ├─┬ [email protected] │ │ └─┬ [email protected] │ │ └── [email protected] │ ├─┬ [email protected] │ │ ├── [email protected] │ │ ├── [email protected] │ │ └── [email protected] │ └── [email protected] ├── [email protected] ├── [email protected] ├── [email protected] ├─┬ [email protected] │ ├── [email protected] │ ├─┬ [email protected] │ │ └── [email protected] │ └── [email protected] ├─┬ [email protected] │ ├─┬ [email protected] │ │ └── [email protected] │ ├── [email protected] │ └── [email protected] ├── [email protected] ├── [email protected] ├─┬ [email protected] │ ├── [email protected] │ ├── [email protected] │ └── [email protected] ├── [email protected] ├── [email protected] ├── [email protected] ├─┬ [email protected] │ ├── [email protected] │ ├─┬ [email protected] │ │ ├─┬ [email protected] │ │ │ ├── [email protected] │ │ │ └─┬ [email protected] │ │ │ └── [email protected] 1.4.4 1.2.4 1.1.7 1.5.2
  6. www

  7. $ dig SRV _avatars._tcp.fmarier.org ; <<>> DiG 9.9.5-4-Debian <<>> SRV

    _avatars._tcp.fmarier.org ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 48289 ;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 4096 ;; QUESTION SECTION: ;_avatars._tcp.fmarier.org. IN SRV ;; ANSWER SECTION: _avatars._tcp.fmarier.org. 3600 IN SRV 1 0 80 fmarier.org. ;; Query time: 137 msec ;; SERVER: 192.168.1.1#53(192.168.1.1) ;; WHEN: Sat Aug 16 14:45:04 EDT 2014 ;; MSG SIZE rcvd: 85
  8. only use Python libraries that are packaged for Debian only

    use the version from the latest Debian release rules 1. 2.
  9. $ apt-cache search ^python- | grep ^python | wc -l

    2248 $ apt-cache search ^python3- | grep ^python | wc -l 656
  10. apticron report [Sat, 23 Aug 2014 10:11:08 +0000] ================================================= apticron

    has detected that some packages need upgrading on: husavik [ 162.x.x.x 10.x.x.x 2001::37f0 ] [ 162.x.x.x 2001::37f0 ] The following packages are currently pending an upgrade: python-django 1.4.5-1+deb7u8 =================================================
  11. [email protected] ├── [email protected] ├─┬ [email protected] │ ├─┬ [email protected] │ │

    ├── [email protected] │ │ └─┬ [email protected] │ │ └── [email protected] │ ├─┬ [email protected] │ │ ├── [email protected] │ │ └── [email protected] │ ├─┬ [email protected] │ │ ├── [email protected] │ │ ├── [email protected] │ │ └── [email protected] │ ├─┬ [email protected] │ │ ├── [email protected] │ │ ├── [email protected] │ │ ├── [email protected] │ │ └── [email protected] │ ├── [email protected] │ ├─┬ [email protected] │ │ └─┬ [email protected] │ │ ├── [email protected] │ │ ├── [email protected] │ │ ├── [email protected] │ │ └── [email protected] │ ├─┬ [email protected] │ │ └── [email protected] │ ├─┬ [email protected] │ │ ├─┬ [email protected] │ │ │ ├── [email protected] │ │ │ └─┬ [email protected] │ │ │ └── [email protected] │ │ ├── [email protected] │ │ ├── [email protected] │ │ └─┬ [email protected] │ │ ├── [email protected] │ │ └── [email protected] │ ├── [email protected] │ ├── [email protected] │ └─┬ [email protected] │ └── [email protected] ├─┬ [email protected] │ └── [email protected] ├─┬ [email protected] │ └── [email protected] ├── [email protected] ├─┬ [email protected] │ │ ├── [email protected] │ │ ├── [email protected] │ │ ├─┬ [email protected] │ │ │ ├── [email protected] │ │ │ ├─┬ [email protected] │ │ │ │ └── [email protected] │ │ │ ├─┬ [email protected] │ │ │ │ └─┬ [email protected] │ │ │ │ └─┬ [email protected] │ │ │ │ ├── [email protected] │ │ │ │ └── [email protected] │ │ │ └─┬ [email protected] │ │ │ ├─┬ [email protected] │ │ │ │ ├── [email protected] │ │ │ │ └── [email protected] │ │ │ ├─┬ [email protected] │ │ │ │ └── [email protected] │ │ │ └─┬ [email protected] │ │ │ ├─┬ [email protected] │ │ │ │ └── [email protected] │ │ │ └─┬ [email protected] │ │ │ └── [email protected] │ │ └─┬ [email protected] │ │ ├── [email protected] │ │ └── [email protected] │ ├─┬ [email protected] │ │ └── [email protected] │ └─┬ [email protected] │ ├── [email protected] │ └── [email protected] ├── [email protected] ├─┬ [email protected] │ ├─┬ [email protected] │ │ └─┬ [email protected] │ │ ├── [email protected] │ │ ├── [email protected] │ │ ├─┬ [email protected] │ │ │ ├── [email protected] │ │ │ └── [email protected] │ │ └── [email protected] │ ├── [email protected] │ ├─┬ [email protected] │ │ ├── [email protected] │ │ └── [email protected] │ ├── shelljs @0.1.4 ├─┬ [email protected] │ ├─┬ [email protected] │ │ ├─┬ [email protected] │ │ │ └── [email protected] │ │ ├── follow-redirects@ │ │ ├── [email protected] │ │ ├── [email protected] │ │ └─┬ [email protected] │ │ ├── addressparser@0 │ │ └─┬ [email protected] │ │ └── iconv-lite@0. │ └─┬ [email protected] │ ├── [email protected] │ └── [email protected] ├─┬ [email protected] │ ├── [email protected] │ └── [email protected] ├── [email protected] ├─┬ [email protected] │ └── [email protected] ├── [email protected] ├─┬ [email protected] │ ├── [email protected] │ └─┬ [email protected] │ └── [email protected] ├─┬ [email protected] │ └── [email protected] ├── [email protected] ├── [email protected] ├── [email protected] ├── [email protected] ├─┬ [email protected] │ └── [email protected] ├── [email protected] ├─┬ [email protected] │ ├── [email protected] │ ├── [email protected] │ └─┬ [email protected] │ ├── [email protected] │ ├── [email protected] │ └─┬ [email protected] │ ├── [email protected] │ └── [email protected] ├── [email protected] └─┬ [email protected] ├── [email protected] ├── [email protected] ├── [email protected] ├── [email protected] ├─┬ [email protected] │ ├── [email protected] │ └── [email protected] ├─┬ [email protected] │ └─┬ [email protected] │ └── [email protected] ├─┬ [email protected] │ ├── [email protected] │ └── [email protected] ├── [email protected] ├─┬ [email protected] │ ├── [email protected] │ ├── [email protected] │ ├─┬ [email protected] │ │ └─┬ [email protected] │ │ └── [email protected] │ ├─┬ [email protected] │ │ ├── [email protected] │ │ ├── [email protected] │ │ └── [email protected] │ └── [email protected] ├── [email protected] ├── [email protected] ├── [email protected] ├─┬ [email protected] │ ├── [email protected] │ ├─┬ [email protected] │ │ └── [email protected] │ └── [email protected] ├─┬ [email protected] │ ├─┬ [email protected] │ │ └── [email protected] │ ├── [email protected] │ └── [email protected] ├── [email protected] ├── [email protected] ├─┬ [email protected] │ ├── [email protected] │ ├── [email protected] │ └── [email protected] ├── [email protected] ├── [email protected] ├── [email protected] ├─┬ [email protected] │ ├── [email protected] │ ├─┬ [email protected] │ │ ├─┬ [email protected] │ │ │ ├── [email protected] │ │ │ └─┬ [email protected] │ │ │ └── [email protected]
  12. © 2014 François Marier <[email protected]> This work is licensed under

    a Creative Commons Attribution-ShareAlike 4.0 License. Questions?