summaryrefslogtreecommitdiff
diff options
authorMartin Packman <martin@zegami.com>2018-08-23 18:02:51 +0100
committerMartin Packman <martin@zegami.com>2018-08-23 18:02:51 +0100
commitf1aec5c421d4090cc42aa9a52d5afc913914a595 (patch)
tree045693bd4a8d78f8d610df34cb4c70ec84e4317c
parent0723f59efe376b2d0c6ec20fa61931c02af166c5 (diff)
Complete-ish presentation on typingHEADmaster
Cut flow for lightning speed.
-rw-r--r--css/theme/zegami.css16
-rw-r--r--index.html324
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;
diff --git a/index.html b/index.html
index b3b7043..680002d 100644
--- a/index.html
+++ b/index.html
@@ -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 &lt;$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 &lt;$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: &lt;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>