├── Gemfile ├── Gemfile.lock ├── Makefile ├── README.md ├── config.ru ├── custom.css ├── python-for-humans ├── 0_intro.md ├── 1_content.md ├── 2_outro.md └── ext │ ├── dont-panic.jpeg │ ├── heroku.png │ └── moo.png └── showoff.json /Gemfile: -------------------------------------------------------------------------------- 1 | source :rubygems 2 | gem 'bluecloth' 3 | gem 'nokogiri' 4 | gem 'showoff' 5 | gem 'gli' 6 | gem 'heroku' 7 | -------------------------------------------------------------------------------- /Gemfile.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: http://rubygems.org/ 3 | specs: 4 | addressable (2.2.6) 5 | blankslate (2.1.2.4) 6 | bluecloth (2.1.0) 7 | gli (1.3.3) 8 | heroku (2.8.5) 9 | launchy (>= 0.3.2) 10 | rest-client (~> 1.6.1) 11 | rubyzip 12 | term-ansicolor (~> 1.0.5) 13 | json (1.6.1) 14 | launchy (2.0.5) 15 | addressable (~> 2.2.6) 16 | mime-types (1.16) 17 | nokogiri (1.5.0) 18 | parslet (1.2.3) 19 | blankslate (~> 2.0) 20 | rack (1.3.4) 21 | rack-protection (1.1.4) 22 | rack 23 | rest-client (1.6.7) 24 | mime-types (>= 1.16) 25 | rubyzip (0.9.4) 26 | showoff (0.7.0) 27 | bluecloth 28 | gli (>= 1.3.2) 29 | json 30 | nokogiri 31 | parslet 32 | sinatra 33 | sinatra (1.3.1) 34 | rack (~> 1.3, >= 1.3.4) 35 | rack-protection (~> 1.1, >= 1.1.2) 36 | tilt (~> 1.3, >= 1.3.3) 37 | term-ansicolor (1.0.6) 38 | tilt (1.3.3) 39 | 40 | PLATFORMS 41 | ruby 42 | 43 | DEPENDENCIES 44 | bluecloth 45 | gli 46 | heroku 47 | nokogiri 48 | showoff 49 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | run: 2 | showoff serve -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Python for Humans 2 | 3 | ## tl;dr 4 | 5 | - Publish Modules for Humans 6 | - Help with Python-Guide 7 | 8 | ## Slides 9 | 10 | [Available Online](http://python-for-humans.heroku.com) 11 | 12 | ## Audio 13 | 14 | - [MP3](http://cl.ly/1h0y0k2F0D2K3F3V3J16/PyCodeConf2011_-_Kenneth_Reitz_01.mp3) 15 | - [OGG](http://codeconf.s3.amazonaws.com/2011/pycodeconf/talks/PyCodeConf2011%20-%20Kenneth%20Reitz.ogg) 16 | - [M4A](http://codeconf.s3.amazonaws.com/2011/pycodeconf/talks/PyCodeConf2011%20-%20Kenneth%20Reitz.m4a) 17 | 18 | 19 | ## Powered By 20 | 21 | - [schacon/showoff](https://github.com/schacon/showoff) 22 | - [Heroku](https://heroku.com) 23 | - [Octocats](http://octodex.github.com/) 24 | - [Redbull](http://www.redbull.com/) 25 | 26 | ## Special Thanks 27 | 28 | - GitHub 29 | - The dozens of developers that helped form the list of woes. -------------------------------------------------------------------------------- /config.ru: -------------------------------------------------------------------------------- 1 | require "showoff" 2 | run ShowOff.new 3 | -------------------------------------------------------------------------------- /custom.css: -------------------------------------------------------------------------------- 1 | .github { 2 | font-family: 'Collegiate', helvetica, sans-serif; 3 | } 4 | 5 | .bigger { 6 | font-size: 2.3em; 7 | } 8 | 9 | .red { 10 | color: red; 11 | } 12 | 13 | .top { 14 | margin-top: 50px !important; 15 | } 16 | -------------------------------------------------------------------------------- /python-for-humans/0_intro.md: -------------------------------------------------------------------------------- 1 | !SLIDE bullets 2 | 3 | * API Design and Pragmatic Python 4 | * Python is a Ghetto 5 | * Python is a Cancer 6 | * Python Has Jumped the Shark 7 | 8 | !SLIDE 9 | # Hi. 10 | 11 | 12 | !SLIDE github bigger 13 | github.com/kennethreitz 14 | 15 | !SLIDE 16 | 17 | ## I PYTHON! 18 | 19 | !SLIDE 20 | 21 | ![Heroku™](ext/heroku.png) 22 | 23 | !SLIDE github 24 | 25 | ## The GitHub Reflog. 26 | 27 | !SLIDE 28 | 29 | ## I OPEN SOURCE! 30 | 31 | !SLIDE incremental bullets small 32 | 33 | * Requests: HTTP for Humans 34 | * Tablib: Pythonic Tabular Datasets 35 | * Legit: Awesome Git Interface 36 | * OSX-GCC-Installer: Angers Lawyers 37 | * Clint: Command-line Interface Tools 38 | * Envoy: Subprocess for Humans 39 | * Httpbin.org: Requests & Response Service 40 | * ~197 Others 41 | -------------------------------------------------------------------------------- /python-for-humans/1_content.md: -------------------------------------------------------------------------------- 1 | !SLIDE 2 | # Python for Humans 3 | (or something to that effect) 4 | 5 | 6 | !SLIDE 7 | # Philosophy. 8 | 9 | 10 | !SLIDE 11 | # We share a dark past: 12 | 13 | Perl, Java, PHP, ColdFusion, Classic ASP, *&c*. 14 | 15 | 16 | !SLIDE code 17 | # The Zen of Python. 18 | >>> import this 19 | 20 | 21 | !SLIDE 22 | ## Beautiful is better than ugly. 23 | 24 | 25 | !SLIDE 26 | ## Explicit is better than implicit. 27 | 28 | 29 | !SLIDE 30 | ## Simple is better than complex. 31 | 32 | 33 | !SLIDE 34 | ## Complex is better than complicated. 35 | 36 | 37 | !SLIDE incremental bullets 38 | ### If the implementation is hard to explain, it's a bad idea. 39 | 40 | - (except pypy) 41 | 42 | 43 | !SLIDE 44 | ### There should be one—and preferably only one—obvious way to do it. 45 | 46 | 47 | 48 | !SLIDE 49 | # Welcome to paradise. 50 | 51 | !SLIDE 52 | # Welcome to paradise. 53 | 54 | !SLIDE red bigger 55 | # LIES! 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | !SLIDE 69 | # Let's mess around. 70 | 71 | ### Maybe play with the GitHub API? 72 | 73 | 74 | !SLIDE small code 75 | 76 | ## We know Ruby. 77 | 78 | @@@ ruby 79 | require 'net/http' 80 | require 'uri' 81 | 82 | uri = URI.parse('https://api.github.com/user') 83 | 84 | http = Net::HTTP.new(uri.host, uri.port) 85 | http.use_ssl = true 86 | 87 | req = Net::HTTP::Get.new(uri.request_uri) 88 | req.basic_auth('username', 'password') 89 | 90 | r = http.request(req) 91 | 92 | puts r 93 | 94 | !SLIDE 95 | # Python's net/http? 96 | 97 | ## http/url/lib/2 98 | 99 | (better in py3) 100 | 101 | !SLIDE 102 | 103 | # Several hours later... 104 | 105 | !SLIDE smaller code execute 106 | 107 | @@@ python 108 | import urllib2 109 | 110 | gh_url = 'https://api.github.com/user' 111 | 112 | req = urllib2.Request(gh_url) 113 | 114 | password_manager = urllib2.HTTPPasswordMgrWithDefaultRealm() 115 | password_manager.add_password(None, gh_url, 'user', 'pass') 116 | 117 | auth_manager = urllib2.HTTPBasicAuthHandler(password_manager) 118 | opener = urllib2.build_opener(auth_manager) 119 | 120 | urllib2.install_opener(opener) 121 | 122 | handler = urllib2.urlopen(req) 123 | 124 | print handler.read() 125 | 126 | !SLIDE smaller code execute 127 | #I lied — there's more! 128 | 129 | @@@ python 130 | 131 | import re 132 | 133 | class HTTPForcedBasicAuthHandler(HTTPBasicAuthHandler): 134 | 135 | auth_header = 'Authorization' 136 | rx = re.compile('(?:.*,)*[ \t]*([^ \t]+)[ \t]+' 137 | 'realm=(["\'])(.*?)\\2', re.I) 138 | 139 | def __init__(self, *args, **kwargs): 140 | HTTPBasicAuthHandler.__init__(self, *args, **kwargs) 141 | 142 | def http_error_401(self, req, fp, code, msg, headers): 143 | url = req.get_full_url() 144 | response = self._http_error_auth_reqed( 145 | 'www-authenticate', url, req, headers) 146 | self.reset_retry_count() 147 | return response 148 | 149 | http_error_404 = http_error_401 150 | 151 | !SLIDE 152 | # Admit it. 153 | 154 | If this was you, you'd leave Python and never come back. 155 | 156 | 157 | 158 | !SLIDE bullets incremental 159 | # The Problem. 160 | 161 | - Unclear which module to use in the first place. 162 | - Prognosis seems to be urllib2, but the docs are terrible. 163 | - Worst API ever. 164 | 165 | 166 | !SLIDE bullets incremental smaller 167 | # This is a serious problem. 168 | 169 | - HTTP should be as simple as the print statement. 170 | 171 | 172 | !SLIDE bullets incremental 173 | # The Solution is Simple. 174 | 175 | - Build elegant tools to perform these tasks. 176 | 177 | 178 | !SLIDE 179 | ## Python needs more Pragmatic Packages. 180 | 181 | !SLIDE dark 182 | 183 | ## pra•gmat•ic |pragˈmatik|, *adj*: 184 | Dealing with things sensibly and realistically in a way that is 185 | based on practical rather than theoretical considerations. 186 | 187 | !SLIDE 188 | # Python for Humans 189 | 190 | 191 | !SLIDE incremental 192 | # Let's Break it down. 193 | 194 | What *is* HTTP at its core? 195 | 196 | - A small set of methods with consistent parameters. 197 | - HEAD, GET, PUSH, POST, PUT, PATCH, DELETE 198 | - They all accept headers, url parameters, and form data. 199 | 200 | 201 | !SLIDE incremental 202 | # Urllib2 is Toxic. 203 | 204 | - Heavily over-engineered. 205 | - Abolishes most of PEP20. 206 | - Docs are impossible to read. 207 | - HTTP is simple. Urllib2 is absolute garbage. 208 | - Scares people away. 209 | 210 | 211 | !SLIDE 212 | # Enter Requests. 213 | 214 | 215 | !SLIDE 216 | # HTTP for Humans. 217 | 218 | 219 | !SLIDE 220 | 221 | @@@ python 222 | import requests 223 | 224 | url = 'https://api.github.com/user' 225 | auth = ('username', 'password') 226 | 227 | r = requests.get(url, auth=auth) 228 | print r.content 229 | 230 | 231 | !SLIDE incremental 232 | # Achievement Unlocked! 233 | 234 | - A small set of methods with consistent parameters. 235 | - HEAD, GET, PUSH, POST, PUT, PATCH, DELETE 236 | - They all accept headers, url parameters, and form data. 237 | 238 | !SLIDE incremental 239 | # Do this. 240 | 241 | 242 | !SLIDE 243 | # The Litmus Test 244 | If you have to refer to the documentation every time you use a module, 245 | find (or build) a new module. 246 | 247 | !SLIDE 248 | # Fit the 90% Use Case. 249 | 250 | !SLIDE 251 | # The API is all that matters. 252 | 253 | 254 | ## Everything else is secondary. 255 | 256 | 257 | !SLIDE incremental bullets 258 | # I Mean ***Everything***. 259 | 260 | - Features. 261 | - Efficiency. 262 | - Performance. 263 | - Corner-cases. 264 | 265 | 266 | !SLIDE incremental bullets 267 | # Pivot. 268 | 269 | - At first, Requests was far from powerful. 270 | - Deeply resonated with people. 271 | - Features grew over time, API never compromised. 272 | 273 | !SLIDE incremental bullets 274 | # Today 275 | - Cookies, sessions, content-iteration, decompression, file uploads, async i/o, keep-alive, callback hooks, proxies, *&c*. 276 | - 7th most–watched Python GitHub project. 277 | - 65,000+ downloads from PyPi. 278 | - Twitter, Library of Congress, Readability, etc. 279 | 280 | 281 | !SLIDE incremental bullets 282 | # Cool Story, Bro. 283 | 284 | - We need this. 285 | - We want this. 286 | - It's worth your time. 287 | - It's worth everyone's time. 288 | 289 | 290 | !SLIDE bullets incremental 291 | # Subprocess 292 | 293 | - Powerful 294 | - Effective 295 | - (Second) Worst API ever. 296 | - Documentation is severely lacking. 297 | 298 | 299 | !SLIDE bullets 300 | # (Proposed) Solution. 301 | 302 | ![Moo](ext/moo.png) 303 | 304 | 305 | 306 | !SLIDE 307 | # File and System Operations 308 | - sys | shutils | os | os.path | io 309 | - Really difficult to run external commands. 310 | - This blocks dev+ops folks from adopting Python. 311 | 312 | 313 | 314 | 315 | !SLIDE 316 | # Barriers to Entry 317 | 318 | 319 | !SLIDE incremental 320 | # Installing Python. 321 | 322 | Decisions, decisions. 323 | 324 | * Download installer from python.org? 325 | * 32bit or 64bit? 326 | * Build from source? 327 | * If so, Unix or framework build? 328 | 329 | !SLIDE 330 | ### There should be one—and preferably only one—obvious way to do it. 331 | 332 | 333 | !SLIDE 334 | # XML 335 | 336 | - `etree` is terrible. 337 | - `lxml` is awesome, but difficult to install. 338 | 339 | 340 | !SLIDE incremental 341 | # Packaging and Dependencies 342 | - Pip or easy_install? 343 | - Setuptools isn't included with python? 344 | - Distribute? Why? 345 | - No easy_uninstall? 346 | - Broken `setup.py`s 347 | - "Released" packages not in the Cheeseshop 348 | 349 | !SLIDE incremental 350 | # Date[time]s. 351 | - Which module to use? 352 | - Timezones 353 | - The stdlib can generate but not parse ISO8601 dates 354 | 355 | !SLIDE 356 | # Unicode. 357 | 358 | !SLIDE 359 | # Testing. 360 | 361 | !SLIDE incremental 362 | # Installing Dependencies 363 | 364 | * python-mysql 365 | * PIL 366 | * mod_wsgi 367 | 368 | 369 | 370 | !SLIDE 371 | ## Unless there's an explicit requirement, 372 | ## a student should never be exposed to urllib2. 373 | 374 | # No excuses. 375 | 376 | 377 | 378 | 379 | 380 | 381 | 382 | 383 | 384 | !SLIDE 385 | ## The Hitchhiker's Guide to Python 386 | 387 | http://python-guide.org 388 | 389 | !SLIDE code top 390 | ![DON'T PANIC](ext/dont-panic.jpeg) 391 | 392 | 393 | !SLIDE bullets incremental 394 | - A guidebook for newcomers. 395 | - A reference for seasoned veterans. 396 | 397 | !SLIDE small bullets incremental 398 | # Best Practices 399 | 400 | - Will recommend **distribute**, **pip**, and **virtualenv** out of the box. 401 | Explicit directions for setup on every major OS. 402 | - Instill a resistance to `doctest` 403 | - Teach `datetime.utcnow()` 404 | 405 | 406 | !SLIDE 407 | # There's only one rule. 408 | 409 | !SLIDE 410 | > There should be one—and preferably only one—obvious way to do it. 411 | 412 | 413 | !SLIDE 414 | # This Solves 415 | 416 | - Makes Python more accessible, lowering the barrier to entry. 417 | - Great reference guide for seasoned veterans. 418 | - Practice what we preach. 419 | 420 | 421 | !SLIDE red 422 | # THE MANIFESTO 423 | 424 | 425 | !SLIDE 426 | # Simplify terrible APIs. 427 | 428 | !SLIDE 429 | # Document our best-practices. 430 | 431 | -------------------------------------------------------------------------------- /python-for-humans/2_outro.md: -------------------------------------------------------------------------------- 1 | !SLIDE 2 | ## Questions? 3 | 4 | 5 | !SLIDE github bigger 6 | [github.com/kennethreitz](http://github.com/kennethreitz) 7 | -------------------------------------------------------------------------------- /python-for-humans/ext/dont-panic.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/not-kennethreitz/python-for-humans/a9dd19fa85396ebdb86aab3a553df8030270ec71/python-for-humans/ext/dont-panic.jpeg -------------------------------------------------------------------------------- /python-for-humans/ext/heroku.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/not-kennethreitz/python-for-humans/a9dd19fa85396ebdb86aab3a553df8030270ec71/python-for-humans/ext/heroku.png -------------------------------------------------------------------------------- /python-for-humans/ext/moo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/not-kennethreitz/python-for-humans/a9dd19fa85396ebdb86aab3a553df8030270ec71/python-for-humans/ext/moo.png -------------------------------------------------------------------------------- /showoff.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Python for Humans", 3 | "sections": 4 | [ 5 | {"section": "python-for-humans"} 6 | ] 7 | } 8 | --------------------------------------------------------------------------------