diff options
| author | Martin Packman <martin@zegami.com> | 2018-08-23 18:02:51 +0100 |
|---|---|---|
| committer | Martin Packman <martin@zegami.com> | 2018-08-23 18:02:51 +0100 |
| commit | f1aec5c421d4090cc42aa9a52d5afc913914a595 (patch) | |
| tree | 045693bd4a8d78f8d610df34cb4c70ec84e4317c | |
| parent | 0723f59efe376b2d0c6ec20fa61931c02af166c5 (diff) | |
Cut flow for lightning speed.
| -rw-r--r-- | css/theme/zegami.css | 16 | ||||
| -rw-r--r-- | index.html | 324 |
2 files changed, 330 insertions, 10 deletions
diff --git a/css/theme/zegami.css b/css/theme/zegami.css index cf23277..2e965ea 100644 --- a/css/theme/zegami.css +++ b/css/theme/zegami.css @@ -58,7 +58,7 @@ body { word-wrap: break-word; } .reveal h1 { - font-size: 3.5em; } + font-size: 2.5em; } .reveal h2 { font-size: 2.0em; } @@ -158,8 +158,13 @@ body { text-align: left; font-family: "Ubuntu Mono", monospace; line-height: 1; - word-wrap: break-word; - box-shadow: 0px 0px 6px rgba(0, 0, 0, 0.3); } + word-wrap: break-word; } + +.reveal pre.page { + background: white; + padding: 2em; + font-size: 0.55em; +} .reveal code { font-family: "Ubuntu Mono", monospace; } @@ -172,11 +177,6 @@ body { font-size: 0.55em; word-wrap: normal; } -.reveal pre code.lang-shell { - font-size: 1em; - min-height: 400px; -} - .reveal table { margin: auto; border-collapse: collapse; @@ -25,14 +25,334 @@ <div class="reveal"> <div class="slides"> <section> -<h1>Typing? Flow?</h1> -<h4>comparing static type checking frameworks for Python and Javascript</h4> +<h1>Optional[Typing]</h1> +<h4>exploring Python type checking</h4> <p>Martin Packman</p> <p><a href="mailto:martin@zegami.com">martin@zegami.com</a></p> <aside class="notes"> <p>Hi.</p> </aside> </section> + <section> +<h2>Example app</h2> +<aside class="notes"> +<p>Need some example code to check.</p> +</aside> + </section> + <section> +<pre><code class="lang-python hljs"> +#!/usr/bin/env python + +"""Simple server application using WSGI with a subtle bug.""" + + +def app(environ, start_response): + start_response('200 OK', [('Content-Type', 'text/plain')]) + return 'Hello Oxford Python meetup!\n' * 100 + + +if __name__ == '__main__': + from wsgiref.simple_server import make_server + make_server('localhost', 8080, app).serve_forever() + +</code></pre> +<aside class="notes"> +<p>Simple hello web application, and we're a little exuberant so 100 hellos.</p> +</aside> + </section> + <section> +<pre><code class="lang-shell hljs"> +$ chmod 755 server.py +$ ./server.py + +</code></pre> +<pre class="fragment page"> +Hello Oxford Python meetup! +Hello Oxford Python meetup! +Hello Oxford Python meetup! +... +Hello Oxford Python meetup! +</pre> +<aside class="notes"> +<p>Run it, load in browser, see our message 100 times.</p> +</aside> + </section> + <section> +<h2>Done?</h2> +<aside class="notes"> +<p>Anything else? Could write a test? Maybe benchmark?</p> +</aside> + </section> + <section> +<pre><code class="lang-shell hljs"> +$ ab -n100 http://localhost:8080/ +</code><code class="fragment lang-shell hljs" +>This is ApacheBench, Version 2.3 <$Revision: 1807734 $> +... +Requests per second: 82.59 [#/sec] (mean) + +</code></pre> +<aside class="notes"> +<p>Benchmark, 80 req/sec, fine? Python is just slow, right?</p> +</aside> + </section> + <section> +<h2>Done?</h2> +<aside class="notes"> +<p>Hint, should be 10x faster. Function signature wrong, try using mypy. Or strace.</p> +</aside> + </section> + <section> +<pre><code class="lang-shell hljs"> +$ strace -I1 ./server.py +</code><code class="fragment lang-shell hljs" +>... +sendto(4, "HTTP/1.0 200 OK\r\n", 17, 0, NULL, 0) = 17 +sendto(4, "Date: Thu, 23 Aug 2018 01:17:46 "..., 37, 0, NULL, 0) = 37 +sendto(4, "Server: WSGIServer/0.1 Python/2."..., 41, 0, NULL, 0) = 41 +sendto(4, "Content-Type: text/plain\r\n\r\n", 28, 0, NULL, 0) = 28 +sendto(4, "H", 1, 0, NULL, 0) = 1 +sendto(4, "e", 1, 0, NULL, 0) = 1 +sendto(4, "l", 1, 0, NULL, 0) = 1 +sendto(4, "l", 1, 0, NULL, 0) = 1 +sendto(4, "o", 1, 0, NULL, 0) = 1 +sendto(4, " ", 1, 0, NULL, 0) = 1 +sendto(4, "O", 1, 0, NULL, 0) = 1 +sendto(4, "x", 1, 0, NULL, 0) = 1 +... +</code></pre> +<aside class="notes"> +<p>Trying out strace approach. One byte at a time to the socket?</p> +</aside> + </section> + <section> +<pre><code class="lang-python hljs"> +def app(environ, start_response): + start_response('200 OK', [('Content-Type', 'text/plain')]) + return ['Hello Oxford Python meetup!\n' * 100] + +</code></pre> +<aside class="notes"> +<p>Return value if string is iterated over, so just make single item list.</p> +</aside> + </section> + <section> +<pre><code class="lang-shell hljs"> +$ ab -n100 http://localhost:8080/ +</code><code class="fragment lang-shell hljs" +>This is ApacheBench, Version 2.3 <$Revision: 1807734 $> +... +Requests per second: 786.49 [#/sec] (mean) + +</code></pre> +<aside class="notes"> +<p>Rebenchmark, much better, order of magnitude faster.</p> +</aside> + </section> + <section> +<h3>Installing mypy</h3> +<pre><code class="lang-shell hljs"> +$ pip3 install mypy --user + +</code></pre> +<aside class="notes"> +<p>Lots of ways, but is in pypi so use pip or similar. I installed from git.</p> +</aside> + </section> + <section> +<h3>mypy.ini</h3> +<pre><code class="lang-ini hljs"> +[mypy] +python_version = 2.7 + +</code></pre> +<aside class="notes"> +<p>Lots of config options, for now just need to specify a Python version.</p> +</aside> + </section> + <section> +<pre><code class="lang-shell hljs" data-noescape=""> +$ mypy server.py <span class="fragment">-v</span> +</code><code class="fragment lang-shell hljs"> +LOG: Mypy version 0.630+dev-402d734c4b8ceffdc04478eb49fc196dd2a3a785 +... +LOG: Loaded graph with 19 nodes (0.028 sec) +LOG: Found 14 SCCs; largest has 6 nodes +LOG: 14 fresh SCCs (19 nodes) left in queue (and will remain unprocessed) +LOG: Build finished in 0.029 seconds with 0 modules, and 0 errors + +</code></pre> +<aside class="notes"> +<p>Run... no output? Add verbose. Seems it thinks there are no errors?</p> +</aside> + </section> + <section> +<pre><code class="lang-diff hljs"> +- make_server('localhost', 8080, app).serve_forever() ++ make_server('localhost', '8080', app).serve_forever() + +</code></pre> +<pre class="fragment"><code class="lang-shell hljs"> +server.py:13: error: No overload variant of "make_server" matches argument types "str", "str", "Callable[[Any, Any], Any]" +server.py:13: note: Possible overload variant: +server.py:13: note: def make_server(host: str, port: int, app: Callable[[Dict[unicode, Any], StartResponse], Iterable[str]], *, handler_class: Type[WSGIRequestHandler] = ...) -> WSGIServer +server.py:13: note: <1 more non-matching overload not shown> + +</code></pre> +<aside class="notes"> +<p>Try breaking. Works! Or rather, fails. Hint in first line Callable/Any. Is a lot to take it, but we'll get used to this.</p> +</aside> + </section> + <section> +<pre><code class="lang-python hljs"> +from typing import Any, Callable + + +def app(environ: Any, start_response: Callable) -> str: + start_response('200 OK', [('Content-Type', 'text/plain')]) + return 'Hello Oxford Python meetup!\n' * 100 + +</code></pre> +<pre class="fragment"><code class="lang-shell hljs"> +server.py:8: error: invalid syntax + +</code></pre> +<aside class="notes"> +<p>Read PEP add some annotations, run. Whoops, we're using Python 2.</p> +</aside> + </section> + <section> +<pre><code class="lang-python hljs"> +from typing import Any, Callable + + +def app(environ, start_response): + # type: (Any, Callable) -> str + start_response('200 OK', [('Content-Type', 'text/plain')]) + return 'Hello Oxford Python meetup!\n' * 100 + +</code></pre> +<div class="fragment"> +<p>The typing import is still required.</p> +<pre><code class="lang-shell hljs"> +server.py:5: error: Name 'Any' is not defined +server.py:5: error: Name 'Callable' is not defined + +</code></pre> +<aside class="notes"> +<p>Okay, have comment syntax that works for Python 2. Passes again.</p> +</aside> + </section> + <section> +<pre><code class="lang-python hljs"> +from typing import TYPE_CHECKING + + +if TYPE_CHECKING: + from wsgiref.types import WSGIApplication + + +def app(environ, start_response): + # type: WSGIApplication + start_response('200 OK', [('Content-Type', 'text/plain')]) + return 'Hello Oxford Python meetup!\n' * 100 + + +</code></pre> +<pre class="fragment"><code class="lang-shell hljs"> +server.py:12: error: syntax error in type comment + +</code></pre> +<aside class="notes"> +<p>Defintions exist in typeshed, just reuse? Can't quite do this.</p> +</aside> + </section> + <section> +<pre><code class="lang-python hljs"> +from typing import TYPE_CHECKING + + +if TYPE_CHECKING: + from wsgiref.types import StartResponse, WSGIEnvironment + + +def app(environ, start_response): + # type: (WSGIEnvironment, StartResponse) -> str + start_response('200 OK', [('Content-Type', 'text/plain')]) + return 'Hello Oxford Python meetup!\n' * 100 + +</code></pre> +<aside class="notes"> +<p>Can get arguments though. Passes again! No bug found.</p> +</aside> + </section> + <section> +<pre><code class="lang-ini hljs"> +[mypy] +python_version = 3.6 + +</code></pre> +<aside class="notes"> +<p>Lets try using Python 3 instead. Change mypy.ini config then port app.</p> +</aside> + </section> + <section> +<pre><code class="lang-python hljs"> +from typing import TYPE_CHECKING + + +if TYPE_CHECKING: + from wsgiref.types import StartResponse, WSGIEnvironment + + +def app( + environ: 'WSGIEnvironment', + start_response: 'StartResponse', + ) -> bytes: + start_response('200 OK', [('Content-Type', 'text/plain')]) + return b'Hello Oxford Python meetup!\n' * 100 + +</code></pre> +<pre class="fragment"><code class="lang-shell hljs"> +server.py:19: error: Argument 3 to "make_server" has incompatible type "Callable[[Dict[str, Any], StartResponse], bytes]"; expected "Callable[[Dict[str, Any], StartResponse], Iterable[bytes]]" + +</code></pre> +<aside class="notes"> +<p>Ported. Changed return value and declaration to bytes, use inline type annotations, but as strings due to guard.</p> +</aside> + </section> + <section> +<pre><code class="lang-python hljs"> +from typing import Iterable, TYPE_CHECKING + + +if TYPE_CHECKING: + from wsgiref.types import StartResponse, WSGIEnvironment + + +def app( + environ: 'WSGIEnvironment', + start_response: 'StartResponse', + ) -> Iterable[bytes]: + start_response('200 OK', [('Content-Type', 'text/plain')]) + return [b'Hello Oxford Python meetup!\n' * 100] + + +</code></pre> +<aside class="notes"> +<p>Fixed! Right declaration, no errors.</p> +</aside> + </section> + <section> +<h3>Teasers</h3> +<ul class="fragment"> +<li>Why problem caught on Python 3 only?</li> +<li>Why use a development version of mypy?</li> +</ul> +<aside class="notes"> +<p>Things to think about and ask me later.</p> +</aside> + </section> </div> <script src="lib/js/head.min.js"></script> |
