├── .hgignore ├── .htaccess ├── about.html ├── advanced-iterators.html ├── blank.html ├── case-study-porting-chardet-to-python-3.html ├── colophon.html ├── comprehensions.html ├── dip2 ├── dip3.css ├── diveintopython3.org ├── epio.ini ├── examples ├── .htaccess ├── alphametics.py ├── alphameticstest.py ├── basic-pretty.json ├── basic.json ├── beauregard.jpg ├── chinese.txt ├── customserializer.py ├── entry-pretty.json ├── entry.json ├── entry.pickle ├── favorite-people.txt ├── feed-broken.xml ├── feed-ns0.xml ├── feed.xml ├── fibonacci.py ├── fibonacci2.py ├── humansize.py ├── oneline.py ├── pickleversion.py ├── plural1.py ├── plural2.py ├── plural3.py ├── plural4-rules.txt ├── plural4.py ├── plural5-rules.txt ├── plural5.py ├── plural6-rules.txt ├── plural6.py ├── pluraltest1.py ├── pluraltest2.py ├── pluraltest3.py ├── pluraltest4.py ├── pluraltest5.py ├── pluraltest6.py ├── regression.py ├── roman1.py ├── roman10.py ├── roman2.py ├── roman3.py ├── roman4.py ├── roman5.py ├── roman6.py ├── roman7.py ├── roman8.py ├── roman9.py ├── romantest1.py ├── romantest10.py ├── romantest2.py ├── romantest3.py ├── romantest4.py ├── romantest5.py ├── romantest6.py ├── romantest7.py ├── romantest8.py ├── romantest9.py └── stdout.py ├── files.html ├── generators.html ├── http-web-services.html ├── i ├── .htaccess ├── cover.jpg ├── identica-deleted.png ├── identica-screenshot.png ├── mac-install-0-dmg-contents.png ├── mac-install-1-welcome.png ├── mac-install-10-application-folder.png ├── mac-install-2-information.png ├── mac-install-3-license.png ├── mac-install-4-license-dialog.png ├── mac-install-5-standard-install.png ├── mac-install-6-custom-install.png ├── mac-install-7-admin-password.png ├── mac-install-8-progress.png ├── mac-install-9-succeeded.png ├── mac-interactive-shell.png ├── mac-pythonlauncher.png ├── openclipart.org_media_files_Selanit_8331.png ├── openclipart.org_media_files_johnny_automatic_5154.png ├── openclipart.org_media_files_johnny_automatic_5261.png ├── ubu-install-0-add-remove-programs.png ├── ubu-install-1-all-open-source-applications.png ├── ubu-install-2-search-python-3.png ├── ubu-install-3-select-python-3.png ├── ubu-install-4-select-idle.png ├── ubu-install-5-apply-changes.png ├── ubu-install-6-download-progress.png ├── ubu-install-7-install-progress.png ├── ubu-install-8-success.png ├── ubu-interactive-shell.png ├── win-install-0-security-warning.png ├── win-install-1-all-users-or-just-me.png ├── win-install-2-destination-directory.png ├── win-install-3-customize.png ├── win-install-3a-disk-usage.png ├── win-install-3b-test-suite.png ├── win-install-4-copying.png ├── win-install-5-finish.png └── win-interactive-shell.png ├── images-original ├── mac-install-0-dmg-contents.png ├── mac-install-1-welcome.png ├── mac-install-10-application-folder.png ├── mac-install-2-information.png ├── mac-install-3-license.png ├── mac-install-4-license-dialog.png ├── mac-install-5-standard-install.png ├── mac-install-6-custom-install.png ├── mac-install-7-admin-password.png ├── mac-install-8-progress.png ├── mac-install-9-succeeded.png ├── mac-interactive-shell.png ├── mac-pythonlauncher.png ├── ubu-install-0-add-remove-programs.png ├── ubu-install-1-all-open-source-applications.png ├── ubu-install-2-search-python-3.png ├── ubu-install-3-select-python-3.png ├── ubu-install-4-select-idle.png ├── ubu-install-5-apply-changes.png ├── ubu-install-6-download-progress.png ├── ubu-install-7-install-progress.png ├── ubu-install-8-success.png ├── ubu-interactive-shell.png ├── win-install-0-security-warning.bmp ├── win-install-1-all-users-or-just-me.bmp ├── win-install-2-destination-directory.bmp ├── win-install-3-customize.bmp ├── win-install-3a-disk-usage.bmp ├── win-install-3b-test-suite.bmp ├── win-install-4-copying.bmp ├── win-install-5-finish.bmp └── win-interactive-shell.bmp ├── index.html ├── installing-python.html ├── iterators.html ├── j ├── .htaccess ├── dip3.js ├── ga.js ├── html5.js ├── jquery.js ├── jquery.min.js ├── jslint.js ├── plug.html └── prettify.js ├── layout.css ├── mobile.css ├── native-datatypes.html ├── notes.txt ├── packaging.html ├── porting-code-to-python-3-with-2to3.html ├── prince.css ├── print.css ├── publish ├── refactoring.html ├── regular-expressions.html ├── robots.txt ├── serializing.html ├── special-method-names.html ├── strings.html ├── table-of-contents.html ├── troubleshooting.html ├── unit-testing.html ├── util ├── buildtoc.py ├── compiler.jar ├── flatten.py ├── htmlminimizer.py ├── lesscss.py ├── single-footer.html ├── single-header.html ├── single-header2.html ├── validate.py └── yuicompressor-2.4.2.jar ├── whats-new.html ├── where-to-go-from-here.html ├── xml.html └── your-first-python-program.html /.hgignore: -------------------------------------------------------------------------------- 1 | syntax: glob 2 | *.pyc 3 | build 4 | grid28.gif 5 | copyedit 6 | proofs 7 | -------------------------------------------------------------------------------- /.htaccess: -------------------------------------------------------------------------------- 1 | FileETag MTime Size 2 | 3 | SetEnv dont-vary 4 | -------------------------------------------------------------------------------- /about.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | About the book - Dive Into Python 3 4 | 5 | 12 | 13 | 14 | 15 |
 
16 |

You are here: Home Dive Into Python 3 17 |

About The Book

18 |
19 |
20 |

Dive Into Python 3 comprises original prose and graphics licensed under the CC-BY-SA-3.0 license. Illustrations from the Open Clip Art Library are public domain. 21 |

The chardet library is licensed under the LGPL 2.1 or later. The alphametics solver is a port of Raymond Hettinger’s version, released under the MIT license. Several chapters contain code from the Python standard library, released under the PSF License 2.0. All other original code is licensed under the MIT license. 22 |

The online edition uses jQuery, released under the MIT and GPL licenses. Color syntax highlighting is provided by prettify.js, other parsing code is adapted from highlighter.js; both are released under the Apache License 2.0. 23 |

Corrections and feedback to mark@diveintomark.org or on Github. 24 |

25 |
26 |

© 2001–11 Mark Pilgrim 27 | 28 | -------------------------------------------------------------------------------- /blank.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | This page intentionally left blank - Dive Into Python 3 5 | 6 | 9 | 10 | 11 | 12 |

This page intentionally left blank. 13 | -------------------------------------------------------------------------------- /colophon.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Colophon - Dive Into Python 3 5 | 6 | 10 | 11 | 12 | 13 |

  
14 |

You are here: Home Dive Into Python 3 15 |

Colophon

16 |
17 |

Je n’ai fait celle-ci plus longue que parce que je n’ai pas eu le loisir de la faire plus courte.
(I would have written a shorter letter, but I did not have the time.)
Blaise Pascal 18 |

19 |

  20 |

Diving In

21 |

This book, like all books, was a labor of love. Oh sure, I got paid the medium-sized bucks for it, but nobody writes technical books for the money. And since this book is available on the web as well as on paper, I spent a lot of time fiddling with webby stuff when I should have been writing. 22 | 23 |

[typewriter] 24 | 25 |

The online edition loads as efficiently as possible. Efficiency never happens by accident; I spent many hours making it so. Perhaps too many hours. Yes, almost certainly too many hours. Never underestimate the depths to which a procrastinating writer will sink. 26 | 27 |

I won’t bore you with all the details. Wait, yes — I will bore you with all the details. But here’s the short version. 28 | 29 |

    30 |
  1. HTML is minimized, then served compressed. 31 |
  2. Scripts and stylesheets are minimized by YUI Compressor (and also served compressed). 32 |
  3. Scripts are combined to reduce HTTP requests. 33 |
  4. Stylesheets are combined and inlined to reduce HTTP requests. 34 |
  5. Unused CSS selectors and properties are removed on a page-by-page basis with a little help from pyquery. 35 |
  6. HTTP caching and other server-side options are optimized based on advice from YSlow and Page Speed. 36 |
  7. Pages use Unicode characters in place of images wherever possible. 37 |
  8. Images are optimized with OptiPNG. 38 |
  9. The entire book was lovingly hand-authored in HTML 5 to avoid markup cruft. 39 |
40 | 41 |

⁂ 42 | 43 |

Typography

44 | 45 |

vertical rhythm, best available ampersand, curly quotes/apostrophes, other stuff from webtypography.net 46 | 47 |

⁂ 48 | 49 |

Graphics

50 | 51 |

Unicode, callouts, font-family issues on Windows 52 | 53 |

⁂ 54 | 55 |

Performance

56 | 57 |

"Dive Into History 2009 edition", minimizing CSS + JS + HTML, inline CSS, optimizing images 58 | 59 |

⁂ 60 | 61 |

Fun stuff

62 | 63 |

Quotes, constrained writing(?), PapayaWhip 64 | 65 |

⁂ 66 | 67 |

Further Reading

68 | 69 | 83 | 84 |

© 2001–11 Mark Pilgrim 85 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /diveintopython3.org: -------------------------------------------------------------------------------- 1 | * Installing Python 2 | * Your First Python Program 3 | ** TODO mention why from module import * is only allowed at module level 4 | * Native Datatypes 5 | * DONE Comprehensions 6 | ** List comprehensions 7 | ** Set comprehensions 8 | ** Dictionary comprehensions 9 | * Strings 10 | * Regular Expressions 11 | * Closures & Generators 12 | * Classes & Iterators 13 | * DONE 2nd draft Advanced Iterators 14 | SCHEDULED: <2009-07-15 Wed> CLOSED: [2009-07-15 Wed 20:57] 15 | * DONE 2nd draft Unit Testing 16 | * DONE 2nd draft Refactoring 17 | * DONE 1st draft Files 18 | SCHEDULED: <2009-07-16 Thu> CLOSED: [2009-07-19 Sun 15:26] 19 | ** Reading from text files 20 | *** Opening a file (to read) 21 | *** Character encoding 22 | *** File objects 23 | *** Closing a file 24 | **** Checking if a file is closed 25 | **** "with open(...) as file" pattern 26 | *** Reading data from a file one line at a time 27 | **** Line-endings 28 | ** Writing to text files 29 | *** Opening a file (to write) 30 | *** Character encoding again 31 | *** write(), writelines(), .writeable 32 | ** Handling I/O errors 33 | ** Binary files 34 | ** File-like objects 35 | ** Standard Input, Output, and Error 36 | ** Further reading 37 | * DONE 2nd draft XML 38 | * TODO 1st draft Serializing Python Objects 39 | * DONE 2nd draft HTTP Web Services 40 | CLOSED: [2009-07-15 Wed 20:57] 41 | * TODO 1st draft Threading & Multiprocessing 42 | * TODO 1st draft Packaging Python libraries 43 | * DONE 2nd draft Case Study: Porting chardet to Python 3 44 | * Where to go from here 45 | * DONE 2nd draft Porting Code to Python 3 with 2to3 46 | * DONE 2nd draft Special Method Names 47 | * Bits to add somewhere 48 | ** DONE section on tuples 49 | ** TODO section on dictionary views 50 | several dictionary methods return them 51 | they're dynamic 52 | they update when the dictionary changes 53 | ** TODO Decorators 54 | [[http://docs.python.org/3.1/whatsnew/3.1.html][@unittest.skipUnless(sys.platform.startswith("win"), "requires Windows")]] 55 | * Meta 56 | ** TODO generate HTML 57 | ** TODO generate PDF 58 | ** DONE all

 blocks without numbers should be marked class=nd
59 |    CLOSED: [2009-07-14 Tue 20:55]
60 | 


--------------------------------------------------------------------------------
/epio.ini:
--------------------------------------------------------------------------------
1 | [static]
2 | / = ./
3 | _directory_indexes = true
4 | 
5 | [wsgi]
6 | enabled = false


--------------------------------------------------------------------------------
/examples/.htaccess:
--------------------------------------------------------------------------------
 1 | AddType application/xml .xml
 2 | AddType text/plain .py
 3 | 
 4 | AddDefaultCharset utf-8
 5 | 
 6 | ExpiresActive On
 7 | ExpiresDefault "access plus 1 day"
 8 | 
 9 | FileETag MTime Size
10 | 
11 | SetOutputFilter DEFLATE
12 | 
13 | Header unset Vary
14 | Header add Vary Accept-Encoding
15 | 
16 | Redirect /examples/feed-302.xml http://diveintopython3.org/examples/feed.xml
17 | Redirect permanent /examples/feed-301.xml http://diveintopython3.org/examples/feed.xml
18 | 


--------------------------------------------------------------------------------
/examples/alphametics.py:
--------------------------------------------------------------------------------
 1 | '''Find solutions to alphametic equations.
 2 | 
 3 | >>> alphametics.solve('SEND + MORE == MONEY')
 4 | '9567 + 1085 == 10652'
 5 | '''
 6 | 
 7 | import re
 8 | import itertools
 9 | 
10 | def solve(puzzle):
11 |     words = re.findall('[A-Z]+', puzzle.upper())
12 |     unique_characters = set(''.join(words))
13 |     assert len(unique_characters) <= 10, 'Too many letters'
14 |     first_letters = {word[0] for word in words}
15 |     n = len(first_letters)
16 |     sorted_characters = ''.join(first_letters) + \
17 |         ''.join(unique_characters - first_letters)
18 |     characters = tuple(ord(c) for c in sorted_characters)
19 |     digits = tuple(ord(c) for c in '0123456789')
20 |     zero = digits[0]
21 |     for guess in itertools.permutations(digits, len(characters)):
22 |         if zero not in guess[:n]:
23 |             equation = puzzle.translate(dict(zip(characters, guess)))
24 |             if eval(equation):
25 |                 return equation
26 | 
27 | if __name__ == '__main__':
28 |     import sys
29 |     for puzzle in sys.argv[1:]:
30 |         print(puzzle)
31 |         solution = solve(puzzle)
32 |         if solution:
33 |             print(solution)
34 | 
35 | # Copyright (c) 2009, Raymond Hettinger, All rights reserved.
36 | # Ported to Python 3 and modified by Mark Pilgrim
37 | # original: http://code.activestate.com/recipes/576615/
38 | # 
39 | # Redistribution and use in source and binary forms, with or without modification,
40 | # are permitted provided that the following conditions are met:
41 | # 
42 | # * Redistributions of source code must retain the above copyright notice,
43 | #   this list of conditions and the following disclaimer.
44 | # * Redistributions in binary form must reproduce the above copyright notice,
45 | #   this list of conditions and the following disclaimer in the documentation
46 | #   and/or other materials provided with the distribution.
47 | # 
48 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS'
49 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
50 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
51 | # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
52 | # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
53 | # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
54 | # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
55 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
56 | # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
57 | # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
58 | # POSSIBILITY OF SUCH DAMAGE.
59 | 


--------------------------------------------------------------------------------
/examples/alphameticstest.py:
--------------------------------------------------------------------------------
 1 | from alphametics import solve
 2 | import unittest
 3 | 
 4 | class KnownValues(unittest.TestCase):
 5 |     def test_out(self):
 6 |         '''TO + GO == OUT'''
 7 |         self.assertEqual(solve('TO + GO == OUT'), '21 + 81 == 102')
 8 | 
 9 |     def test_too(self):
10 |         '''I + DID == TOO'''
11 |         self.assertEqual(solve('I + DID == TOO'), '9 + 191 == 200')
12 | 
13 |     def test_mom(self):
14 |         '''AS + A == MOM'''
15 |         self.assertEqual(solve('AS + A == MOM'), '92 + 9 == 101')
16 | 
17 |     def test_best(self):
18 |         '''HES + THE == BEST'''
19 |         self.assertEqual(solve('HES + THE == BEST'), '426 + 842 == 1268')
20 | 
21 |     def test_late(self):
22 |         '''NO + NO + TOO == LATE'''
23 |         self.assertEqual(solve('NO + NO + TOO == LATE'), '74 + 74 + 944 == 1092')
24 | 
25 |     def test_onze(self):
26 |         '''UN + UN + NEUF == ONZE'''
27 |         self.assertEqual(solve('UN + UN + NEUF == ONZE'), '81 + 81 + 1987 == 2149')
28 | 
29 |     def test_deux(self):
30 |         '''UN + DEUX + DEUX + DEUX + DEUX == NEUF'''
31 |         self.assertEqual(solve('UN + DEUX + DEUX + DEUX + DEUX == NEUF'), '25 + 1326 + 1326 + 1326 + 1326 == 5329')
32 | 
33 | if __name__ == '__main__':
34 |     unittest.main()
35 | 
36 | # Copyright (c) 2009, Mark Pilgrim, All rights reserved.
37 | # 
38 | # Redistribution and use in source and binary forms, with or without modification,
39 | # are permitted provided that the following conditions are met:
40 | # 
41 | # * Redistributions of source code must retain the above copyright notice,
42 | #   this list of conditions and the following disclaimer.
43 | # * Redistributions in binary form must reproduce the above copyright notice,
44 | #   this list of conditions and the following disclaimer in the documentation
45 | #   and/or other materials provided with the distribution.
46 | # 
47 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS'
48 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
49 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
50 | # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
51 | # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
52 | # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
53 | # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
54 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
55 | # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
56 | # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
57 | # POSSIBILITY OF SUCH DAMAGE.
58 | 


--------------------------------------------------------------------------------
/examples/basic-pretty.json:
--------------------------------------------------------------------------------
 1 | {
 2 |   "published": true, 
 3 |   "tags": [
 4 |     "diveintopython", 
 5 |     "docbook", 
 6 |     "html"
 7 |   ], 
 8 |   "comments_link": null, 
 9 |   "id": 256, 
10 |   "title": "Dive into history, 2009 edition"
11 | }


--------------------------------------------------------------------------------
/examples/basic.json:
--------------------------------------------------------------------------------
1 | {"published": true, "tags": ["diveintopython", "docbook", "html"], "comments_link": null, "id": 256, "title": "Dive into history, 2009 edition"}


--------------------------------------------------------------------------------
/examples/beauregard.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kennethreitz/dive-into-python3/67ef8e6df7adcafec77b8994ee4a79c59d625c45/examples/beauregard.jpg


--------------------------------------------------------------------------------
/examples/chinese.txt:
--------------------------------------------------------------------------------
1 | Dive Into Python 是为有经验的程序员编写的一本 Python 书。
2 | 


--------------------------------------------------------------------------------
/examples/customserializer.py:
--------------------------------------------------------------------------------
 1 | import pickle
 2 | import json
 3 | import time
 4 | 
 5 | def to_json(python_object):
 6 |     if isinstance(python_object, time.struct_time):
 7 |         return {'__class__': 'time.asctime',
 8 |                 '__value__': time.asctime(python_object)}
 9 |     if isinstance(python_object, bytes):
10 |         return {'__class__': 'bytes',
11 |                 '__value__': list(python_object)}
12 |     raise TypeError(repr(python_object) + ' is not JSON serializable')
13 | 
14 | def from_json(json_object):
15 |     if '__class__' in json_object:
16 |         if json_object['__class__'] == 'time.asctime':
17 |             return time.strptime(json_object['__value__'])
18 |         if json_object['__class__'] == 'bytes':
19 |             return bytes(json_object['__value__'])
20 |     return json_object
21 | 
22 | if __name__ == '__main__':
23 |     entry = {}
24 |     entry['title'] = 'Dive into history, 2009 edition'
25 |     entry['article_link'] = 'http://diveintomark.org/archives/2009/03/27/dive-into-history-2009-edition'
26 |     entry['comments_link'] = None
27 |     entry['internal_id'] = b'\xDE\xD5\xB4\xF8'
28 |     entry['tags'] = ('diveintopython', 'docbook', 'html')
29 |     entry['published'] = True
30 |     entry['published_date'] = time.strptime('Fri Mar 27 22:20:42 2009')
31 |     
32 |     with open('entry.pickle', 'wb') as f:
33 |         pickle.dump(entry, f)
34 | 
35 |     with open('entry.pickle', 'rb') as f:
36 |         entry2 = pickle.load(f)
37 | 
38 |     print(entry == entry2)
39 |     print(type(entry['tags']))
40 |     print(type(entry2['tags']))
41 | 
42 |     with open('entry.json', 'w', encoding='utf-8') as f:
43 |         json.dump(entry, f, default=to_json)
44 | 
45 |     with open('entry.json', 'r', encoding='utf-8') as f:
46 |         entry2 = json.load(f, object_hook=from_json)
47 | 
48 |     print(entry == entry2)
49 |     print(type(entry['tags']))
50 |     print(type(entry2['tags']))
51 | 


--------------------------------------------------------------------------------
/examples/entry-pretty.json:
--------------------------------------------------------------------------------
 1 | {
 2 |   "comments_link": null, 
 3 |   "internal_id": {
 4 |     "__class__": "bytes", 
 5 |     "__value__": [
 6 |       222, 
 7 |       213, 
 8 |       180, 
 9 |       248
10 |     ]
11 |   }, 
12 |   "title": "Dive into history, 2009 edition", 
13 |   "tags": [
14 |     "diveintopython", 
15 |     "docbook", 
16 |     "html"
17 |   ], 
18 |   "article_link": "http://diveintomark.org/archives/2009/03/27/dive-into-history-2009-edition", 
19 |   "published_date": {
20 |     "__class__": "time.asctime", 
21 |     "__value__": "Fri Mar 27 22:20:42 2009"
22 |   }, 
23 |   "published": true
24 | }


--------------------------------------------------------------------------------
/examples/entry.json:
--------------------------------------------------------------------------------
1 | {"published_date": {"__class__": "time.asctime", "__value__": "Fri Mar 27 22:20:42 2009"}, "comments_link": null, "internal_id": {"__class__": "bytes", "__value__": [222, 213, 180, 248]}, "tags": ["diveintopython", "docbook", "html"], "title": "Dive into history, 2009 edition", "article_link": "http://diveintomark.org/archives/2009/03/27/dive-into-history-2009-edition", "published": true}


--------------------------------------------------------------------------------
/examples/entry.pickle:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kennethreitz/dive-into-python3/67ef8e6df7adcafec77b8994ee4a79c59d625c45/examples/entry.pickle


--------------------------------------------------------------------------------
/examples/favorite-people.txt:
--------------------------------------------------------------------------------
 1 | Dora
 2 | Ethan
 3 | Wesley
 4 | John
 5 | Anne
 6 | Mike
 7 | Chris
 8 | Sarah
 9 | Alex
10 | Lizzie
11 | 


--------------------------------------------------------------------------------
/examples/feed-broken.xml:
--------------------------------------------------------------------------------
 1 | 
 2 | 
 3 |   dive into …
 4 |   currently between addictions
 5 |   tag:diveintomark.org,2001-07-29:/
 6 |   2009-03-27T21:56:07Z
 7 |   
 8 |   
 9 |     
10 |       Mark
11 |       http://diveintomark.org/
12 |     
13 |     Dive into history, 2009 edition
14 |     
16 |     tag:diveintomark.org,2009-03-27:/archives/20090327172042
17 |     2009-03-27T21:56:07Z
18 |     2009-03-27T17:20:42Z
19 |     
20 |     
21 |     
22 |     Putting an entire chapter on one page sounds
23 |       bloated, but consider this &mdash; my longest chapter so far
24 |       would be 75 printed pages, and it loads in under 5 seconds&hellip;
25 |       On dialup.
26 |   
27 |   
28 |     
29 |       Mark
30 |       http://diveintomark.org/
31 |     
32 |     Accessibility is a harsh mistress
33 |     
35 |     tag:diveintomark.org,2009-03-21:/archives/20090321200928
36 |     2009-03-22T01:05:37Z
37 |     2009-03-21T20:09:28Z
38 |     
39 |     The accessibility orthodoxy does not permit people to
40 |       question the value of features that are rarely useful and rarely used.
41 |   
42 |   
43 |     
44 |       Mark
45 |     
46 |     A gentle introduction to video encoding, part 1: container formats
47 |     
49 |     tag:diveintomark.org,2008-12-18:/archives/20081218155422
50 |     2009-01-11T19:39:22Z
51 |     2008-12-18T15:54:22Z
52 |     
53 |     
54 |     
55 |     
56 |     
57 |     
58 |     
59 |     
60 |     These notes will eventually become part of a
61 |       tech talk on video encoding.
62 |   
63 | 
64 | 


--------------------------------------------------------------------------------
/examples/feed-ns0.xml:
--------------------------------------------------------------------------------
 1 | 
 2 | 
 3 |   dive into mark
 4 |   currently between addictions
 5 |   tag:diveintomark.org,2001-07-29:/
 6 |   2009-03-27T21:56:07Z
 7 |   
 8 |   
 9 |     
10 |       Mark
11 |       http://diveintomark.org/
12 |     
13 |     Dive into history, 2009 edition
14 |     
16 |     tag:diveintomark.org,2009-03-27:/archives/20090327172042
17 |     2009-03-27T21:56:07Z
18 |     2009-03-27T17:20:42Z
19 |     
20 |     
21 |     
22 |     Putting an entire chapter on one page sounds
23 |       bloated, but consider this &mdash; my longest chapter so far
24 |       would be 75 printed pages, and it loads in under 5 seconds&hellip;
25 |       On dialup.
26 |   
27 |   
28 |     
29 |       Mark
30 |       http://diveintomark.org/
31 |     
32 |     Accessibility is a harsh mistress
33 |     
35 |     tag:diveintomark.org,2009-03-21:/archives/20090321200928
36 |     2009-03-22T01:05:37Z
37 |     2009-03-21T20:09:28Z
38 |     
39 |     The accessibility orthodoxy does not permit people to
40 |       question the value of features that are rarely useful and rarely used.
41 |   
42 |   
43 |     
44 |       Mark
45 |     
46 |     A gentle introduction to video encoding, part 1: container formats
47 |     
49 |     tag:diveintomark.org,2008-12-18:/archives/20081218155422
50 |     2009-01-11T19:39:22Z
51 |     2008-12-18T15:54:22Z
52 |     
53 |     
54 |     
55 |     
56 |     
57 |     
58 |     
59 |     
60 |     These notes will eventually become part of a
61 |       tech talk on video encoding.
62 |   
63 | 
64 | 


--------------------------------------------------------------------------------
/examples/feed.xml:
--------------------------------------------------------------------------------
 1 | 
 2 | 
 3 |   dive into mark
 4 |   currently between addictions
 5 |   tag:diveintomark.org,2001-07-29:/
 6 |   2009-03-27T21:56:07Z
 7 |   
 8 |   
 9 |     
10 |       Mark
11 |       http://diveintomark.org/
12 |     
13 |     Dive into history, 2009 edition
14 |     
16 |     tag:diveintomark.org,2009-03-27:/archives/20090327172042
17 |     2009-03-27T21:56:07Z
18 |     2009-03-27T17:20:42Z
19 |     
20 |     
21 |     
22 |     Putting an entire chapter on one page sounds
23 |       bloated, but consider this &mdash; my longest chapter so far
24 |       would be 75 printed pages, and it loads in under 5 seconds&hellip;
25 |       On dialup.
26 |   
27 |   
28 |     
29 |       Mark
30 |       http://diveintomark.org/
31 |     
32 |     Accessibility is a harsh mistress
33 |     
35 |     tag:diveintomark.org,2009-03-21:/archives/20090321200928
36 |     2009-03-22T01:05:37Z
37 |     2009-03-21T20:09:28Z
38 |     
39 |     The accessibility orthodoxy does not permit people to
40 |       question the value of features that are rarely useful and rarely used.
41 |   
42 |   
43 |     
44 |       Mark
45 |     
46 |     A gentle introduction to video encoding, part 1: container formats
47 |     
49 |     tag:diveintomark.org,2008-12-18:/archives/20081218155422
50 |     2009-01-11T19:39:22Z
51 |     2008-12-18T15:54:22Z
52 |     
53 |     
54 |     
55 |     
56 |     
57 |     
58 |     
59 |     
60 |     These notes will eventually become part of a
61 |       tech talk on video encoding.
62 |   
63 | 
64 | 


--------------------------------------------------------------------------------
/examples/fibonacci.py:
--------------------------------------------------------------------------------
 1 | '''Fibonacci generator'''
 2 | 
 3 | def fib(max):
 4 |     a, b = 0, 1
 5 |     while a < max:
 6 |         yield a
 7 |         a, b = b, a + b
 8 | 
 9 | # Copyright (c) 2009, Mark Pilgrim, All rights reserved.
10 | # 
11 | # Redistribution and use in source and binary forms, with or without modification,
12 | # are permitted provided that the following conditions are met:
13 | # 
14 | # * Redistributions of source code must retain the above copyright notice,
15 | #   this list of conditions and the following disclaimer.
16 | # * Redistributions in binary form must reproduce the above copyright notice,
17 | #   this list of conditions and the following disclaimer in the documentation
18 | #   and/or other materials provided with the distribution.
19 | # 
20 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS'
21 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 | # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
24 | # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 | # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 | # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 | # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 | # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 | # POSSIBILITY OF SUCH DAMAGE.
31 | 


--------------------------------------------------------------------------------
/examples/fibonacci2.py:
--------------------------------------------------------------------------------
 1 | '''Fibonacci iterator'''
 2 | 
 3 | class Fib:
 4 |     '''iterator that yields numbers in the Fibonacci sequence'''
 5 | 
 6 |     def __init__(self, max):
 7 |         self.max = max
 8 | 
 9 |     def __iter__(self):
10 |         self.a = 0
11 |         self.b = 1
12 |         return self
13 | 
14 |     def __next__(self):
15 |         fib = self.a
16 |         if fib > self.max:
17 |             raise StopIteration
18 |         self.a, self.b = self.b, self.a + self.b
19 |         return fib
20 | 
21 | # Copyright (c) 2009, Mark Pilgrim, All rights reserved.
22 | # 
23 | # Redistribution and use in source and binary forms, with or without modification,
24 | # are permitted provided that the following conditions are met:
25 | # 
26 | # * Redistributions of source code must retain the above copyright notice,
27 | #   this list of conditions and the following disclaimer.
28 | # * Redistributions in binary form must reproduce the above copyright notice,
29 | #   this list of conditions and the following disclaimer in the documentation
30 | #   and/or other materials provided with the distribution.
31 | # 
32 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS'
33 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
34 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
35 | # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
36 | # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
37 | # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
38 | # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
39 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
40 | # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
41 | # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42 | # POSSIBILITY OF SUCH DAMAGE.
43 | 


--------------------------------------------------------------------------------
/examples/humansize.py:
--------------------------------------------------------------------------------
 1 | '''Convert file sizes to human-readable form.
 2 | 
 3 | Available functions:
 4 | approximate_size(size, a_kilobyte_is_1024_bytes)
 5 |     takes a file size and returns a human-readable string
 6 | 
 7 | Examples:
 8 | >>> approximate_size(1024)
 9 | '1.0 KiB'
10 | >>> approximate_size(1000, False)
11 | '1.0 KB'
12 | 
13 | '''
14 | 
15 | SUFFIXES = {1000: ['KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'],
16 |             1024: ['KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB']}
17 | 
18 | def approximate_size(size, a_kilobyte_is_1024_bytes=True):
19 |     '''Convert a file size to human-readable form.
20 | 
21 |     Keyword arguments:
22 |     size -- file size in bytes
23 |     a_kilobyte_is_1024_bytes -- if True (default), use multiples of 1024
24 |                                 if False, use multiples of 1000
25 | 
26 |     Returns: string
27 | 
28 |     '''
29 |     if size < 0:
30 |         raise ValueError('number must be non-negative')
31 | 
32 |     multiple = 1024 if a_kilobyte_is_1024_bytes else 1000
33 |     for suffix in SUFFIXES[multiple]:
34 |         size /= multiple
35 |         if size < multiple:
36 |             return '{0:.1f} {1}'.format(size, suffix)
37 | 
38 |     raise ValueError('number too large')
39 | 
40 | if __name__ == '__main__':
41 |     print(approximate_size(1000000000000, False))
42 |     print(approximate_size(1000000000000))
43 | 
44 | # Copyright (c) 2009, Mark Pilgrim, All rights reserved.
45 | # 
46 | # Redistribution and use in source and binary forms, with or without modification,
47 | # are permitted provided that the following conditions are met:
48 | # 
49 | # * Redistributions of source code must retain the above copyright notice,
50 | #   this list of conditions and the following disclaimer.
51 | # * Redistributions in binary form must reproduce the above copyright notice,
52 | #   this list of conditions and the following disclaimer in the documentation
53 | #   and/or other materials provided with the distribution.
54 | # 
55 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS'
56 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
57 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
58 | # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
59 | # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
60 | # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
61 | # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
62 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
63 | # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
64 | # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
65 | # POSSIBILITY OF SUCH DAMAGE.
66 | 


--------------------------------------------------------------------------------
/examples/oneline.py:
--------------------------------------------------------------------------------
1 | line_number = 1
2 | with open('examples/favorite-people.txt', encoding='utf-8') as a_file:
3 |     for a_line in a_file:
4 |         print('{:>4} {}'.format(line_number, a_line.rstrip()))
5 |         line_number += 1
6 | 


--------------------------------------------------------------------------------
/examples/pickleversion.py:
--------------------------------------------------------------------------------
1 | import pickletools
2 | 
3 | def protocol_version(file_object):
4 |     maxproto = -1
5 |     for opcode, arg, pos in pickletools.genops(file_object):
6 |         maxproto = max(maxproto, opcode.proto)
7 |     return maxproto
8 | 
9 | 


--------------------------------------------------------------------------------
/examples/plural1.py:
--------------------------------------------------------------------------------
 1 | '''Pluralize English nouns (stage 1)
 2 | 
 3 | Command line usage:
 4 | $ python3 plural.py noun
 5 | nouns
 6 | '''
 7 | 
 8 | import re
 9 | 
10 | def plural(noun):
11 |     if re.search('[sxz]$', noun):
12 |         return re.sub('$', 'es', noun)
13 |     elif re.search('[^aeioudgkprt]h$', noun):
14 |         return re.sub('$', 'es', noun)
15 |     elif re.search('[^aeiou]y$', noun):
16 |         return re.sub('y$', 'ies', noun)
17 |     else:
18 |         return noun + 's'
19 | 
20 | if __name__ == '__main__':
21 |     import sys
22 |     if sys.argv[1:]:
23 |         print(plural(sys.argv[1]))
24 |     else:
25 |         print(__doc__)
26 | 
27 | # Copyright (c) 2009, Mark Pilgrim, All rights reserved.
28 | # 
29 | # Redistribution and use in source and binary forms, with or without modification,
30 | # are permitted provided that the following conditions are met:
31 | # 
32 | # * Redistributions of source code must retain the above copyright notice,
33 | #   this list of conditions and the following disclaimer.
34 | # * Redistributions in binary form must reproduce the above copyright notice,
35 | #   this list of conditions and the following disclaimer in the documentation
36 | #   and/or other materials provided with the distribution.
37 | # 
38 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS'
39 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
40 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
41 | # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
42 | # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
43 | # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
44 | # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
45 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
46 | # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
47 | # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
48 | # POSSIBILITY OF SUCH DAMAGE.
49 | 


--------------------------------------------------------------------------------
/examples/plural2.py:
--------------------------------------------------------------------------------
 1 | '''Pluralize English nouns (stage 2)
 2 | 
 3 | Command line usage:
 4 | $ python plural2.py noun
 5 | nouns
 6 | '''
 7 | 
 8 | import re
 9 | 
10 | def match_sxz(noun):
11 |     return re.search('[sxz]$', noun)
12 | 
13 | def apply_sxz(noun):
14 |     return re.sub('$', 'es', noun)
15 | 
16 | def match_h(noun):
17 |     return re.search('[^aeioudgkprt]h$', noun)
18 | 
19 | def apply_h(noun):
20 |     return re.sub('$', 'es', noun)
21 | 
22 | def match_y(noun):
23 |     return re.search('[^aeiou]y$', noun)
24 |         
25 | def apply_y(noun):
26 |     return re.sub('y$', 'ies', noun)
27 | 
28 | def match_default(noun):
29 |     return True
30 | 
31 | def apply_default(noun):
32 |     return noun + 's'
33 | 
34 | rules = ((match_sxz, apply_sxz),
35 |          (match_h, apply_h),
36 |          (match_y, apply_y),
37 |          (match_default, apply_default)
38 |          )
39 | 
40 | def plural(noun):
41 |     for matches_rule, apply_rule in rules:
42 |         if matches_rule(noun):
43 |             return apply_rule(noun)
44 | 
45 | if __name__ == '__main__':
46 |     import sys
47 |     if sys.argv[1:]:
48 |         print(plural(sys.argv[1]))
49 |     else:
50 |         print(__doc__)
51 | 
52 | # Copyright (c) 2009, Mark Pilgrim, All rights reserved.
53 | # 
54 | # Redistribution and use in source and binary forms, with or without modification,
55 | # are permitted provided that the following conditions are met:
56 | # 
57 | # * Redistributions of source code must retain the above copyright notice,
58 | #   this list of conditions and the following disclaimer.
59 | # * Redistributions in binary form must reproduce the above copyright notice,
60 | #   this list of conditions and the following disclaimer in the documentation
61 | #   and/or other materials provided with the distribution.
62 | # 
63 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS'
64 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
65 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
66 | # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
67 | # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
68 | # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
69 | # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
70 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
71 | # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
72 | # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
73 | # POSSIBILITY OF SUCH DAMAGE.
74 | 


--------------------------------------------------------------------------------
/examples/plural3.py:
--------------------------------------------------------------------------------
 1 | '''Pluralize English nouns (stage 3)
 2 | 
 3 | Command line usage:
 4 | $ python plural3.py noun
 5 | nouns
 6 | '''
 7 | 
 8 | import re
 9 | 
10 | def build_match_and_apply_functions(pattern, search, replace):
11 |     def matches_rule(word):
12 |         return re.search(pattern, word)
13 |     def apply_rule(word):
14 |         return re.sub(search, replace, word)
15 |     return (matches_rule, apply_rule)
16 | 
17 | patterns = \
18 |   (
19 |     ('[sxz]$',           '$',  'es'),
20 |     ('[^aeioudgkprt]h$', '$',  'es'),
21 |     ('(qu|[^aeiou])y$',  'y$', 'ies'),
22 |     ('$',                '$',  's')
23 |   )
24 | rules = [build_match_and_apply_functions(pattern, search, replace)
25 |          for (pattern, search, replace) in patterns]
26 | 
27 | def plural(noun):
28 |     for matches_rule, apply_rule in rules:
29 |         if matches_rule(noun):
30 |             return apply_rule(noun)
31 | 
32 | if __name__ == '__main__':
33 |     import sys
34 |     if sys.argv[1:]:
35 |         print(plural(sys.argv[1]))
36 |     else:
37 |         print(__doc__)
38 | 
39 | # Copyright (c) 2009, Mark Pilgrim, All rights reserved.
40 | # 
41 | # Redistribution and use in source and binary forms, with or without modification,
42 | # are permitted provided that the following conditions are met:
43 | # 
44 | # * Redistributions of source code must retain the above copyright notice,
45 | #   this list of conditions and the following disclaimer.
46 | # * Redistributions in binary form must reproduce the above copyright notice,
47 | #   this list of conditions and the following disclaimer in the documentation
48 | #   and/or other materials provided with the distribution.
49 | # 
50 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS'
51 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
52 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
53 | # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
54 | # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
55 | # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
56 | # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
57 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
58 | # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
59 | # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
60 | # POSSIBILITY OF SUCH DAMAGE.
61 | 


--------------------------------------------------------------------------------
/examples/plural4-rules.txt:
--------------------------------------------------------------------------------
1 | [sxz]$			$		es
2 | [^aeioudgkprt]h$	$		es
3 | [^aeiou]y$		y$		ies
4 | $			$		s
5 | 


--------------------------------------------------------------------------------
/examples/plural4.py:
--------------------------------------------------------------------------------
 1 | '''Pluralize English nouns (stage 4)
 2 | 
 3 | Command line usage:
 4 | $ python plural4.py noun
 5 | nouns
 6 | '''
 7 | 
 8 | import re
 9 | 
10 | def build_match_and_apply_functions(pattern, search, replace):
11 |     def matches_rule(word):
12 |         return re.search(pattern, word)
13 |     def apply_rule(word):
14 |         return re.sub(search, replace, word)
15 |     return (matches_rule, apply_rule)
16 | 
17 | rules = []
18 | with open('plural4-rules.txt', encoding='utf-8') as pattern_file:
19 |     for line in pattern_file:
20 |         pattern, search, replace = line.split(None, 3)
21 |         rules.append(build_match_and_apply_functions(
22 |                 pattern, search, replace))
23 | 
24 | def plural(noun):
25 |     for matches_rule, apply_rule in rules:
26 |         if matches_rule(noun):
27 |             return apply_rule(noun)
28 | 
29 | if __name__ == '__main__':
30 |     import sys
31 |     if sys.argv[1:]:
32 |         print(plural(sys.argv[1]))
33 |     else:
34 |         print(__doc__)
35 | 
36 | # Copyright (c) 2009, Mark Pilgrim, All rights reserved.
37 | # 
38 | # Redistribution and use in source and binary forms, with or without modification,
39 | # are permitted provided that the following conditions are met:
40 | # 
41 | # * Redistributions of source code must retain the above copyright notice,
42 | #   this list of conditions and the following disclaimer.
43 | # * Redistributions in binary form must reproduce the above copyright notice,
44 | #   this list of conditions and the following disclaimer in the documentation
45 | #   and/or other materials provided with the distribution.
46 | # 
47 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS'
48 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
49 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
50 | # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
51 | # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
52 | # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
53 | # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
54 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
55 | # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
56 | # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
57 | # POSSIBILITY OF SUCH DAMAGE.
58 | 


--------------------------------------------------------------------------------
/examples/plural5-rules.txt:
--------------------------------------------------------------------------------
1 | [sxz]$			$		es
2 | [^aeioudgkprt]h$	$		es
3 | [^aeiou]y$		y$		ies
4 | $			$		s
5 | 


--------------------------------------------------------------------------------
/examples/plural5.py:
--------------------------------------------------------------------------------
 1 | '''Pluralize English nouns (stage 5)
 2 | 
 3 | Command line usage:
 4 | $ python plural5.py noun
 5 | nouns
 6 | '''
 7 | 
 8 | import re
 9 | 
10 | def build_match_and_apply_functions(pattern, search, replace):
11 |     def matches_rule(word):
12 |         return re.search(pattern, word)
13 |     def apply_rule(word):
14 |         return re.sub(search, replace, word)
15 |     return [matches_rule, apply_rule]
16 | 
17 | def rules(rules_filename):
18 |     with open(rules_filename, encoding='utf-8') as pattern_file:
19 |         for line in pattern_file:
20 |             pattern, search, replace = line.split(None, 3)
21 |             yield build_match_and_apply_functions(pattern, search, replace)
22 | 
23 | def plural(noun, rules_filename='plural5-rules.txt'):
24 |     for matches_rule, apply_rule in rules(rules_filename):
25 |         if matches_rule(noun):
26 |             return apply_rule(noun)
27 |     raise ValueError('no matching rule for {0}'.format(noun))
28 | 
29 | if __name__ == '__main__':
30 |     import sys
31 |     if sys.argv[1:]:
32 |         print(plural(sys.argv[1]))
33 |     else:
34 |         print(__doc__)
35 | 
36 | # Copyright (c) 2009, Mark Pilgrim, All rights reserved.
37 | # 
38 | # Redistribution and use in source and binary forms, with or without modification,
39 | # are permitted provided that the following conditions are met:
40 | # 
41 | # * Redistributions of source code must retain the above copyright notice,
42 | #   this list of conditions and the following disclaimer.
43 | # * Redistributions in binary form must reproduce the above copyright notice,
44 | #   this list of conditions and the following disclaimer in the documentation
45 | #   and/or other materials provided with the distribution.
46 | # 
47 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS'
48 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
49 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
50 | # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
51 | # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
52 | # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
53 | # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
54 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
55 | # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
56 | # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
57 | # POSSIBILITY OF SUCH DAMAGE.
58 | 


--------------------------------------------------------------------------------
/examples/plural6-rules.txt:
--------------------------------------------------------------------------------
 1 | ^(sheep|deer|fish|moose|aircraft|series|haiku)$	($)	\1
 2 | [ml]ouse$		ouse$		ice
 3 | child$			$		ren
 4 | booth$			$		s
 5 | foot$			oot$		eet
 6 | ooth$			ooth$		eeth
 7 | l[eo]af$		af$		aves
 8 | sis$			sis$		ses
 9 | ^(hu|ro)man$		$		s
10 | man$			man$		men
11 | ^lowlife$		$		s
12 | ife$			ife$		ives
13 | eau$			$		x
14 | ^[dp]elf$		$		s
15 | lf$			lf$		lves
16 | [sxz]$			$		es
17 | [^aeioudgkprt]h$	$		es
18 | (qu|[^aeiou])y$		y$		ies
19 | $			$		s
20 | 


--------------------------------------------------------------------------------
/examples/plural6.py:
--------------------------------------------------------------------------------
 1 | '''Pluralize English nouns (stage 6)
 2 | 
 3 | Command line usage:
 4 | $ python plural6.py noun
 5 | nouns
 6 | '''
 7 | 
 8 | import re
 9 | 
10 | def build_match_and_apply_functions(pattern, search, replace):
11 |     def matches_rule(word):
12 |         return re.search(pattern, word)
13 |     def apply_rule(word):
14 |         return re.sub(search, replace, word)
15 |     return [matches_rule, apply_rule]
16 | 
17 | class LazyRules:
18 |     rules_filename = 'plural6-rules.txt'
19 | 
20 |     def __init__(self):
21 |         self.pattern_file = open(self.rules_filename, encoding='utf-8')
22 |         self.cache = []
23 | 
24 |     def __iter__(self):
25 |         self.cache_index = 0
26 |         return self
27 | 
28 |     def __next__(self):
29 |         self.cache_index += 1
30 |         if len(self.cache) >= self.cache_index:
31 |             return self.cache[self.cache_index - 1]
32 | 
33 |         if self.pattern_file.closed:
34 |             raise StopIteration
35 | 
36 |         line = self.pattern_file.readline()
37 |         if not line:
38 |             self.pattern_file.close()
39 |             raise StopIteration
40 | 
41 |         pattern, search, replace = line.split(None, 3)
42 |         funcs = build_match_and_apply_functions(
43 |             pattern, search, replace)
44 |         self.cache.append(funcs)
45 |         return funcs
46 | 
47 | rules = LazyRules()
48 |         
49 | def plural(noun):
50 |     for matches_rule, apply_rule in rules:
51 |         if matches_rule(noun):
52 |             return apply_rule(noun)
53 | 
54 | if __name__ == '__main__':
55 |     import sys
56 |     if sys.argv[1:]:
57 |         print(plural(sys.argv[1]))
58 |     else:
59 |         print(__doc__)
60 | 
61 | # Copyright (c) 2009, Mark Pilgrim, All rights reserved.
62 | # 
63 | # Redistribution and use in source and binary forms, with or without modification,
64 | # are permitted provided that the following conditions are met:
65 | # 
66 | # * Redistributions of source code must retain the above copyright notice,
67 | #   this list of conditions and the following disclaimer.
68 | # * Redistributions in binary form must reproduce the above copyright notice,
69 | #   this list of conditions and the following disclaimer in the documentation
70 | #   and/or other materials provided with the distribution.
71 | # 
72 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS'
73 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
74 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
75 | # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
76 | # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
77 | # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
78 | # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
79 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
80 | # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
81 | # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
82 | # POSSIBILITY OF SUCH DAMAGE.
83 | 


--------------------------------------------------------------------------------
/examples/pluraltest1.py:
--------------------------------------------------------------------------------
 1 | '''Unit test for plural1.py'''
 2 | 
 3 | import plural1
 4 | import unittest
 5 | 
 6 | class KnownValues(unittest.TestCase):
 7 |     def test_sxz(self):
 8 |         'words ending in S, X, and Z'
 9 |         nouns = {
10 |             'bass': 'basses',
11 |             'bus': 'buses',
12 |             'walrus': 'walruses',
13 |             'box': 'boxes',
14 |             'fax': 'faxes',
15 |             'suffix': 'suffixes',
16 |             'mailbox': 'mailboxes',
17 |             'buzz': 'buzzes',
18 |             'waltz': 'waltzes'
19 |             }
20 |         for singular, plural in nouns.items():
21 |             self.assertEqual(plural1.plural(singular), plural)
22 | 
23 |     def test_h(self):
24 |         'words ending in H'
25 |         nouns = {
26 |             'coach': 'coaches',
27 |             'glitch': 'glitches',
28 |             'rash': 'rashes',
29 |             'watch': 'watches',
30 |             'cheetah': 'cheetahs',
31 |             'cough': 'coughs'
32 |             }
33 |         for singular, plural in nouns.items():
34 |             self.assertEqual(plural1.plural(singular), plural)
35 | 
36 |     def test_y(self):
37 |         'words ending in Y'
38 |         nouns = {
39 |             'utility': 'utilities',
40 |             'vacancy': 'vacancies',
41 |             'boy': 'boys',
42 |             'day': 'days'
43 |             }
44 |         for singular, plural in nouns.items():
45 |             self.assertEqual(plural1.plural(singular), plural)
46 | 
47 |     def test_default(self):
48 |         'unexceptional words'
49 |         nouns = {
50 |             'papaya': 'papayas',
51 |             'whip': 'whips',
52 |             'palimpsest': 'palimpsests'
53 |             }
54 |         for singular, plural in nouns.items():
55 |             self.assertEqual(plural1.plural(singular), plural)
56 |         
57 | if __name__ == '__main__':
58 |     unittest.main()
59 | 
60 | # Copyright (c) 2009, Mark Pilgrim, All rights reserved.
61 | # 
62 | # Redistribution and use in source and binary forms, with or without modification,
63 | # are permitted provided that the following conditions are met:
64 | # 
65 | # * Redistributions of source code must retain the above copyright notice,
66 | #   this list of conditions and the following disclaimer.
67 | # * Redistributions in binary form must reproduce the above copyright notice,
68 | #   this list of conditions and the following disclaimer in the documentation
69 | #   and/or other materials provided with the distribution.
70 | # 
71 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS'
72 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
73 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
74 | # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
75 | # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
76 | # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
77 | # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
78 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
79 | # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
80 | # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
81 | # POSSIBILITY OF SUCH DAMAGE.
82 | 


--------------------------------------------------------------------------------
/examples/pluraltest2.py:
--------------------------------------------------------------------------------
 1 | '''Unit test for plural2.py'''
 2 | 
 3 | import plural2
 4 | import unittest
 5 | 
 6 | class KnownValues(unittest.TestCase):
 7 |     def test_sxz(self):
 8 |         'words ending in S, X, and Z'
 9 |         nouns = {
10 |             'bass': 'basses',
11 |             'bus': 'buses',
12 |             'walrus': 'walruses',
13 |             'box': 'boxes',
14 |             'fax': 'faxes',
15 |             'suffix': 'suffixes',
16 |             'mailbox': 'mailboxes',
17 |             'buzz': 'buzzes',
18 |             'waltz': 'waltzes'
19 |             }
20 |         for singular, plural in nouns.items():
21 |             self.assertEqual(plural2.plural(singular), plural)
22 | 
23 |     def test_h(self):
24 |         'words ending in H'
25 |         nouns = {
26 |             'coach': 'coaches',
27 |             'glitch': 'glitches',
28 |             'rash': 'rashes',
29 |             'watch': 'watches',
30 |             'cheetah': 'cheetahs',
31 |             'cough': 'coughs'
32 |             }
33 |         for singular, plural in nouns.items():
34 |             self.assertEqual(plural2.plural(singular), plural)
35 | 
36 |     def test_y(self):
37 |         'words ending in Y'
38 |         nouns = {
39 |             'utility': 'utilities',
40 |             'vacancy': 'vacancies',
41 |             'boy': 'boys',
42 |             'day': 'days'
43 |             }
44 |         for singular, plural in nouns.items():
45 |             self.assertEqual(plural2.plural(singular), plural)
46 | 
47 |     def test_default(self):
48 |         'unexceptional words'
49 |         nouns = {
50 |             'papaya': 'papayas',
51 |             'whip': 'whips',
52 |             'palimpsest': 'palimpsests'
53 |             }
54 |         for singular, plural in nouns.items():
55 |             self.assertEqual(plural2.plural(singular), plural)
56 |         
57 | if __name__ == '__main__':
58 |     unittest.main()
59 | 
60 | # Copyright (c) 2009, Mark Pilgrim, All rights reserved.
61 | # 
62 | # Redistribution and use in source and binary forms, with or without modification,
63 | # are permitted provided that the following conditions are met:
64 | # 
65 | # * Redistributions of source code must retain the above copyright notice,
66 | #   this list of conditions and the following disclaimer.
67 | # * Redistributions in binary form must reproduce the above copyright notice,
68 | #   this list of conditions and the following disclaimer in the documentation
69 | #   and/or other materials provided with the distribution.
70 | # 
71 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS'
72 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
73 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
74 | # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
75 | # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
76 | # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
77 | # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
78 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
79 | # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
80 | # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
81 | # POSSIBILITY OF SUCH DAMAGE.
82 | 


--------------------------------------------------------------------------------
/examples/pluraltest3.py:
--------------------------------------------------------------------------------
 1 | '''Unit test for plural1.py'''
 2 | 
 3 | import plural3
 4 | import unittest
 5 | 
 6 | class KnownValues(unittest.TestCase):
 7 |     def test_sxz(self):
 8 |         'words ending in S, X, and Z'
 9 |         nouns = {
10 |             'bass': 'basses',
11 |             'bus': 'buses',
12 |             'walrus': 'walruses',
13 |             'box': 'boxes',
14 |             'fax': 'faxes',
15 |             'suffix': 'suffixes',
16 |             'mailbox': 'mailboxes',
17 |             'buzz': 'buzzes',
18 |             'waltz': 'waltzes'
19 |             }
20 |         for singular, plural in nouns.items():
21 |             self.assertEqual(plural3.plural(singular), plural)
22 | 
23 |     def test_h(self):
24 |         'words ending in H'
25 |         nouns = {
26 |             'coach': 'coaches',
27 |             'glitch': 'glitches',
28 |             'rash': 'rashes',
29 |             'watch': 'watches',
30 |             'cheetah': 'cheetahs',
31 |             'cough': 'coughs'
32 |             }
33 |         for singular, plural in nouns.items():
34 |             self.assertEqual(plural3.plural(singular), plural)
35 | 
36 |     def test_y(self):
37 |         'words ending in Y'
38 |         nouns = {
39 |             'utility': 'utilities',
40 |             'vacancy': 'vacancies',
41 |             'boy': 'boys',
42 |             'day': 'days'
43 |             }
44 |         for singular, plural in nouns.items():
45 |             self.assertEqual(plural3.plural(singular), plural)
46 | 
47 |     def test_default(self):
48 |         'unexceptional words'
49 |         nouns = {
50 |             'papaya': 'papayas',
51 |             'whip': 'whips',
52 |             'palimpsest': 'palimpsests'
53 |             }
54 |         for singular, plural in nouns.items():
55 |             self.assertEqual(plural3.plural(singular), plural)
56 |         
57 | if __name__ == '__main__':
58 |     unittest.main()
59 | 
60 | # Copyright (c) 2009, Mark Pilgrim, All rights reserved.
61 | # 
62 | # Redistribution and use in source and binary forms, with or without modification,
63 | # are permitted provided that the following conditions are met:
64 | # 
65 | # * Redistributions of source code must retain the above copyright notice,
66 | #   this list of conditions and the following disclaimer.
67 | # * Redistributions in binary form must reproduce the above copyright notice,
68 | #   this list of conditions and the following disclaimer in the documentation
69 | #   and/or other materials provided with the distribution.
70 | # 
71 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS'
72 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
73 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
74 | # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
75 | # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
76 | # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
77 | # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
78 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
79 | # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
80 | # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
81 | # POSSIBILITY OF SUCH DAMAGE.
82 | 


--------------------------------------------------------------------------------
/examples/pluraltest4.py:
--------------------------------------------------------------------------------
 1 | '''Unit test for plural1.py'''
 2 | 
 3 | import plural4
 4 | import unittest
 5 | 
 6 | class KnownValues(unittest.TestCase):
 7 |     def test_sxz(self):
 8 |         'words ending in S, X, and Z'
 9 |         nouns = {
10 |             'bass': 'basses',
11 |             'bus': 'buses',
12 |             'walrus': 'walruses',
13 |             'box': 'boxes',
14 |             'fax': 'faxes',
15 |             'suffix': 'suffixes',
16 |             'mailbox': 'mailboxes',
17 |             'buzz': 'buzzes',
18 |             'waltz': 'waltzes'
19 |             }
20 |         for singular, plural in nouns.items():
21 |             self.assertEqual(plural4.plural(singular), plural)
22 | 
23 |     def test_h(self):
24 |         'words ending in H'
25 |         nouns = {
26 |             'coach': 'coaches',
27 |             'glitch': 'glitches',
28 |             'rash': 'rashes',
29 |             'watch': 'watches',
30 |             'cheetah': 'cheetahs',
31 |             'cough': 'coughs'
32 |             }
33 |         for singular, plural in nouns.items():
34 |             self.assertEqual(plural4.plural(singular), plural)
35 | 
36 |     def test_y(self):
37 |         'words ending in Y'
38 |         nouns = {
39 |             'utility': 'utilities',
40 |             'vacancy': 'vacancies',
41 |             'boy': 'boys',
42 |             'day': 'days'
43 |             }
44 |         for singular, plural in nouns.items():
45 |             self.assertEqual(plural4.plural(singular), plural)
46 | 
47 |     def test_default(self):
48 |         'unexceptional words'
49 |         nouns = {
50 |             'papaya': 'papayas',
51 |             'whip': 'whips',
52 |             'palimpsest': 'palimpsests'
53 |             }
54 |         for singular, plural in nouns.items():
55 |             self.assertEqual(plural4.plural(singular), plural)
56 |         
57 | if __name__ == '__main__':
58 |     unittest.main()
59 | 
60 | # Copyright (c) 2009, Mark Pilgrim, All rights reserved.
61 | # 
62 | # Redistribution and use in source and binary forms, with or without modification,
63 | # are permitted provided that the following conditions are met:
64 | # 
65 | # * Redistributions of source code must retain the above copyright notice,
66 | #   this list of conditions and the following disclaimer.
67 | # * Redistributions in binary form must reproduce the above copyright notice,
68 | #   this list of conditions and the following disclaimer in the documentation
69 | #   and/or other materials provided with the distribution.
70 | # 
71 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS'
72 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
73 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
74 | # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
75 | # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
76 | # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
77 | # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
78 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
79 | # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
80 | # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
81 | # POSSIBILITY OF SUCH DAMAGE.
82 | 


--------------------------------------------------------------------------------
/examples/pluraltest5.py:
--------------------------------------------------------------------------------
 1 | '''Unit test for plural5.py'''
 2 | 
 3 | import plural5
 4 | import unittest
 5 | 
 6 | class KnownValues(unittest.TestCase):
 7 |     def test_sxz(self):
 8 |         'words ending in S, X, and Z'
 9 |         nouns = {
10 |             'bass': 'basses',
11 |             'bus': 'buses',
12 |             'walrus': 'walruses',
13 |             'box': 'boxes',
14 |             'fax': 'faxes',
15 |             'suffix': 'suffixes',
16 |             'mailbox': 'mailboxes',
17 |             'buzz': 'buzzes',
18 |             'waltz': 'waltzes'
19 |             }
20 |         for singular, plural in nouns.items():
21 |             self.assertEqual(plural5.plural(singular), plural)
22 | 
23 |     def test_h(self):
24 |         'words ending in H'
25 |         nouns = {
26 |             'coach': 'coaches',
27 |             'glitch': 'glitches',
28 |             'rash': 'rashes',
29 |             'watch': 'watches',
30 |             'cheetah': 'cheetahs',
31 |             'cough': 'coughs'
32 |             }
33 |         for singular, plural in nouns.items():
34 |             self.assertEqual(plural5.plural(singular), plural)
35 | 
36 |     def test_y(self):
37 |         'words ending in Y'
38 |         nouns = {
39 |             'utility': 'utilities',
40 |             'vacancy': 'vacancies',
41 |             'boy': 'boys',
42 |             'day': 'days'
43 |             }
44 |         for singular, plural in nouns.items():
45 |             self.assertEqual(plural5.plural(singular), plural)
46 | 
47 |     def test_default(self):
48 |         'unexceptional words'
49 |         nouns = {
50 |             'papaya': 'papayas',
51 |             'whip': 'whips',
52 |             'palimpsest': 'palimpsests'
53 |             }
54 |         for singular, plural in nouns.items():
55 |             self.assertEqual(plural5.plural(singular), plural)
56 |         
57 | if __name__ == '__main__':
58 |     unittest.main()
59 | 
60 | # Copyright (c) 2009, Mark Pilgrim, All rights reserved.
61 | # 
62 | # Redistribution and use in source and binary forms, with or without modification,
63 | # are permitted provided that the following conditions are met:
64 | # 
65 | # * Redistributions of source code must retain the above copyright notice,
66 | #   this list of conditions and the following disclaimer.
67 | # * Redistributions in binary form must reproduce the above copyright notice,
68 | #   this list of conditions and the following disclaimer in the documentation
69 | #   and/or other materials provided with the distribution.
70 | # 
71 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS'
72 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
73 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
74 | # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
75 | # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
76 | # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
77 | # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
78 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
79 | # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
80 | # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
81 | # POSSIBILITY OF SUCH DAMAGE.
82 | 


--------------------------------------------------------------------------------
/examples/pluraltest6.py:
--------------------------------------------------------------------------------
  1 | '''Unit test for plural6.py'''
  2 | 
  3 | import plural6
  4 | import unittest
  5 | 
  6 | class KnownValues(unittest.TestCase):
  7 |     def test_sxz(self):
  8 |         'words ending in S, X, and Z'
  9 |         nouns = {
 10 |             'bass': 'basses',
 11 |             'bus': 'buses',
 12 |             'walrus': 'walruses',
 13 |             'box': 'boxes',
 14 |             'fax': 'faxes',
 15 |             'suffix': 'suffixes',
 16 |             'mailbox': 'mailboxes',
 17 |             'buzz': 'buzzes',
 18 |             'waltz': 'waltzes'
 19 |             }
 20 |         for singular, plural in nouns.items():
 21 |             self.assertEqual(plural6.plural(singular), plural)
 22 | 
 23 |     def test_h(self):
 24 |         'words ending in H'
 25 |         nouns = {
 26 |             'coach': 'coaches',
 27 |             'glitch': 'glitches',
 28 |             'rash': 'rashes',
 29 |             'watch': 'watches',
 30 |             'cheetah': 'cheetahs',
 31 |             'cough': 'coughs'
 32 |             }
 33 |         for singular, plural in nouns.items():
 34 |             self.assertEqual(plural6.plural(singular), plural)
 35 | 
 36 |     def test_y(self):
 37 |         'words ending in Y'
 38 |         nouns = {
 39 |             'utility': 'utilities',
 40 |             'vacancy': 'vacancies',
 41 |             'boy': 'boys',
 42 |             'day': 'days'
 43 |             }
 44 |         for singular, plural in nouns.items():
 45 |             self.assertEqual(plural6.plural(singular), plural)
 46 | 
 47 |     def test_ouce(self):
 48 |         'words ending in OUSE'
 49 |         nouns = {
 50 |              'mouse': 'mice',
 51 |              'louse': 'lice'
 52 |              }
 53 |         for singular, plural in nouns.items():
 54 |             self.assertEqual(plural6.plural(singular), plural)
 55 | 
 56 |     def test_child(self):
 57 |         'special case: child'
 58 |         nouns = {
 59 |              'child': 'children'
 60 |              }
 61 |         for singular, plural in nouns.items():
 62 |             self.assertEqual(plural6.plural(singular), plural)
 63 | 
 64 |     def test_oot(self):
 65 |         'special case: foot'
 66 |         nouns = {
 67 |              'foot': 'feet'
 68 |              }
 69 |         for singular, plural in nouns.items():
 70 |             self.assertEqual(plural6.plural(singular), plural)
 71 | 
 72 |     def test_ooth(self):
 73 |         'words ending in OOTH'
 74 |         nouns = {
 75 |              'booth': 'booths',
 76 |              'tooth': 'teeth'
 77 |              }
 78 |         for singular, plural in nouns.items():
 79 |             self.assertEqual(plural6.plural(singular), plural)
 80 | 
 81 |     def test_f_ves(self):
 82 |         'words ending in F that become VES'
 83 |         nouns = {
 84 |              'leaf': 'leaves',
 85 |              'loaf': 'loaves'
 86 |              }
 87 |         for singular, plural in nouns.items():
 88 |             self.assertEqual(plural6.plural(singular), plural)
 89 | 
 90 |     def test_sis(self):
 91 |         'words ending in SIS'
 92 |         nouns = {
 93 |              'thesis': 'theses'
 94 |              }
 95 |         for singular, plural in nouns.items():
 96 |             self.assertEqual(plural6.plural(singular), plural)
 97 | 
 98 |     def test_man(self):
 99 |         'words ending in MAN'
100 |         nouns = {
101 |              'man': 'men',
102 |              'mailman': 'mailmen',
103 |              'human': 'humans',
104 |              'roman': 'romans'
105 |              }
106 |         for singular, plural in nouns.items():
107 |             self.assertEqual(plural6.plural(singular), plural)
108 | 
109 |     def test_ife(self):
110 |         'words ending in IFE'
111 |         nouns = {
112 |              'knife': 'knives',
113 |              'wife': 'wives',
114 |              'lowlife': 'lowlifes'
115 |              }
116 |         for singular, plural in nouns.items():
117 |             self.assertEqual(plural6.plural(singular), plural)
118 | 
119 |     def test_eau(self):
120 |         'words ending in EAU'
121 |         nouns = {
122 |              'tableau': 'tableaux'
123 |              }
124 |         for singular, plural in nouns.items():
125 |             self.assertEqual(plural6.plural(singular), plural)
126 | 
127 |     def test_elf(self):
128 |         'words ending in ELF'
129 |         nouns = {
130 |              'elf': 'elves',
131 |              'shelf': 'shelves',
132 |              'delf': 'delfs',
133 |              'pelf': 'pelfs'
134 |              }
135 |         for singular, plural in nouns.items():
136 |             self.assertEqual(plural6.plural(singular), plural)
137 | 
138 |     def test_same(self):
139 |         'words that are their own plural'
140 |         nouns = {
141 |              'sheep': 'sheep',
142 |              'deer': 'deer',
143 |              'fish': 'fish',
144 |              'moose': 'moose',
145 |              'aircraft': 'aircraft',
146 |              'series': 'series',
147 |              'haiku': 'haiku'
148 |              }
149 |         for singular, plural in nouns.items():
150 |             self.assertEqual(plural6.plural(singular), plural)
151 | 
152 |     def test_default(self):
153 |         'unexceptional words'
154 |         nouns = {
155 |             'papaya': 'papayas',
156 |             'whip': 'whips',
157 |             'palimpsest': 'palimpsests'
158 |             }
159 |         for singular, plural in nouns.items():
160 |             self.assertEqual(plural6.plural(singular), plural)
161 |         
162 | if __name__ == '__main__':
163 |     unittest.main()
164 | 
165 | # Copyright (c) 2009, Mark Pilgrim, All rights reserved.
166 | # 
167 | # Redistribution and use in source and binary forms, with or without modification,
168 | # are permitted provided that the following conditions are met:
169 | # 
170 | # * Redistributions of source code must retain the above copyright notice,
171 | #   this list of conditions and the following disclaimer.
172 | # * Redistributions in binary form must reproduce the above copyright notice,
173 | #   this list of conditions and the following disclaimer in the documentation
174 | #   and/or other materials provided with the distribution.
175 | # 
176 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS'
177 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
178 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
179 | # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
180 | # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
181 | # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
182 | # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
183 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
184 | # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
185 | # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
186 | # POSSIBILITY OF SUCH DAMAGE.
187 | 


--------------------------------------------------------------------------------
/examples/regression.py:
--------------------------------------------------------------------------------
 1 | #!/usr/bin/python3
 2 | 
 3 | import unittest
 4 | import os
 5 | import glob
 6 | 
 7 | def regressionTest():
 8 |     filenames = glob.glob('*test*.py')
 9 |     module_names = [os.path.splitext(os.path.basename(f))[0] for f in filenames]
10 |     modules = [__import__(name) for name in module_names]
11 |     tests = [unittest.defaultTestLoader.loadTestsFromModule(m) for m in modules]
12 |     return unittest.TestSuite(tests)
13 | 
14 | if __name__ == '__main__':
15 |     unittest.main(defaultTest='regressionTest')


--------------------------------------------------------------------------------
/examples/roman1.py:
--------------------------------------------------------------------------------
 1 | '''Convert to and from Roman numerals
 2 | 
 3 | This program is part of 'Dive Into Python 3', a free Python book for
 4 | experienced programmers.  Visit http://diveintopython3.org/ for the
 5 | latest version.
 6 | '''
 7 | 
 8 | roman_numeral_map = (('M',  1000),
 9 |                      ('CM', 900),
10 |                      ('D',  500),
11 |                      ('CD', 400),
12 |                      ('C',  100),
13 |                      ('XC', 90),
14 |                      ('L',  50),
15 |                      ('XL', 40),
16 |                      ('X',  10),
17 |                      ('IX', 9),
18 |                      ('V',  5),
19 |                      ('IV', 4),
20 |                      ('I',  1))
21 | 
22 | def to_roman(n):
23 |     '''convert integer to Roman numeral'''
24 |     result = ''
25 |     for numeral, integer in roman_numeral_map:
26 |         while n >= integer:
27 |             result += numeral
28 |             n -= integer
29 |     return result
30 | 
31 | # Copyright (c) 2009, Mark Pilgrim, All rights reserved.
32 | # 
33 | # Redistribution and use in source and binary forms, with or without modification,
34 | # are permitted provided that the following conditions are met:
35 | # 
36 | # * Redistributions of source code must retain the above copyright notice,
37 | #   this list of conditions and the following disclaimer.
38 | # * Redistributions in binary form must reproduce the above copyright notice,
39 | #   this list of conditions and the following disclaimer in the documentation
40 | #   and/or other materials provided with the distribution.
41 | # 
42 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS'
43 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
44 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
45 | # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
46 | # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
47 | # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
48 | # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
49 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
50 | # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
51 | # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
52 | # POSSIBILITY OF SUCH DAMAGE.
53 | 


--------------------------------------------------------------------------------
/examples/roman10.py:
--------------------------------------------------------------------------------
 1 | '''Convert to and from Roman numerals
 2 | 
 3 | This program is part of 'Dive Into Python 3', a free Python book for
 4 | experienced programmers.  Visit http://diveintopython3.org/ for the
 5 | latest version.
 6 | '''
 7 | 
 8 | class OutOfRangeError(ValueError): pass
 9 | class NotIntegerError(ValueError): pass
10 | class InvalidRomanNumeralError(ValueError): pass
11 | 
12 | roman_numeral_map = (('M',  1000),
13 |                      ('CM', 900),
14 |                      ('D',  500),
15 |                      ('CD', 400),
16 |                      ('C',  100),
17 |                      ('XC', 90),
18 |                      ('L',  50),
19 |                      ('XL', 40),
20 |                      ('X',  10),
21 |                      ('IX', 9),
22 |                      ('V',  5),
23 |                      ('IV', 4),
24 |                      ('I',  1))
25 | 
26 | to_roman_table = [ None ]
27 | from_roman_table = {}
28 | 
29 | def to_roman(n):
30 |     '''convert integer to Roman numeral'''
31 |     if int(n) != n:
32 |         raise NotIntegerError('non-integers can not be converted')
33 |     if not (0 < n < 5000):
34 |         raise OutOfRangeError('number out of range (must be 1..4999)')
35 |     return to_roman_table[n]
36 | 
37 | def from_roman(s):
38 |     '''convert Roman numeral to integer'''
39 |     if not isinstance(s, str):
40 |         raise InvalidRomanNumeralError('Input must be a string')
41 |     if not s:
42 |         raise InvalidRomanNumeralError('Input can not be blank')
43 |     if s not in from_roman_table:
44 |         raise InvalidRomanNumeralError('Invalid Roman numeral: {0}'.format(s))
45 |     return from_roman_table[s]
46 | 
47 | def build_lookup_tables():
48 |     def to_roman(n):
49 |         result = ''
50 |         for numeral, integer in roman_numeral_map:
51 |             if n >= integer:
52 |                 result = numeral
53 |                 n -= integer
54 |                 break
55 |         if n > 0:
56 |             result += to_roman_table[n]
57 |         return result
58 | 
59 |     for integer in range(1, 5000):
60 |         roman_numeral = to_roman(integer)
61 |         to_roman_table.append(roman_numeral)
62 |         from_roman_table[roman_numeral] = integer
63 | 
64 | build_lookup_tables()
65 | 
66 | # Copyright (c) 2009, Mark Pilgrim, All rights reserved.
67 | # 
68 | # Redistribution and use in source and binary forms, with or without modification,
69 | # are permitted provided that the following conditions are met:
70 | # 
71 | # * Redistributions of source code must retain the above copyright notice,
72 | #   this list of conditions and the following disclaimer.
73 | # * Redistributions in binary form must reproduce the above copyright notice,
74 | #   this list of conditions and the following disclaimer in the documentation
75 | #   and/or other materials provided with the distribution.
76 | # 
77 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS'
78 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
79 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
80 | # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
81 | # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
82 | # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
83 | # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
84 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
85 | # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
86 | # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
87 | # POSSIBILITY OF SUCH DAMAGE.
88 | 


--------------------------------------------------------------------------------
/examples/roman2.py:
--------------------------------------------------------------------------------
 1 | '''Convert to and from Roman numerals
 2 | 
 3 | This program is part of 'Dive Into Python 3', a free Python book for
 4 | experienced programmers.  Visit http://diveintopython3.org/ for the
 5 | latest version.
 6 | '''
 7 | class OutOfRangeError(ValueError):
 8 |     pass
 9 | 
10 | roman_numeral_map = (('M',  1000),
11 |                      ('CM', 900),
12 |                      ('D',  500),
13 |                      ('CD', 400),
14 |                      ('C',  100),
15 |                      ('XC', 90),
16 |                      ('L',  50),
17 |                      ('XL', 40),
18 |                      ('X',  10),
19 |                      ('IX', 9),
20 |                      ('V',  5),
21 |                      ('IV', 4),
22 |                      ('I',  1))
23 | 
24 | def to_roman(n):
25 |     '''convert integer to Roman numeral'''
26 |     if n > 3999:
27 |         raise OutOfRangeError('number out of range (must be less than 4000)')
28 | 
29 |     result = ''
30 |     for numeral, integer in roman_numeral_map:
31 |         while n >= integer:
32 |             result += numeral
33 |             n -= integer
34 |     return result
35 | 
36 | # Copyright (c) 2009, Mark Pilgrim, All rights reserved.
37 | # 
38 | # Redistribution and use in source and binary forms, with or without modification,
39 | # are permitted provided that the following conditions are met:
40 | # 
41 | # * Redistributions of source code must retain the above copyright notice,
42 | #   this list of conditions and the following disclaimer.
43 | # * Redistributions in binary form must reproduce the above copyright notice,
44 | #   this list of conditions and the following disclaimer in the documentation
45 | #   and/or other materials provided with the distribution.
46 | # 
47 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS'
48 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
49 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
50 | # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
51 | # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
52 | # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
53 | # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
54 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
55 | # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
56 | # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
57 | # POSSIBILITY OF SUCH DAMAGE.
58 | 


--------------------------------------------------------------------------------
/examples/roman3.py:
--------------------------------------------------------------------------------
 1 | '''Convert to and from Roman numerals
 2 | 
 3 | This program is part of 'Dive Into Python 3', a free Python book for
 4 | experienced programmers.  Visit http://diveintopython3.org/ for the
 5 | latest version.
 6 | '''
 7 | class OutOfRangeError(ValueError): pass
 8 | 
 9 | roman_numeral_map = (('M',  1000),
10 |                      ('CM', 900),
11 |                      ('D',  500),
12 |                      ('CD', 400),
13 |                      ('C',  100),
14 |                      ('XC', 90),
15 |                      ('L',  50),
16 |                      ('XL', 40),
17 |                      ('X',  10),
18 |                      ('IX', 9),
19 |                      ('V',  5),
20 |                      ('IV', 4),
21 |                      ('I',  1))
22 | 
23 | def to_roman(n):
24 |     '''convert integer to Roman numeral'''
25 |     if not (0 < n < 4000):
26 |         raise OutOfRangeError('number out of range (must be 1..3999)')
27 | 
28 |     result = ''
29 |     for numeral, integer in roman_numeral_map:
30 |         while n >= integer:
31 |             result += numeral
32 |             n -= integer
33 |     return result
34 | 
35 | # Copyright (c) 2009, Mark Pilgrim, All rights reserved.
36 | # 
37 | # Redistribution and use in source and binary forms, with or without modification,
38 | # are permitted provided that the following conditions are met:
39 | # 
40 | # * Redistributions of source code must retain the above copyright notice,
41 | #   this list of conditions and the following disclaimer.
42 | # * Redistributions in binary form must reproduce the above copyright notice,
43 | #   this list of conditions and the following disclaimer in the documentation
44 | #   and/or other materials provided with the distribution.
45 | # 
46 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS'
47 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
48 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
49 | # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
50 | # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
51 | # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
52 | # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
53 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
54 | # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
55 | # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
56 | # POSSIBILITY OF SUCH DAMAGE.
57 | 


--------------------------------------------------------------------------------
/examples/roman4.py:
--------------------------------------------------------------------------------
 1 | '''Convert to and from Roman numerals
 2 | 
 3 | This program is part of 'Dive Into Python 3', a free Python book for
 4 | experienced programmers.  Visit http://diveintopython3.org/ for the
 5 | latest version.
 6 | '''
 7 | class OutOfRangeError(ValueError): pass
 8 | class NotIntegerError(ValueError): pass
 9 | 
10 | roman_numeral_map = (('M',  1000),
11 |                      ('CM', 900),
12 |                      ('D',  500),
13 |                      ('CD', 400),
14 |                      ('C',  100),
15 |                      ('XC', 90),
16 |                      ('L',  50),
17 |                      ('XL', 40),
18 |                      ('X',  10),
19 |                      ('IX', 9),
20 |                      ('V',  5),
21 |                      ('IV', 4),
22 |                      ('I',  1))
23 | 
24 | def to_roman(n):
25 |     '''convert integer to Roman numeral'''
26 |     if not (0 < n < 4000):
27 |         raise OutOfRangeError('number out of range (must be 1..3999)')
28 |     if not isinstance(n, int):
29 |         raise NotIntegerError('non-integers can not be converted')
30 | 
31 |     result = ''
32 |     for numeral, integer in roman_numeral_map:
33 |         while n >= integer:
34 |             result += numeral
35 |             n -= integer
36 |     return result
37 | 
38 | # Copyright (c) 2009, Mark Pilgrim, All rights reserved.
39 | # 
40 | # Redistribution and use in source and binary forms, with or without modification,
41 | # are permitted provided that the following conditions are met:
42 | # 
43 | # * Redistributions of source code must retain the above copyright notice,
44 | #   this list of conditions and the following disclaimer.
45 | # * Redistributions in binary form must reproduce the above copyright notice,
46 | #   this list of conditions and the following disclaimer in the documentation
47 | #   and/or other materials provided with the distribution.
48 | # 
49 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS'
50 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
51 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
52 | # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
53 | # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
54 | # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
55 | # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
56 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
57 | # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
58 | # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
59 | # POSSIBILITY OF SUCH DAMAGE.
60 | 


--------------------------------------------------------------------------------
/examples/roman5.py:
--------------------------------------------------------------------------------
 1 | '''Convert to and from Roman numerals
 2 | 
 3 | This program is part of 'Dive Into Python 3', a free Python book for
 4 | experienced programmers.  Visit http://diveintopython3.org/ for the
 5 | latest version.
 6 | '''
 7 | class OutOfRangeError(ValueError): pass
 8 | class NotIntegerError(ValueError): pass
 9 | 
10 | roman_numeral_map = (('M',  1000),
11 |                      ('CM', 900),
12 |                      ('D',  500),
13 |                      ('CD', 400),
14 |                      ('C',  100),
15 |                      ('XC', 90),
16 |                      ('L',  50),
17 |                      ('XL', 40),
18 |                      ('X',  10),
19 |                      ('IX', 9),
20 |                      ('V',  5),
21 |                      ('IV', 4),
22 |                      ('I',  1))
23 | 
24 | def to_roman(n):
25 |     '''convert integer to Roman numeral'''
26 |     if not (0 < n < 4000):
27 |         raise OutOfRangeError('number out of range (must be 1..3999)')
28 |     if not isinstance(n, int):
29 |         raise NotIntegerError('non-integers can not be converted')
30 | 
31 |     result = ''
32 |     for numeral, integer in roman_numeral_map:
33 |         while n >= integer:
34 |             result += numeral
35 |             n -= integer
36 |     return result
37 | 
38 | def from_roman(s):
39 |     '''convert Roman numeral to integer'''
40 |     result = 0
41 |     index = 0
42 |     for numeral, integer in roman_numeral_map:
43 |         while s[index : index + len(numeral)] == numeral:
44 |             result += integer
45 |             index += len(numeral)
46 |     return result
47 | 
48 | # Copyright (c) 2009, Mark Pilgrim, All rights reserved.
49 | # 
50 | # Redistribution and use in source and binary forms, with or without modification,
51 | # are permitted provided that the following conditions are met:
52 | # 
53 | # * Redistributions of source code must retain the above copyright notice,
54 | #   this list of conditions and the following disclaimer.
55 | # * Redistributions in binary form must reproduce the above copyright notice,
56 | #   this list of conditions and the following disclaimer in the documentation
57 | #   and/or other materials provided with the distribution.
58 | # 
59 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS'
60 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
61 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
62 | # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
63 | # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
64 | # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
65 | # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
66 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
67 | # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
68 | # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
69 | # POSSIBILITY OF SUCH DAMAGE.
70 | 


--------------------------------------------------------------------------------
/examples/roman6.py:
--------------------------------------------------------------------------------
 1 | '''Convert to and from Roman numerals
 2 | 
 3 | This program is part of 'Dive Into Python 3', a free Python book for
 4 | experienced programmers.  Visit http://diveintopython3.org/ for the
 5 | latest version.
 6 | '''
 7 | import re
 8 | 
 9 | class OutOfRangeError(ValueError): pass
10 | class NotIntegerError(ValueError): pass
11 | class InvalidRomanNumeralError(ValueError): pass
12 | 
13 | roman_numeral_map = (('M',  1000),
14 |                      ('CM', 900),
15 |                      ('D',  500),
16 |                      ('CD', 400),
17 |                      ('C',  100),
18 |                      ('XC', 90),
19 |                      ('L',  50),
20 |                      ('XL', 40),
21 |                      ('X',  10),
22 |                      ('IX', 9),
23 |                      ('V',  5),
24 |                      ('IV', 4),
25 |                      ('I',  1))
26 | 
27 | roman_numeral_pattern = re.compile('''
28 |     ^                   # beginning of string
29 |     M{0,3}              # thousands - 0 to 3 M's
30 |     (CM|CD|D?C{0,3})    # hundreds - 900 (CM), 400 (CD), 0-300 (0 to 3 C's),
31 |                         #            or 500-800 (D, followed by 0 to 3 C's)
32 |     (XC|XL|L?X{0,3})    # tens - 90 (XC), 40 (XL), 0-30 (0 to 3 X's),
33 |                         #        or 50-80 (L, followed by 0 to 3 X's)
34 |     (IX|IV|V?I{0,3})    # ones - 9 (IX), 4 (IV), 0-3 (0 to 3 I's),
35 |                         #        or 5-8 (V, followed by 0 to 3 I's)
36 |     $                   # end of string
37 |     ''', re.VERBOSE)
38 | 
39 | def to_roman(n):
40 |     '''convert integer to Roman numeral'''
41 |     if not (0 < n < 4000):
42 |         raise OutOfRangeError('number out of range (must be 1..3999)')
43 |     if not isinstance(n, int):
44 |         raise NotIntegerError('non-integers can not be converted')
45 | 
46 |     result = ''
47 |     for numeral, integer in roman_numeral_map:
48 |         while n >= integer:
49 |             result += numeral
50 |             n -= integer
51 |     return result
52 | 
53 | def from_roman(s):
54 |     '''convert Roman numeral to integer'''
55 |     if not roman_numeral_pattern.search(s):
56 |         raise InvalidRomanNumeralError('Invalid Roman numeral: {0}'.format(s))
57 | 
58 |     result = 0
59 |     index = 0
60 |     for numeral, integer in roman_numeral_map:
61 |         while s[index : index + len(numeral)] == numeral:
62 |             result += integer
63 |             index += len(numeral)
64 |     return result
65 | 
66 | # Copyright (c) 2009, Mark Pilgrim, All rights reserved.
67 | # 
68 | # Redistribution and use in source and binary forms, with or without modification,
69 | # are permitted provided that the following conditions are met:
70 | # 
71 | # * Redistributions of source code must retain the above copyright notice,
72 | #   this list of conditions and the following disclaimer.
73 | # * Redistributions in binary form must reproduce the above copyright notice,
74 | #   this list of conditions and the following disclaimer in the documentation
75 | #   and/or other materials provided with the distribution.
76 | # 
77 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS'
78 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
79 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
80 | # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
81 | # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
82 | # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
83 | # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
84 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
85 | # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
86 | # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
87 | # POSSIBILITY OF SUCH DAMAGE.
88 | 


--------------------------------------------------------------------------------
/examples/roman7.py:
--------------------------------------------------------------------------------
 1 | '''Convert to and from Roman numerals
 2 | 
 3 | This program is part of 'Dive Into Python 3', a free Python book for
 4 | experienced programmers.  Visit http://diveintopython3.org/ for the
 5 | latest version.
 6 | '''
 7 | import re
 8 | 
 9 | class OutOfRangeError(ValueError): pass
10 | class NotIntegerError(ValueError): pass
11 | class InvalidRomanNumeralError(ValueError): pass
12 | 
13 | roman_numeral_map = (('M',  1000),
14 |                      ('CM', 900),
15 |                      ('D',  500),
16 |                      ('CD', 400),
17 |                      ('C',  100),
18 |                      ('XC', 90),
19 |                      ('L',  50),
20 |                      ('XL', 40),
21 |                      ('X',  10),
22 |                      ('IX', 9),
23 |                      ('V',  5),
24 |                      ('IV', 4),
25 |                      ('I',  1))
26 | 
27 | roman_numeral_pattern = re.compile('''
28 |     ^                   # beginning of string
29 |     M{0,3}              # thousands - 0 to 3 M's
30 |     (CM|CD|D?C{0,3})    # hundreds - 900 (CM), 400 (CD), 0-300 (0 to 3 C's),
31 |                         #            or 500-800 (D, followed by 0 to 3 C's)
32 |     (XC|XL|L?X{0,3})    # tens - 90 (XC), 40 (XL), 0-30 (0 to 3 X's),
33 |                         #        or 50-80 (L, followed by 0 to 3 X's)
34 |     (IX|IV|V?I{0,3})    # ones - 9 (IX), 4 (IV), 0-3 (0 to 3 I's),
35 |                         #        or 5-8 (V, followed by 0 to 3 I's)
36 |     $                   # end of string
37 |     ''', re.VERBOSE)
38 | 
39 | def to_roman(n):
40 |     '''convert integer to Roman numeral'''
41 |     if not (0 < n < 4000):
42 |         raise OutOfRangeError('number out of range (must be 1..3999)')
43 |     if not isinstance(n, int):
44 |         raise NotIntegerError('non-integers can not be converted')
45 | 
46 |     result = ''
47 |     for numeral, integer in roman_numeral_map:
48 |         while n >= integer:
49 |             result += numeral
50 |             n -= integer
51 |     return result
52 | 
53 | def from_roman(s):
54 |     '''convert Roman numeral to integer'''
55 |     if not isinstance(s, str):
56 |         raise InvalidRomanNumeralError('Input must be a string')
57 |     if not roman_numeral_pattern.search(s):
58 |         raise InvalidRomanNumeralError('Invalid Roman numeral: {0}'.format(s))
59 | 
60 |     result = 0
61 |     index = 0
62 |     for numeral, integer in roman_numeral_map:
63 |         while s[index : index + len(numeral)] == numeral:
64 |             result += integer
65 |             index += len(numeral)
66 |     return result
67 | 
68 | # Copyright (c) 2009, Mark Pilgrim, All rights reserved.
69 | # 
70 | # Redistribution and use in source and binary forms, with or without modification,
71 | # are permitted provided that the following conditions are met:
72 | # 
73 | # * Redistributions of source code must retain the above copyright notice,
74 | #   this list of conditions and the following disclaimer.
75 | # * Redistributions in binary form must reproduce the above copyright notice,
76 | #   this list of conditions and the following disclaimer in the documentation
77 | #   and/or other materials provided with the distribution.
78 | # 
79 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS'
80 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
81 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
82 | # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
83 | # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
84 | # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
85 | # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
86 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
87 | # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
88 | # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
89 | # POSSIBILITY OF SUCH DAMAGE.
90 | 


--------------------------------------------------------------------------------
/examples/roman8.py:
--------------------------------------------------------------------------------
 1 | '''Convert to and from Roman numerals
 2 | 
 3 | This program is part of 'Dive Into Python 3', a free Python book for
 4 | experienced programmers.  Visit http://diveintopython3.org/ for the
 5 | latest version.
 6 | '''
 7 | import re
 8 | 
 9 | class OutOfRangeError(ValueError): pass
10 | class NotIntegerError(ValueError): pass
11 | class InvalidRomanNumeralError(ValueError): pass
12 | 
13 | roman_numeral_map = (('M',  1000),
14 |                      ('CM', 900),
15 |                      ('D',  500),
16 |                      ('CD', 400),
17 |                      ('C',  100),
18 |                      ('XC', 90),
19 |                      ('L',  50),
20 |                      ('XL', 40),
21 |                      ('X',  10),
22 |                      ('IX', 9),
23 |                      ('V',  5),
24 |                      ('IV', 4),
25 |                      ('I',  1))
26 | 
27 | roman_numeral_pattern = re.compile('''
28 |     ^                   # beginning of string
29 |     M{0,3}              # thousands - 0 to 3 M's
30 |     (CM|CD|D?C{0,3})    # hundreds - 900 (CM), 400 (CD), 0-300 (0 to 3 C's),
31 |                         #            or 500-800 (D, followed by 0 to 3 C's)
32 |     (XC|XL|L?X{0,3})    # tens - 90 (XC), 40 (XL), 0-30 (0 to 3 X's),
33 |                         #        or 50-80 (L, followed by 0 to 3 X's)
34 |     (IX|IV|V?I{0,3})    # ones - 9 (IX), 4 (IV), 0-3 (0 to 3 I's),
35 |                         #        or 5-8 (V, followed by 0 to 3 I's)
36 |     $                   # end of string
37 |     ''', re.VERBOSE)
38 | 
39 | def to_roman(n):
40 |     '''convert integer to Roman numeral'''
41 |     if not (0 < n < 4000):
42 |         raise OutOfRangeError('number out of range (must be 1..3999)')
43 |     if not isinstance(n, int):
44 |         raise NotIntegerError('non-integers can not be converted')
45 | 
46 |     result = ''
47 |     for numeral, integer in roman_numeral_map:
48 |         while n >= integer:
49 |             result += numeral
50 |             n -= integer
51 |     return result
52 | 
53 | def from_roman(s):
54 |     '''convert Roman numeral to integer'''
55 |     if not isinstance(s, str):
56 |         raise InvalidRomanNumeralError('Input must be a string')
57 |     if not s:
58 |         raise InvalidRomanNumeralError('Input can not be blank')
59 |     if not roman_numeral_pattern.search(s):
60 |         raise InvalidRomanNumeralError('Invalid Roman numeral: {0}'.format(s))
61 | 
62 |     result = 0
63 |     index = 0
64 |     for numeral, integer in roman_numeral_map:
65 |         while s[index : index + len(numeral)] == numeral:
66 |             result += integer
67 |             index += len(numeral)
68 |     return result
69 | 
70 | # Copyright (c) 2009, Mark Pilgrim, All rights reserved.
71 | # 
72 | # Redistribution and use in source and binary forms, with or without modification,
73 | # are permitted provided that the following conditions are met:
74 | # 
75 | # * Redistributions of source code must retain the above copyright notice,
76 | #   this list of conditions and the following disclaimer.
77 | # * Redistributions in binary form must reproduce the above copyright notice,
78 | #   this list of conditions and the following disclaimer in the documentation
79 | #   and/or other materials provided with the distribution.
80 | # 
81 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS'
82 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
83 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
84 | # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
85 | # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
86 | # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
87 | # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
88 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
89 | # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
90 | # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
91 | # POSSIBILITY OF SUCH DAMAGE.
92 | 


--------------------------------------------------------------------------------
/examples/roman9.py:
--------------------------------------------------------------------------------
 1 | '''Convert to and from Roman numerals
 2 | 
 3 | This program is part of 'Dive Into Python 3', a free Python book for
 4 | experienced programmers.  Visit http://diveintopython3.org/ for the
 5 | latest version.
 6 | '''
 7 | import re
 8 | 
 9 | class OutOfRangeError(ValueError): pass
10 | class NotIntegerError(ValueError): pass
11 | class InvalidRomanNumeralError(ValueError): pass
12 | 
13 | roman_numeral_map = (('M',  1000),
14 |                      ('CM', 900),
15 |                      ('D',  500),
16 |                      ('CD', 400),
17 |                      ('C',  100),
18 |                      ('XC', 90),
19 |                      ('L',  50),
20 |                      ('XL', 40),
21 |                      ('X',  10),
22 |                      ('IX', 9),
23 |                      ('V',  5),
24 |                      ('IV', 4),
25 |                      ('I',  1))
26 | 
27 | roman_numeral_pattern = re.compile('''
28 |     ^                   # beginning of string
29 |     M{0,4}              # thousands - 0 to 4 M's
30 |     (CM|CD|D?C{0,3})    # hundreds - 900 (CM), 400 (CD), 0-300 (0 to 3 C's),
31 |                         #            or 500-800 (D, followed by 0 to 3 C's)
32 |     (XC|XL|L?X{0,3})    # tens - 90 (XC), 40 (XL), 0-30 (0 to 3 X's),
33 |                         #        or 50-80 (L, followed by 0 to 3 X's)
34 |     (IX|IV|V?I{0,3})    # ones - 9 (IX), 4 (IV), 0-3 (0 to 3 I's),
35 |                         #        or 5-8 (V, followed by 0 to 3 I's)
36 |     $                   # end of string
37 |     ''', re.VERBOSE)
38 | 
39 | def to_roman(n):
40 |     '''convert integer to Roman numeral'''
41 |     if not isinstance(n, int):
42 |         raise NotIntegerError('non-integers can not be converted')
43 |     if not (0 < n < 5000):
44 |         raise OutOfRangeError('number out of range (must be 1..4999)')
45 | 
46 |     result = ''
47 |     for numeral, integer in roman_numeral_map:
48 |         while n >= integer:
49 |             result += numeral
50 |             n -= integer
51 |     return result
52 | 
53 | def from_roman(s):
54 |     '''convert Roman numeral to integer'''
55 |     if not isinstance(s, str):
56 |         raise InvalidRomanNumeralError('Input must be a string')
57 |     if not s:
58 |         raise InvalidRomanNumeralError('Input can not be blank')
59 |     if not roman_numeral_pattern.search(s):
60 |         raise InvalidRomanNumeralError('Invalid Roman numeral: {0}'.format(s))
61 | 
62 |     result = 0
63 |     index = 0
64 |     for numeral, integer in roman_numeral_map:
65 |         while s[index : index + len(numeral)] == numeral:
66 |             result += integer
67 |             index += len(numeral)
68 |     return result
69 | 
70 | # Copyright (c) 2009, Mark Pilgrim, All rights reserved.
71 | # 
72 | # Redistribution and use in source and binary forms, with or without modification,
73 | # are permitted provided that the following conditions are met:
74 | # 
75 | # * Redistributions of source code must retain the above copyright notice,
76 | #   this list of conditions and the following disclaimer.
77 | # * Redistributions in binary form must reproduce the above copyright notice,
78 | #   this list of conditions and the following disclaimer in the documentation
79 | #   and/or other materials provided with the distribution.
80 | # 
81 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS'
82 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
83 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
84 | # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
85 | # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
86 | # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
87 | # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
88 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
89 | # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
90 | # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
91 | # POSSIBILITY OF SUCH DAMAGE.
92 | 


--------------------------------------------------------------------------------
/examples/romantest1.py:
--------------------------------------------------------------------------------
  1 | '''Unit test for roman1.py
  2 | 
  3 | This program is part of 'Dive Into Python 3', a free Python book for
  4 | experienced programmers.  Visit http://diveintopython3.org/ for the
  5 | latest version.
  6 | '''
  7 | 
  8 | import roman1
  9 | import unittest
 10 | 
 11 | class KnownValues(unittest.TestCase):
 12 |     known_values = ( (1, 'I'),
 13 |                      (2, 'II'),
 14 |                      (3, 'III'),
 15 |                      (4, 'IV'),
 16 |                      (5, 'V'),
 17 |                      (6, 'VI'),
 18 |                      (7, 'VII'),
 19 |                      (8, 'VIII'),
 20 |                      (9, 'IX'),
 21 |                      (10, 'X'),
 22 |                      (50, 'L'),
 23 |                      (100, 'C'),
 24 |                      (500, 'D'),
 25 |                      (1000, 'M'),
 26 |                      (31, 'XXXI'),
 27 |                      (148, 'CXLVIII'),
 28 |                      (294, 'CCXCIV'),
 29 |                      (312, 'CCCXII'),
 30 |                      (421, 'CDXXI'),
 31 |                      (528, 'DXXVIII'),
 32 |                      (621, 'DCXXI'),
 33 |                      (782, 'DCCLXXXII'),
 34 |                      (870, 'DCCCLXX'),
 35 |                      (941, 'CMXLI'),
 36 |                      (1043, 'MXLIII'),
 37 |                      (1110, 'MCX'),
 38 |                      (1226, 'MCCXXVI'),
 39 |                      (1301, 'MCCCI'),
 40 |                      (1485, 'MCDLXXXV'),
 41 |                      (1509, 'MDIX'),
 42 |                      (1607, 'MDCVII'),
 43 |                      (1754, 'MDCCLIV'),
 44 |                      (1832, 'MDCCCXXXII'),
 45 |                      (1993, 'MCMXCIII'),
 46 |                      (2074, 'MMLXXIV'),
 47 |                      (2152, 'MMCLII'),
 48 |                      (2212, 'MMCCXII'),
 49 |                      (2343, 'MMCCCXLIII'),
 50 |                      (2499, 'MMCDXCIX'),
 51 |                      (2574, 'MMDLXXIV'),
 52 |                      (2646, 'MMDCXLVI'),
 53 |                      (2723, 'MMDCCXXIII'),
 54 |                      (2892, 'MMDCCCXCII'),
 55 |                      (2975, 'MMCMLXXV'),
 56 |                      (3051, 'MMMLI'),
 57 |                      (3185, 'MMMCLXXXV'),
 58 |                      (3250, 'MMMCCL'),
 59 |                      (3313, 'MMMCCCXIII'),
 60 |                      (3408, 'MMMCDVIII'),
 61 |                      (3501, 'MMMDI'),
 62 |                      (3610, 'MMMDCX'),
 63 |                      (3743, 'MMMDCCXLIII'),
 64 |                      (3844, 'MMMDCCCXLIV'),
 65 |                      (3888, 'MMMDCCCLXXXVIII'),
 66 |                      (3940, 'MMMCMXL'),
 67 |                      (3999, 'MMMCMXCIX'))
 68 | 
 69 |     def test_to_roman_known_values(self):
 70 |         '''to_roman should give known result with known input'''
 71 |         for integer, numeral in self.known_values:
 72 |             result = roman1.to_roman(integer)
 73 |             self.assertEqual(numeral, result)
 74 | 
 75 | if __name__ == '__main__':
 76 |     unittest.main()
 77 | 
 78 | # Copyright (c) 2009, Mark Pilgrim, All rights reserved.
 79 | # 
 80 | # Redistribution and use in source and binary forms, with or without modification,
 81 | # are permitted provided that the following conditions are met:
 82 | # 
 83 | # * Redistributions of source code must retain the above copyright notice,
 84 | #   this list of conditions and the following disclaimer.
 85 | # * Redistributions in binary form must reproduce the above copyright notice,
 86 | #   this list of conditions and the following disclaimer in the documentation
 87 | #   and/or other materials provided with the distribution.
 88 | # 
 89 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS'
 90 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 91 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 92 | # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 93 | # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 94 | # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 95 | # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 96 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 97 | # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 98 | # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 99 | # POSSIBILITY OF SUCH DAMAGE.
100 | 


--------------------------------------------------------------------------------
/examples/romantest2.py:
--------------------------------------------------------------------------------
  1 | '''Unit test for roman1.py
  2 | 
  3 | This program is part of 'Dive Into Python 3', a free Python book for
  4 | experienced programmers.  Visit http://diveintopython3.org/ for the
  5 | latest version.
  6 | '''
  7 | 
  8 | import roman2
  9 | import unittest
 10 | 
 11 | class KnownValues(unittest.TestCase):
 12 |     known_values = ( (1, 'I'),
 13 |                      (2, 'II'),
 14 |                      (3, 'III'),
 15 |                      (4, 'IV'),
 16 |                      (5, 'V'),
 17 |                      (6, 'VI'),
 18 |                      (7, 'VII'),
 19 |                      (8, 'VIII'),
 20 |                      (9, 'IX'),
 21 |                      (10, 'X'),
 22 |                      (50, 'L'),
 23 |                      (100, 'C'),
 24 |                      (500, 'D'),
 25 |                      (1000, 'M'),
 26 |                      (31, 'XXXI'),
 27 |                      (148, 'CXLVIII'),
 28 |                      (294, 'CCXCIV'),
 29 |                      (312, 'CCCXII'),
 30 |                      (421, 'CDXXI'),
 31 |                      (528, 'DXXVIII'),
 32 |                      (621, 'DCXXI'),
 33 |                      (782, 'DCCLXXXII'),
 34 |                      (870, 'DCCCLXX'),
 35 |                      (941, 'CMXLI'),
 36 |                      (1043, 'MXLIII'),
 37 |                      (1110, 'MCX'),
 38 |                      (1226, 'MCCXXVI'),
 39 |                      (1301, 'MCCCI'),
 40 |                      (1485, 'MCDLXXXV'),
 41 |                      (1509, 'MDIX'),
 42 |                      (1607, 'MDCVII'),
 43 |                      (1754, 'MDCCLIV'),
 44 |                      (1832, 'MDCCCXXXII'),
 45 |                      (1993, 'MCMXCIII'),
 46 |                      (2074, 'MMLXXIV'),
 47 |                      (2152, 'MMCLII'),
 48 |                      (2212, 'MMCCXII'),
 49 |                      (2343, 'MMCCCXLIII'),
 50 |                      (2499, 'MMCDXCIX'),
 51 |                      (2574, 'MMDLXXIV'),
 52 |                      (2646, 'MMDCXLVI'),
 53 |                      (2723, 'MMDCCXXIII'),
 54 |                      (2892, 'MMDCCCXCII'),
 55 |                      (2975, 'MMCMLXXV'),
 56 |                      (3051, 'MMMLI'),
 57 |                      (3185, 'MMMCLXXXV'),
 58 |                      (3250, 'MMMCCL'),
 59 |                      (3313, 'MMMCCCXIII'),
 60 |                      (3408, 'MMMCDVIII'),
 61 |                      (3501, 'MMMDI'),
 62 |                      (3610, 'MMMDCX'),
 63 |                      (3743, 'MMMDCCXLIII'),
 64 |                      (3844, 'MMMDCCCXLIV'),
 65 |                      (3888, 'MMMDCCCLXXXVIII'),
 66 |                      (3940, 'MMMCMXL'),
 67 |                      (3999, 'MMMCMXCIX'))
 68 | 
 69 |     def test_to_roman_known_values(self):
 70 |         '''to_roman should give known result with known input'''
 71 |         for integer, numeral in self.known_values:
 72 |             result = roman2.to_roman(integer)
 73 |             self.assertEqual(numeral, result)
 74 | 
 75 | class ToRomanBadInput(unittest.TestCase):
 76 |     def test_too_large(self):
 77 |         '''to_roman should fail with large input'''
 78 |         self.assertRaises(roman2.OutOfRangeError, roman2.to_roman, 4000)
 79 | 
 80 | if __name__ == '__main__':
 81 |     unittest.main()
 82 | 
 83 | # Copyright (c) 2009, Mark Pilgrim, All rights reserved.
 84 | # 
 85 | # Redistribution and use in source and binary forms, with or without modification,
 86 | # are permitted provided that the following conditions are met:
 87 | # 
 88 | # * Redistributions of source code must retain the above copyright notice,
 89 | #   this list of conditions and the following disclaimer.
 90 | # * Redistributions in binary form must reproduce the above copyright notice,
 91 | #   this list of conditions and the following disclaimer in the documentation
 92 | #   and/or other materials provided with the distribution.
 93 | # 
 94 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS'
 95 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 96 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 97 | # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 98 | # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 99 | # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
100 | # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
101 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
102 | # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
103 | # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
104 | # POSSIBILITY OF SUCH DAMAGE.
105 | 


--------------------------------------------------------------------------------
/examples/romantest3.py:
--------------------------------------------------------------------------------
  1 | '''Unit test for roman1.py
  2 | 
  3 | This program is part of 'Dive Into Python 3', a free Python book for
  4 | experienced programmers.  Visit http://diveintopython3.org/ for the
  5 | latest version.
  6 | '''
  7 | 
  8 | import roman3
  9 | import unittest
 10 | 
 11 | class KnownValues(unittest.TestCase):
 12 |     known_values = ( (1, 'I'),
 13 |                      (2, 'II'),
 14 |                      (3, 'III'),
 15 |                      (4, 'IV'),
 16 |                      (5, 'V'),
 17 |                      (6, 'VI'),
 18 |                      (7, 'VII'),
 19 |                      (8, 'VIII'),
 20 |                      (9, 'IX'),
 21 |                      (10, 'X'),
 22 |                      (50, 'L'),
 23 |                      (100, 'C'),
 24 |                      (500, 'D'),
 25 |                      (1000, 'M'),
 26 |                      (31, 'XXXI'),
 27 |                      (148, 'CXLVIII'),
 28 |                      (294, 'CCXCIV'),
 29 |                      (312, 'CCCXII'),
 30 |                      (421, 'CDXXI'),
 31 |                      (528, 'DXXVIII'),
 32 |                      (621, 'DCXXI'),
 33 |                      (782, 'DCCLXXXII'),
 34 |                      (870, 'DCCCLXX'),
 35 |                      (941, 'CMXLI'),
 36 |                      (1043, 'MXLIII'),
 37 |                      (1110, 'MCX'),
 38 |                      (1226, 'MCCXXVI'),
 39 |                      (1301, 'MCCCI'),
 40 |                      (1485, 'MCDLXXXV'),
 41 |                      (1509, 'MDIX'),
 42 |                      (1607, 'MDCVII'),
 43 |                      (1754, 'MDCCLIV'),
 44 |                      (1832, 'MDCCCXXXII'),
 45 |                      (1993, 'MCMXCIII'),
 46 |                      (2074, 'MMLXXIV'),
 47 |                      (2152, 'MMCLII'),
 48 |                      (2212, 'MMCCXII'),
 49 |                      (2343, 'MMCCCXLIII'),
 50 |                      (2499, 'MMCDXCIX'),
 51 |                      (2574, 'MMDLXXIV'),
 52 |                      (2646, 'MMDCXLVI'),
 53 |                      (2723, 'MMDCCXXIII'),
 54 |                      (2892, 'MMDCCCXCII'),
 55 |                      (2975, 'MMCMLXXV'),
 56 |                      (3051, 'MMMLI'),
 57 |                      (3185, 'MMMCLXXXV'),
 58 |                      (3250, 'MMMCCL'),
 59 |                      (3313, 'MMMCCCXIII'),
 60 |                      (3408, 'MMMCDVIII'),
 61 |                      (3501, 'MMMDI'),
 62 |                      (3610, 'MMMDCX'),
 63 |                      (3743, 'MMMDCCXLIII'),
 64 |                      (3844, 'MMMDCCCXLIV'),
 65 |                      (3888, 'MMMDCCCLXXXVIII'),
 66 |                      (3940, 'MMMCMXL'),
 67 |                      (3999, 'MMMCMXCIX'))
 68 | 
 69 |     def test_to_roman_known_values(self):
 70 |         '''to_roman should give known result with known input'''
 71 |         for integer, numeral in self.known_values:
 72 |             result = roman3.to_roman(integer)
 73 |             self.assertEqual(numeral, result)
 74 | 
 75 | class ToRomanBadInput(unittest.TestCase):
 76 |     def test_too_large(self):
 77 |         '''to_roman should fail with large input'''
 78 |         self.assertRaises(roman3.OutOfRangeError, roman3.to_roman, 4000)
 79 | 
 80 |     def test_zero(self):
 81 |         '''to_roman should fail with 0 input'''
 82 |         self.assertRaises(roman3.OutOfRangeError, roman3.to_roman, 0)
 83 | 
 84 |     def test_negative(self):
 85 |         '''to_roman should fail with negative input'''
 86 |         self.assertRaises(roman3.OutOfRangeError, roman3.to_roman, -1)
 87 | 
 88 | if __name__ == '__main__':
 89 |     unittest.main()
 90 | 
 91 | # Copyright (c) 2009, Mark Pilgrim, All rights reserved.
 92 | # 
 93 | # Redistribution and use in source and binary forms, with or without modification,
 94 | # are permitted provided that the following conditions are met:
 95 | # 
 96 | # * Redistributions of source code must retain the above copyright notice,
 97 | #   this list of conditions and the following disclaimer.
 98 | # * Redistributions in binary form must reproduce the above copyright notice,
 99 | #   this list of conditions and the following disclaimer in the documentation
100 | #   and/or other materials provided with the distribution.
101 | # 
102 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS'
103 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
104 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
105 | # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
106 | # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
107 | # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
108 | # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
109 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
110 | # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
111 | # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
112 | # POSSIBILITY OF SUCH DAMAGE.
113 | 


--------------------------------------------------------------------------------
/examples/romantest4.py:
--------------------------------------------------------------------------------
  1 | '''Unit test for roman1.py
  2 | 
  3 | This program is part of 'Dive Into Python 3', a free Python book for
  4 | experienced programmers.  Visit http://diveintopython3.org/ for the
  5 | latest version.
  6 | '''
  7 | 
  8 | import roman4
  9 | import unittest
 10 | 
 11 | class KnownValues(unittest.TestCase):
 12 |     known_values = ( (1, 'I'),
 13 |                      (2, 'II'),
 14 |                      (3, 'III'),
 15 |                      (4, 'IV'),
 16 |                      (5, 'V'),
 17 |                      (6, 'VI'),
 18 |                      (7, 'VII'),
 19 |                      (8, 'VIII'),
 20 |                      (9, 'IX'),
 21 |                      (10, 'X'),
 22 |                      (50, 'L'),
 23 |                      (100, 'C'),
 24 |                      (500, 'D'),
 25 |                      (1000, 'M'),
 26 |                      (31, 'XXXI'),
 27 |                      (148, 'CXLVIII'),
 28 |                      (294, 'CCXCIV'),
 29 |                      (312, 'CCCXII'),
 30 |                      (421, 'CDXXI'),
 31 |                      (528, 'DXXVIII'),
 32 |                      (621, 'DCXXI'),
 33 |                      (782, 'DCCLXXXII'),
 34 |                      (870, 'DCCCLXX'),
 35 |                      (941, 'CMXLI'),
 36 |                      (1043, 'MXLIII'),
 37 |                      (1110, 'MCX'),
 38 |                      (1226, 'MCCXXVI'),
 39 |                      (1301, 'MCCCI'),
 40 |                      (1485, 'MCDLXXXV'),
 41 |                      (1509, 'MDIX'),
 42 |                      (1607, 'MDCVII'),
 43 |                      (1754, 'MDCCLIV'),
 44 |                      (1832, 'MDCCCXXXII'),
 45 |                      (1993, 'MCMXCIII'),
 46 |                      (2074, 'MMLXXIV'),
 47 |                      (2152, 'MMCLII'),
 48 |                      (2212, 'MMCCXII'),
 49 |                      (2343, 'MMCCCXLIII'),
 50 |                      (2499, 'MMCDXCIX'),
 51 |                      (2574, 'MMDLXXIV'),
 52 |                      (2646, 'MMDCXLVI'),
 53 |                      (2723, 'MMDCCXXIII'),
 54 |                      (2892, 'MMDCCCXCII'),
 55 |                      (2975, 'MMCMLXXV'),
 56 |                      (3051, 'MMMLI'),
 57 |                      (3185, 'MMMCLXXXV'),
 58 |                      (3250, 'MMMCCL'),
 59 |                      (3313, 'MMMCCCXIII'),
 60 |                      (3408, 'MMMCDVIII'),
 61 |                      (3501, 'MMMDI'),
 62 |                      (3610, 'MMMDCX'),
 63 |                      (3743, 'MMMDCCXLIII'),
 64 |                      (3844, 'MMMDCCCXLIV'),
 65 |                      (3888, 'MMMDCCCLXXXVIII'),
 66 |                      (3940, 'MMMCMXL'),
 67 |                      (3999, 'MMMCMXCIX'))
 68 | 
 69 |     def test_to_roman_known_values(self):
 70 |         '''to_roman should give known result with known input'''
 71 |         for integer, numeral in self.known_values:
 72 |             result = roman4.to_roman(integer)
 73 |             self.assertEqual(numeral, result)
 74 | 
 75 | class ToRomanBadInput(unittest.TestCase):
 76 |     def test_too_large(self):
 77 |         '''to_roman should fail with large input'''
 78 |         self.assertRaises(roman4.OutOfRangeError, roman4.to_roman, 4000)
 79 | 
 80 |     def test_zero(self):
 81 |         '''to_roman should fail with 0 input'''
 82 |         self.assertRaises(roman4.OutOfRangeError, roman4.to_roman, 0)
 83 | 
 84 |     def test_negative(self):
 85 |         '''to_roman should fail with negative input'''
 86 |         self.assertRaises(roman4.OutOfRangeError, roman4.to_roman, -1)
 87 | 
 88 |     def test_non_integer(self):
 89 |         '''to_roman should fail with non-integer input'''
 90 |         self.assertRaises(roman4.NotIntegerError, roman4.to_roman, 0.5)
 91 | 
 92 | if __name__ == '__main__':
 93 |     unittest.main()
 94 | 
 95 | # Copyright (c) 2009, Mark Pilgrim, All rights reserved.
 96 | # 
 97 | # Redistribution and use in source and binary forms, with or without modification,
 98 | # are permitted provided that the following conditions are met:
 99 | # 
100 | # * Redistributions of source code must retain the above copyright notice,
101 | #   this list of conditions and the following disclaimer.
102 | # * Redistributions in binary form must reproduce the above copyright notice,
103 | #   this list of conditions and the following disclaimer in the documentation
104 | #   and/or other materials provided with the distribution.
105 | # 
106 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS'
107 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
108 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
109 | # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
110 | # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
111 | # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
112 | # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
113 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
114 | # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
115 | # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
116 | # POSSIBILITY OF SUCH DAMAGE.
117 | 


--------------------------------------------------------------------------------
/examples/romantest5.py:
--------------------------------------------------------------------------------
  1 | '''Unit test for roman1.py
  2 | 
  3 | This program is part of 'Dive Into Python 3', a free Python book for
  4 | experienced programmers.  Visit http://diveintopython3.org/ for the
  5 | latest version.
  6 | '''
  7 | 
  8 | import roman5
  9 | import unittest
 10 | 
 11 | class KnownValues(unittest.TestCase):
 12 |     known_values = ( (1, 'I'),
 13 |                      (2, 'II'),
 14 |                      (3, 'III'),
 15 |                      (4, 'IV'),
 16 |                      (5, 'V'),
 17 |                      (6, 'VI'),
 18 |                      (7, 'VII'),
 19 |                      (8, 'VIII'),
 20 |                      (9, 'IX'),
 21 |                      (10, 'X'),
 22 |                      (50, 'L'),
 23 |                      (100, 'C'),
 24 |                      (500, 'D'),
 25 |                      (1000, 'M'),
 26 |                      (31, 'XXXI'),
 27 |                      (148, 'CXLVIII'),
 28 |                      (294, 'CCXCIV'),
 29 |                      (312, 'CCCXII'),
 30 |                      (421, 'CDXXI'),
 31 |                      (528, 'DXXVIII'),
 32 |                      (621, 'DCXXI'),
 33 |                      (782, 'DCCLXXXII'),
 34 |                      (870, 'DCCCLXX'),
 35 |                      (941, 'CMXLI'),
 36 |                      (1043, 'MXLIII'),
 37 |                      (1110, 'MCX'),
 38 |                      (1226, 'MCCXXVI'),
 39 |                      (1301, 'MCCCI'),
 40 |                      (1485, 'MCDLXXXV'),
 41 |                      (1509, 'MDIX'),
 42 |                      (1607, 'MDCVII'),
 43 |                      (1754, 'MDCCLIV'),
 44 |                      (1832, 'MDCCCXXXII'),
 45 |                      (1993, 'MCMXCIII'),
 46 |                      (2074, 'MMLXXIV'),
 47 |                      (2152, 'MMCLII'),
 48 |                      (2212, 'MMCCXII'),
 49 |                      (2343, 'MMCCCXLIII'),
 50 |                      (2499, 'MMCDXCIX'),
 51 |                      (2574, 'MMDLXXIV'),
 52 |                      (2646, 'MMDCXLVI'),
 53 |                      (2723, 'MMDCCXXIII'),
 54 |                      (2892, 'MMDCCCXCII'),
 55 |                      (2975, 'MMCMLXXV'),
 56 |                      (3051, 'MMMLI'),
 57 |                      (3185, 'MMMCLXXXV'),
 58 |                      (3250, 'MMMCCL'),
 59 |                      (3313, 'MMMCCCXIII'),
 60 |                      (3408, 'MMMCDVIII'),
 61 |                      (3501, 'MMMDI'),
 62 |                      (3610, 'MMMDCX'),
 63 |                      (3743, 'MMMDCCXLIII'),
 64 |                      (3844, 'MMMDCCCXLIV'),
 65 |                      (3888, 'MMMDCCCLXXXVIII'),
 66 |                      (3940, 'MMMCMXL'),
 67 |                      (3999, 'MMMCMXCIX'))
 68 | 
 69 |     def test_to_roman_known_values(self):
 70 |         '''to_roman should give known result with known input'''
 71 |         for integer, numeral in self.known_values:
 72 |             result = roman5.to_roman(integer)
 73 |             self.assertEqual(numeral, result)
 74 | 
 75 |     def test_from_roman_known_values(self):
 76 |         '''from_roman should give known result with known input'''
 77 |         for integer, numeral in self.known_values:
 78 |             result = roman5.from_roman(numeral)
 79 |             self.assertEqual(integer, result)
 80 | 
 81 | class ToRomanBadInput(unittest.TestCase):
 82 |     def test_too_large(self):
 83 |         '''to_roman should fail with large input'''
 84 |         self.assertRaises(roman5.OutOfRangeError, roman5.to_roman, 4000)
 85 | 
 86 |     def test_zero(self):
 87 |         '''to_roman should fail with 0 input'''
 88 |         self.assertRaises(roman5.OutOfRangeError, roman5.to_roman, 0)
 89 | 
 90 |     def test_negative(self):
 91 |         '''to_roman should fail with negative input'''
 92 |         self.assertRaises(roman5.OutOfRangeError, roman5.to_roman, -1)
 93 | 
 94 |     def test_non_integer(self):
 95 |         '''to_roman should fail with non-integer input'''
 96 |         self.assertRaises(roman5.NotIntegerError, roman5.to_roman, 0.5)
 97 | 
 98 | class RoundtripCheck(unittest.TestCase):
 99 |     def test_roundtrip(self):
100 |         '''from_roman(to_roman(n))==n for all n'''
101 |         for integer in range(1, 4000):
102 |             numeral = roman5.to_roman(integer)
103 |             result = roman5.from_roman(numeral)
104 |             self.assertEqual(integer, result)
105 | 
106 | if __name__ == '__main__':
107 |     unittest.main()
108 | 
109 | # Copyright (c) 2009, Mark Pilgrim, All rights reserved.
110 | # 
111 | # Redistribution and use in source and binary forms, with or without modification,
112 | # are permitted provided that the following conditions are met:
113 | # 
114 | # * Redistributions of source code must retain the above copyright notice,
115 | #   this list of conditions and the following disclaimer.
116 | # * Redistributions in binary form must reproduce the above copyright notice,
117 | #   this list of conditions and the following disclaimer in the documentation
118 | #   and/or other materials provided with the distribution.
119 | # 
120 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS'
121 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
122 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
123 | # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
124 | # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
125 | # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
126 | # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
127 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
128 | # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
129 | # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
130 | # POSSIBILITY OF SUCH DAMAGE.
131 | 


--------------------------------------------------------------------------------
/examples/romantest6.py:
--------------------------------------------------------------------------------
  1 | '''Unit test for roman1.py
  2 | 
  3 | This program is part of 'Dive Into Python 3', a free Python book for
  4 | experienced programmers.  Visit http://diveintopython3.org/ for the
  5 | latest version.
  6 | '''
  7 | 
  8 | import roman6
  9 | import unittest
 10 | 
 11 | class KnownValues(unittest.TestCase):
 12 |     known_values = ( (1, 'I'),
 13 |                      (2, 'II'),
 14 |                      (3, 'III'),
 15 |                      (4, 'IV'),
 16 |                      (5, 'V'),
 17 |                      (6, 'VI'),
 18 |                      (7, 'VII'),
 19 |                      (8, 'VIII'),
 20 |                      (9, 'IX'),
 21 |                      (10, 'X'),
 22 |                      (50, 'L'),
 23 |                      (100, 'C'),
 24 |                      (500, 'D'),
 25 |                      (1000, 'M'),
 26 |                      (31, 'XXXI'),
 27 |                      (148, 'CXLVIII'),
 28 |                      (294, 'CCXCIV'),
 29 |                      (312, 'CCCXII'),
 30 |                      (421, 'CDXXI'),
 31 |                      (528, 'DXXVIII'),
 32 |                      (621, 'DCXXI'),
 33 |                      (782, 'DCCLXXXII'),
 34 |                      (870, 'DCCCLXX'),
 35 |                      (941, 'CMXLI'),
 36 |                      (1043, 'MXLIII'),
 37 |                      (1110, 'MCX'),
 38 |                      (1226, 'MCCXXVI'),
 39 |                      (1301, 'MCCCI'),
 40 |                      (1485, 'MCDLXXXV'),
 41 |                      (1509, 'MDIX'),
 42 |                      (1607, 'MDCVII'),
 43 |                      (1754, 'MDCCLIV'),
 44 |                      (1832, 'MDCCCXXXII'),
 45 |                      (1993, 'MCMXCIII'),
 46 |                      (2074, 'MMLXXIV'),
 47 |                      (2152, 'MMCLII'),
 48 |                      (2212, 'MMCCXII'),
 49 |                      (2343, 'MMCCCXLIII'),
 50 |                      (2499, 'MMCDXCIX'),
 51 |                      (2574, 'MMDLXXIV'),
 52 |                      (2646, 'MMDCXLVI'),
 53 |                      (2723, 'MMDCCXXIII'),
 54 |                      (2892, 'MMDCCCXCII'),
 55 |                      (2975, 'MMCMLXXV'),
 56 |                      (3051, 'MMMLI'),
 57 |                      (3185, 'MMMCLXXXV'),
 58 |                      (3250, 'MMMCCL'),
 59 |                      (3313, 'MMMCCCXIII'),
 60 |                      (3408, 'MMMCDVIII'),
 61 |                      (3501, 'MMMDI'),
 62 |                      (3610, 'MMMDCX'),
 63 |                      (3743, 'MMMDCCXLIII'),
 64 |                      (3844, 'MMMDCCCXLIV'),
 65 |                      (3888, 'MMMDCCCLXXXVIII'),
 66 |                      (3940, 'MMMCMXL'),
 67 |                      (3999, 'MMMCMXCIX'))
 68 | 
 69 |     def test_to_roman_known_values(self):
 70 |         '''to_roman should give known result with known input'''
 71 |         for integer, numeral in self.known_values:
 72 |             result = roman6.to_roman(integer)
 73 |             self.assertEqual(numeral, result)
 74 | 
 75 |     def test_from_roman_known_values(self):
 76 |         '''from_roman should give known result with known input'''
 77 |         for integer, numeral in self.known_values:
 78 |             result = roman6.from_roman(numeral)
 79 |             self.assertEqual(integer, result)
 80 | 
 81 | class ToRomanBadInput(unittest.TestCase):
 82 |     def test_too_large(self):
 83 |         '''to_roman should fail with large input'''
 84 |         self.assertRaises(roman6.OutOfRangeError, roman6.to_roman, 4000)
 85 | 
 86 |     def test_zero(self):
 87 |         '''to_roman should fail with 0 input'''
 88 |         self.assertRaises(roman6.OutOfRangeError, roman6.to_roman, 0)
 89 | 
 90 |     def test_negative(self):
 91 |         '''to_roman should fail with negative input'''
 92 |         self.assertRaises(roman6.OutOfRangeError, roman6.to_roman, -1)
 93 | 
 94 |     def test_non_integer(self):
 95 |         '''to_roman should fail with non-integer input'''
 96 |         self.assertRaises(roman6.NotIntegerError, roman6.to_roman, 0.5)
 97 | 
 98 | class FromRomanBadInput(unittest.TestCase):
 99 |     def test_too_many_repeated_numerals(self):
100 |         '''from_roman should fail with too many repeated numerals'''
101 |         for s in ('MMMM', 'DD', 'CCCC', 'LL', 'XXXX', 'VV', 'IIII'):
102 |             self.assertRaises(roman6.InvalidRomanNumeralError, roman6.from_roman, s)
103 | 
104 |     def test_repeated_pairs(self):
105 |         '''from_roman should fail with repeated pairs of numerals'''
106 |         for s in ('CMCM', 'CDCD', 'XCXC', 'XLXL', 'IXIX', 'IVIV'):
107 |             self.assertRaises(roman6.InvalidRomanNumeralError, roman6.from_roman, s)
108 | 
109 |     def test_malformed_antecedents(self):
110 |         '''from_roman should fail with malformed antecedents'''
111 |         for s in ('IIMXCC', 'VX', 'DCM', 'CMM', 'IXIV',
112 |                   'MCMC', 'XCX', 'IVI', 'LM', 'LD', 'LC'):
113 |             self.assertRaises(roman6.InvalidRomanNumeralError, roman6.from_roman, s)
114 | 
115 | class RoundtripCheck(unittest.TestCase):
116 |     def test_roundtrip(self):
117 |         '''from_roman(to_roman(n))==n for all n'''
118 |         for integer in range(1, 4000):
119 |             numeral = roman6.to_roman(integer)
120 |             result = roman6.from_roman(numeral)
121 |             self.assertEqual(integer, result)
122 | 
123 | if __name__ == '__main__':
124 |     unittest.main()
125 | 
126 | # Copyright (c) 2009, Mark Pilgrim, All rights reserved.
127 | # 
128 | # Redistribution and use in source and binary forms, with or without modification,
129 | # are permitted provided that the following conditions are met:
130 | # 
131 | # * Redistributions of source code must retain the above copyright notice,
132 | #   this list of conditions and the following disclaimer.
133 | # * Redistributions in binary form must reproduce the above copyright notice,
134 | #   this list of conditions and the following disclaimer in the documentation
135 | #   and/or other materials provided with the distribution.
136 | # 
137 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS'
138 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
139 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
140 | # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
141 | # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
142 | # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
143 | # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
144 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
145 | # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
146 | # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
147 | # POSSIBILITY OF SUCH DAMAGE.
148 | 


--------------------------------------------------------------------------------
/examples/romantest7.py:
--------------------------------------------------------------------------------
  1 | '''Unit test for roman1.py
  2 | 
  3 | This program is part of 'Dive Into Python 3', a free Python book for
  4 | experienced programmers.  Visit http://diveintopython3.org/ for the
  5 | latest version.
  6 | '''
  7 | 
  8 | import roman7
  9 | import unittest
 10 | 
 11 | class KnownValues(unittest.TestCase):
 12 |     known_values = ( (1, 'I'),
 13 |                      (2, 'II'),
 14 |                      (3, 'III'),
 15 |                      (4, 'IV'),
 16 |                      (5, 'V'),
 17 |                      (6, 'VI'),
 18 |                      (7, 'VII'),
 19 |                      (8, 'VIII'),
 20 |                      (9, 'IX'),
 21 |                      (10, 'X'),
 22 |                      (50, 'L'),
 23 |                      (100, 'C'),
 24 |                      (500, 'D'),
 25 |                      (1000, 'M'),
 26 |                      (31, 'XXXI'),
 27 |                      (148, 'CXLVIII'),
 28 |                      (294, 'CCXCIV'),
 29 |                      (312, 'CCCXII'),
 30 |                      (421, 'CDXXI'),
 31 |                      (528, 'DXXVIII'),
 32 |                      (621, 'DCXXI'),
 33 |                      (782, 'DCCLXXXII'),
 34 |                      (870, 'DCCCLXX'),
 35 |                      (941, 'CMXLI'),
 36 |                      (1043, 'MXLIII'),
 37 |                      (1110, 'MCX'),
 38 |                      (1226, 'MCCXXVI'),
 39 |                      (1301, 'MCCCI'),
 40 |                      (1485, 'MCDLXXXV'),
 41 |                      (1509, 'MDIX'),
 42 |                      (1607, 'MDCVII'),
 43 |                      (1754, 'MDCCLIV'),
 44 |                      (1832, 'MDCCCXXXII'),
 45 |                      (1993, 'MCMXCIII'),
 46 |                      (2074, 'MMLXXIV'),
 47 |                      (2152, 'MMCLII'),
 48 |                      (2212, 'MMCCXII'),
 49 |                      (2343, 'MMCCCXLIII'),
 50 |                      (2499, 'MMCDXCIX'),
 51 |                      (2574, 'MMDLXXIV'),
 52 |                      (2646, 'MMDCXLVI'),
 53 |                      (2723, 'MMDCCXXIII'),
 54 |                      (2892, 'MMDCCCXCII'),
 55 |                      (2975, 'MMCMLXXV'),
 56 |                      (3051, 'MMMLI'),
 57 |                      (3185, 'MMMCLXXXV'),
 58 |                      (3250, 'MMMCCL'),
 59 |                      (3313, 'MMMCCCXIII'),
 60 |                      (3408, 'MMMCDVIII'),
 61 |                      (3501, 'MMMDI'),
 62 |                      (3610, 'MMMDCX'),
 63 |                      (3743, 'MMMDCCXLIII'),
 64 |                      (3844, 'MMMDCCCXLIV'),
 65 |                      (3888, 'MMMDCCCLXXXVIII'),
 66 |                      (3940, 'MMMCMXL'),
 67 |                      (3999, 'MMMCMXCIX'))
 68 | 
 69 |     def test_to_roman_known_values(self):
 70 |         '''to_roman should give known result with known input'''
 71 |         for integer, numeral in self.known_values:
 72 |             result = roman7.to_roman(integer)
 73 |             self.assertEqual(numeral, result)
 74 | 
 75 |     def test_from_roman_known_values(self):
 76 |         '''from_roman should give known result with known input'''
 77 |         for integer, numeral in self.known_values:
 78 |             result = roman7.from_roman(numeral)
 79 |             self.assertEqual(integer, result)
 80 | 
 81 | class ToRomanBadInput(unittest.TestCase):
 82 |     def test_too_large(self):
 83 |         '''to_roman should fail with large input'''
 84 |         self.assertRaises(roman7.OutOfRangeError, roman7.to_roman, 4000)
 85 | 
 86 |     def test_zero(self):
 87 |         '''to_roman should fail with 0 input'''
 88 |         self.assertRaises(roman7.OutOfRangeError, roman7.to_roman, 0)
 89 | 
 90 |     def test_negative(self):
 91 |         '''to_roman should fail with negative input'''
 92 |         self.assertRaises(roman7.OutOfRangeError, roman7.to_roman, -1)
 93 | 
 94 |     def test_non_integer(self):
 95 |         '''to_roman should fail with non-integer input'''
 96 |         self.assertRaises(roman7.NotIntegerError, roman7.to_roman, 0.5)
 97 | 
 98 | class FromRomanBadInput(unittest.TestCase):
 99 |     def test_too_many_repeated_numerals(self):
100 |         '''from_roman should fail with too many repeated numerals'''
101 |         for s in ('MMMM', 'DD', 'CCCC', 'LL', 'XXXX', 'VV', 'IIII'):
102 |             self.assertRaises(roman7.InvalidRomanNumeralError, roman7.from_roman, s)
103 | 
104 |     def test_repeated_pairs(self):
105 |         '''from_roman should fail with repeated pairs of numerals'''
106 |         for s in ('CMCM', 'CDCD', 'XCXC', 'XLXL', 'IXIX', 'IVIV'):
107 |             self.assertRaises(roman7.InvalidRomanNumeralError, roman7.from_roman, s)
108 | 
109 |     def test_malformed_antecedents(self):
110 |         '''from_roman should fail with malformed antecedents'''
111 |         for s in ('IIMXCC', 'VX', 'DCM', 'CMM', 'IXIV',
112 |                   'MCMC', 'XCX', 'IVI', 'LM', 'LD', 'LC'):
113 |             self.assertRaises(roman7.InvalidRomanNumeralError, roman7.from_roman, s)
114 | 
115 |     def test_non_string(self):
116 |         '''from_roman should fail with non-string input'''
117 |         self.assertRaises(roman7.InvalidRomanNumeralError, roman7.from_roman, 1)
118 | 
119 | class RoundtripCheck(unittest.TestCase):
120 |     def test_roundtrip(self):
121 |         '''from_roman(to_roman(n))==n for all n'''
122 |         for integer in range(1, 4000):
123 |             numeral = roman7.to_roman(integer)
124 |             result = roman7.from_roman(numeral)
125 |             self.assertEqual(integer, result)
126 | 
127 | if __name__ == '__main__':
128 |     unittest.main()
129 | 
130 | # Copyright (c) 2009, Mark Pilgrim, All rights reserved.
131 | # 
132 | # Redistribution and use in source and binary forms, with or without modification,
133 | # are permitted provided that the following conditions are met:
134 | # 
135 | # * Redistributions of source code must retain the above copyright notice,
136 | #   this list of conditions and the following disclaimer.
137 | # * Redistributions in binary form must reproduce the above copyright notice,
138 | #   this list of conditions and the following disclaimer in the documentation
139 | #   and/or other materials provided with the distribution.
140 | # 
141 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS'
142 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
143 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
144 | # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
145 | # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
146 | # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
147 | # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
148 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
149 | # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
150 | # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
151 | # POSSIBILITY OF SUCH DAMAGE.
152 | 


--------------------------------------------------------------------------------
/examples/stdout.py:
--------------------------------------------------------------------------------
 1 | import sys
 2 | 
 3 | class RedirectStdoutTo:
 4 |     def __init__(self, out_new):
 5 |         self.out_new = out_new
 6 | 
 7 |     def __enter__(self):
 8 |         self.out_old = sys.stdout
 9 |         sys.stdout = self.out_new
10 | 
11 |     def __exit__(self, *args):
12 |         sys.stdout = self.out_old
13 | 
14 | print('A')
15 | with open('out.log', mode='w', encoding='utf-8') as a_file, RedirectStdoutTo(a_file):
16 |     print('B')
17 | print('C')
18 | 


--------------------------------------------------------------------------------
/i/.htaccess:
--------------------------------------------------------------------------------
1 | FileETag MTime Size
2 | 
3 | ExpiresActive On
4 | ExpiresDefault "access plus 1 year"
5 | 


--------------------------------------------------------------------------------
/i/cover.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kennethreitz/dive-into-python3/67ef8e6df7adcafec77b8994ee4a79c59d625c45/i/cover.jpg


--------------------------------------------------------------------------------
/i/identica-deleted.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kennethreitz/dive-into-python3/67ef8e6df7adcafec77b8994ee4a79c59d625c45/i/identica-deleted.png


--------------------------------------------------------------------------------
/i/identica-screenshot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kennethreitz/dive-into-python3/67ef8e6df7adcafec77b8994ee4a79c59d625c45/i/identica-screenshot.png


--------------------------------------------------------------------------------
/i/mac-install-0-dmg-contents.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kennethreitz/dive-into-python3/67ef8e6df7adcafec77b8994ee4a79c59d625c45/i/mac-install-0-dmg-contents.png


--------------------------------------------------------------------------------
/i/mac-install-1-welcome.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kennethreitz/dive-into-python3/67ef8e6df7adcafec77b8994ee4a79c59d625c45/i/mac-install-1-welcome.png


--------------------------------------------------------------------------------
/i/mac-install-10-application-folder.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kennethreitz/dive-into-python3/67ef8e6df7adcafec77b8994ee4a79c59d625c45/i/mac-install-10-application-folder.png


--------------------------------------------------------------------------------
/i/mac-install-2-information.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kennethreitz/dive-into-python3/67ef8e6df7adcafec77b8994ee4a79c59d625c45/i/mac-install-2-information.png


--------------------------------------------------------------------------------
/i/mac-install-3-license.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kennethreitz/dive-into-python3/67ef8e6df7adcafec77b8994ee4a79c59d625c45/i/mac-install-3-license.png


--------------------------------------------------------------------------------
/i/mac-install-4-license-dialog.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kennethreitz/dive-into-python3/67ef8e6df7adcafec77b8994ee4a79c59d625c45/i/mac-install-4-license-dialog.png


--------------------------------------------------------------------------------
/i/mac-install-5-standard-install.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kennethreitz/dive-into-python3/67ef8e6df7adcafec77b8994ee4a79c59d625c45/i/mac-install-5-standard-install.png


--------------------------------------------------------------------------------
/i/mac-install-6-custom-install.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kennethreitz/dive-into-python3/67ef8e6df7adcafec77b8994ee4a79c59d625c45/i/mac-install-6-custom-install.png


--------------------------------------------------------------------------------
/i/mac-install-7-admin-password.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kennethreitz/dive-into-python3/67ef8e6df7adcafec77b8994ee4a79c59d625c45/i/mac-install-7-admin-password.png


--------------------------------------------------------------------------------
/i/mac-install-8-progress.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kennethreitz/dive-into-python3/67ef8e6df7adcafec77b8994ee4a79c59d625c45/i/mac-install-8-progress.png


--------------------------------------------------------------------------------
/i/mac-install-9-succeeded.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kennethreitz/dive-into-python3/67ef8e6df7adcafec77b8994ee4a79c59d625c45/i/mac-install-9-succeeded.png


--------------------------------------------------------------------------------
/i/mac-interactive-shell.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kennethreitz/dive-into-python3/67ef8e6df7adcafec77b8994ee4a79c59d625c45/i/mac-interactive-shell.png


--------------------------------------------------------------------------------
/i/mac-pythonlauncher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kennethreitz/dive-into-python3/67ef8e6df7adcafec77b8994ee4a79c59d625c45/i/mac-pythonlauncher.png


--------------------------------------------------------------------------------
/i/openclipart.org_media_files_Selanit_8331.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kennethreitz/dive-into-python3/67ef8e6df7adcafec77b8994ee4a79c59d625c45/i/openclipart.org_media_files_Selanit_8331.png


--------------------------------------------------------------------------------
/i/openclipart.org_media_files_johnny_automatic_5154.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kennethreitz/dive-into-python3/67ef8e6df7adcafec77b8994ee4a79c59d625c45/i/openclipart.org_media_files_johnny_automatic_5154.png


--------------------------------------------------------------------------------
/i/openclipart.org_media_files_johnny_automatic_5261.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kennethreitz/dive-into-python3/67ef8e6df7adcafec77b8994ee4a79c59d625c45/i/openclipart.org_media_files_johnny_automatic_5261.png


--------------------------------------------------------------------------------
/i/ubu-install-0-add-remove-programs.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kennethreitz/dive-into-python3/67ef8e6df7adcafec77b8994ee4a79c59d625c45/i/ubu-install-0-add-remove-programs.png


--------------------------------------------------------------------------------
/i/ubu-install-1-all-open-source-applications.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kennethreitz/dive-into-python3/67ef8e6df7adcafec77b8994ee4a79c59d625c45/i/ubu-install-1-all-open-source-applications.png


--------------------------------------------------------------------------------
/i/ubu-install-2-search-python-3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kennethreitz/dive-into-python3/67ef8e6df7adcafec77b8994ee4a79c59d625c45/i/ubu-install-2-search-python-3.png


--------------------------------------------------------------------------------
/i/ubu-install-3-select-python-3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kennethreitz/dive-into-python3/67ef8e6df7adcafec77b8994ee4a79c59d625c45/i/ubu-install-3-select-python-3.png


--------------------------------------------------------------------------------
/i/ubu-install-4-select-idle.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kennethreitz/dive-into-python3/67ef8e6df7adcafec77b8994ee4a79c59d625c45/i/ubu-install-4-select-idle.png


--------------------------------------------------------------------------------
/i/ubu-install-5-apply-changes.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kennethreitz/dive-into-python3/67ef8e6df7adcafec77b8994ee4a79c59d625c45/i/ubu-install-5-apply-changes.png


--------------------------------------------------------------------------------
/i/ubu-install-6-download-progress.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kennethreitz/dive-into-python3/67ef8e6df7adcafec77b8994ee4a79c59d625c45/i/ubu-install-6-download-progress.png


--------------------------------------------------------------------------------
/i/ubu-install-7-install-progress.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kennethreitz/dive-into-python3/67ef8e6df7adcafec77b8994ee4a79c59d625c45/i/ubu-install-7-install-progress.png


--------------------------------------------------------------------------------
/i/ubu-install-8-success.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kennethreitz/dive-into-python3/67ef8e6df7adcafec77b8994ee4a79c59d625c45/i/ubu-install-8-success.png


--------------------------------------------------------------------------------
/i/ubu-interactive-shell.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kennethreitz/dive-into-python3/67ef8e6df7adcafec77b8994ee4a79c59d625c45/i/ubu-interactive-shell.png


--------------------------------------------------------------------------------
/i/win-install-0-security-warning.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kennethreitz/dive-into-python3/67ef8e6df7adcafec77b8994ee4a79c59d625c45/i/win-install-0-security-warning.png


--------------------------------------------------------------------------------
/i/win-install-1-all-users-or-just-me.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kennethreitz/dive-into-python3/67ef8e6df7adcafec77b8994ee4a79c59d625c45/i/win-install-1-all-users-or-just-me.png


--------------------------------------------------------------------------------
/i/win-install-2-destination-directory.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kennethreitz/dive-into-python3/67ef8e6df7adcafec77b8994ee4a79c59d625c45/i/win-install-2-destination-directory.png


--------------------------------------------------------------------------------
/i/win-install-3-customize.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kennethreitz/dive-into-python3/67ef8e6df7adcafec77b8994ee4a79c59d625c45/i/win-install-3-customize.png


--------------------------------------------------------------------------------
/i/win-install-3a-disk-usage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kennethreitz/dive-into-python3/67ef8e6df7adcafec77b8994ee4a79c59d625c45/i/win-install-3a-disk-usage.png


--------------------------------------------------------------------------------
/i/win-install-3b-test-suite.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kennethreitz/dive-into-python3/67ef8e6df7adcafec77b8994ee4a79c59d625c45/i/win-install-3b-test-suite.png


--------------------------------------------------------------------------------
/i/win-install-4-copying.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kennethreitz/dive-into-python3/67ef8e6df7adcafec77b8994ee4a79c59d625c45/i/win-install-4-copying.png


--------------------------------------------------------------------------------
/i/win-install-5-finish.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kennethreitz/dive-into-python3/67ef8e6df7adcafec77b8994ee4a79c59d625c45/i/win-install-5-finish.png


--------------------------------------------------------------------------------
/i/win-interactive-shell.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kennethreitz/dive-into-python3/67ef8e6df7adcafec77b8994ee4a79c59d625c45/i/win-interactive-shell.png


--------------------------------------------------------------------------------
/images-original/mac-install-0-dmg-contents.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kennethreitz/dive-into-python3/67ef8e6df7adcafec77b8994ee4a79c59d625c45/images-original/mac-install-0-dmg-contents.png


--------------------------------------------------------------------------------
/images-original/mac-install-1-welcome.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kennethreitz/dive-into-python3/67ef8e6df7adcafec77b8994ee4a79c59d625c45/images-original/mac-install-1-welcome.png


--------------------------------------------------------------------------------
/images-original/mac-install-10-application-folder.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kennethreitz/dive-into-python3/67ef8e6df7adcafec77b8994ee4a79c59d625c45/images-original/mac-install-10-application-folder.png


--------------------------------------------------------------------------------
/images-original/mac-install-2-information.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kennethreitz/dive-into-python3/67ef8e6df7adcafec77b8994ee4a79c59d625c45/images-original/mac-install-2-information.png


--------------------------------------------------------------------------------
/images-original/mac-install-3-license.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kennethreitz/dive-into-python3/67ef8e6df7adcafec77b8994ee4a79c59d625c45/images-original/mac-install-3-license.png


--------------------------------------------------------------------------------
/images-original/mac-install-4-license-dialog.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kennethreitz/dive-into-python3/67ef8e6df7adcafec77b8994ee4a79c59d625c45/images-original/mac-install-4-license-dialog.png


--------------------------------------------------------------------------------
/images-original/mac-install-5-standard-install.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kennethreitz/dive-into-python3/67ef8e6df7adcafec77b8994ee4a79c59d625c45/images-original/mac-install-5-standard-install.png


--------------------------------------------------------------------------------
/images-original/mac-install-6-custom-install.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kennethreitz/dive-into-python3/67ef8e6df7adcafec77b8994ee4a79c59d625c45/images-original/mac-install-6-custom-install.png


--------------------------------------------------------------------------------
/images-original/mac-install-7-admin-password.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kennethreitz/dive-into-python3/67ef8e6df7adcafec77b8994ee4a79c59d625c45/images-original/mac-install-7-admin-password.png


--------------------------------------------------------------------------------
/images-original/mac-install-8-progress.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kennethreitz/dive-into-python3/67ef8e6df7adcafec77b8994ee4a79c59d625c45/images-original/mac-install-8-progress.png


--------------------------------------------------------------------------------
/images-original/mac-install-9-succeeded.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kennethreitz/dive-into-python3/67ef8e6df7adcafec77b8994ee4a79c59d625c45/images-original/mac-install-9-succeeded.png


--------------------------------------------------------------------------------
/images-original/mac-interactive-shell.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kennethreitz/dive-into-python3/67ef8e6df7adcafec77b8994ee4a79c59d625c45/images-original/mac-interactive-shell.png


--------------------------------------------------------------------------------
/images-original/mac-pythonlauncher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kennethreitz/dive-into-python3/67ef8e6df7adcafec77b8994ee4a79c59d625c45/images-original/mac-pythonlauncher.png


--------------------------------------------------------------------------------
/images-original/ubu-install-0-add-remove-programs.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kennethreitz/dive-into-python3/67ef8e6df7adcafec77b8994ee4a79c59d625c45/images-original/ubu-install-0-add-remove-programs.png


--------------------------------------------------------------------------------
/images-original/ubu-install-1-all-open-source-applications.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kennethreitz/dive-into-python3/67ef8e6df7adcafec77b8994ee4a79c59d625c45/images-original/ubu-install-1-all-open-source-applications.png


--------------------------------------------------------------------------------
/images-original/ubu-install-2-search-python-3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kennethreitz/dive-into-python3/67ef8e6df7adcafec77b8994ee4a79c59d625c45/images-original/ubu-install-2-search-python-3.png


--------------------------------------------------------------------------------
/images-original/ubu-install-3-select-python-3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kennethreitz/dive-into-python3/67ef8e6df7adcafec77b8994ee4a79c59d625c45/images-original/ubu-install-3-select-python-3.png


--------------------------------------------------------------------------------
/images-original/ubu-install-4-select-idle.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kennethreitz/dive-into-python3/67ef8e6df7adcafec77b8994ee4a79c59d625c45/images-original/ubu-install-4-select-idle.png


--------------------------------------------------------------------------------
/images-original/ubu-install-5-apply-changes.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kennethreitz/dive-into-python3/67ef8e6df7adcafec77b8994ee4a79c59d625c45/images-original/ubu-install-5-apply-changes.png


--------------------------------------------------------------------------------
/images-original/ubu-install-6-download-progress.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kennethreitz/dive-into-python3/67ef8e6df7adcafec77b8994ee4a79c59d625c45/images-original/ubu-install-6-download-progress.png


--------------------------------------------------------------------------------
/images-original/ubu-install-7-install-progress.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kennethreitz/dive-into-python3/67ef8e6df7adcafec77b8994ee4a79c59d625c45/images-original/ubu-install-7-install-progress.png


--------------------------------------------------------------------------------
/images-original/ubu-install-8-success.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kennethreitz/dive-into-python3/67ef8e6df7adcafec77b8994ee4a79c59d625c45/images-original/ubu-install-8-success.png


--------------------------------------------------------------------------------
/images-original/ubu-interactive-shell.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kennethreitz/dive-into-python3/67ef8e6df7adcafec77b8994ee4a79c59d625c45/images-original/ubu-interactive-shell.png


--------------------------------------------------------------------------------
/images-original/win-install-0-security-warning.bmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kennethreitz/dive-into-python3/67ef8e6df7adcafec77b8994ee4a79c59d625c45/images-original/win-install-0-security-warning.bmp


--------------------------------------------------------------------------------
/images-original/win-install-1-all-users-or-just-me.bmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kennethreitz/dive-into-python3/67ef8e6df7adcafec77b8994ee4a79c59d625c45/images-original/win-install-1-all-users-or-just-me.bmp


--------------------------------------------------------------------------------
/images-original/win-install-2-destination-directory.bmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kennethreitz/dive-into-python3/67ef8e6df7adcafec77b8994ee4a79c59d625c45/images-original/win-install-2-destination-directory.bmp


--------------------------------------------------------------------------------
/images-original/win-install-3-customize.bmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kennethreitz/dive-into-python3/67ef8e6df7adcafec77b8994ee4a79c59d625c45/images-original/win-install-3-customize.bmp


--------------------------------------------------------------------------------
/images-original/win-install-3a-disk-usage.bmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kennethreitz/dive-into-python3/67ef8e6df7adcafec77b8994ee4a79c59d625c45/images-original/win-install-3a-disk-usage.bmp


--------------------------------------------------------------------------------
/images-original/win-install-3b-test-suite.bmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kennethreitz/dive-into-python3/67ef8e6df7adcafec77b8994ee4a79c59d625c45/images-original/win-install-3b-test-suite.bmp


--------------------------------------------------------------------------------
/images-original/win-install-4-copying.bmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kennethreitz/dive-into-python3/67ef8e6df7adcafec77b8994ee4a79c59d625c45/images-original/win-install-4-copying.bmp


--------------------------------------------------------------------------------
/images-original/win-install-5-finish.bmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kennethreitz/dive-into-python3/67ef8e6df7adcafec77b8994ee4a79c59d625c45/images-original/win-install-5-finish.bmp


--------------------------------------------------------------------------------
/images-original/win-interactive-shell.bmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kennethreitz/dive-into-python3/67ef8e6df7adcafec77b8994ee4a79c59d625c45/images-original/win-interactive-shell.bmp


--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
 1 | 
 2 | 
 3 | Dive Into Python 3
 4 | 
 5 | 
 6 | 
14 | 
15 | 
16 | 
17 | 
 
18 | 19 |

You are here:   20 | 21 |

Dive Into Python 3

22 | 23 |

Dive Into Python 3 covers Python 3 and its differences from Python 2. Compared to Dive Into Python, it’s about 20% revised and 80% new material. The book is now complete, but feedback is always welcome. 24 | 25 |

Table of Contents (expand)

26 | 27 |

Also available on dead trees!
Dive Into Python 3
28 | 29 | 30 |

    31 |
  1. What’s New in “Dive Into Python 3” 32 |
  2. Installing Python 33 |
  3. Your First Python Program 34 |
  4. Native Datatypes 35 |
  5. Comprehensions 36 |
  6. Strings 37 |
  7. Regular Expressions 38 |
  8. Closures & Generators 39 |
  9. Classes & Iterators 40 |
  10. Advanced Iterators 41 |
  11. Unit Testing 42 |
  12. Refactoring 43 |
  13. Files 44 |
  14. XML 45 |
  15. Serializing Python Objects 46 |
  16. HTTP Web Services 47 |
  17. Case Study: Porting chardet to Python 3 48 |
  18. Packaging Python Libraries 49 |
  19. Porting Code to Python 3 with 2to3 50 |
  20. Special Method Names 51 |
  21. Where to Go From Here 52 |
  22. Troubleshooting 53 |
54 | 55 | 56 |

The book is freely licensed under the Creative Commons Attribution Share-Alike license. You can download it as HTML or PDF. Über-geeks can also clone the Git repository: 57 | 58 |

you@localhost:~$ git clone git://github.com/diveintomark/diveintopython3.git
59 | 60 |

© 2001–11 Mark Pilgrim 61 | 62 |

Translations: en español, in italiano, на русском языке, به پارسی, česky 63 | -------------------------------------------------------------------------------- /j/.htaccess: -------------------------------------------------------------------------------- 1 | FileETag MTime Size 2 | 3 | ExpiresActive On 4 | ExpiresDefault "access plus 1 year" 5 | -------------------------------------------------------------------------------- /j/ga.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /j/html5.js: -------------------------------------------------------------------------------- 1 | /*@cc_on@if(@_jscript_version<9)(function(p,e){function q(a,b){if(g[a])g[a].styleSheet.cssText+=b;else{var c=r[l],d=e[j]("style");d.media=a;c.insertBefore(d,c[l]);g[a]=d;q(a,b)}}function s(a,b){for(var c=new RegExp("\\b("+m+")\\b(?!.*[;}])","gi"),d=function(k){return".iepp_"+k},h=-1;++h\\s*$","i");i.innerHTML=a.outerHTML.replace(/\r|\n/g," ").replace(c,a.currentStyle.display=="block"?"":"");c=i.childNodes[0];c.className+=" iepp_"+d;c=f[f.length]=[a,c];a.parentNode.replaceChild(c[1],c[0])}s(e.styleSheets,"all")}function u(){for(var a=-1,b;++aAlso available on dead trees!
Dive Into Python 3
2 | -------------------------------------------------------------------------------- /layout.css: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | "Dive Into Python 3" layout stylesheet 4 | 5 | Copyright (c) 2009, Mark Pilgrim, All rights reserved. 6 | 7 | Redistribution and use in source and binary forms, with or without modification, 8 | are permitted provided that the following conditions are met: 9 | 10 | * Redistributions of source code must retain the above copyright notice, 11 | this list of conditions and the following disclaimer. 12 | * Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' 17 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | @page { 30 | size: US-Letter; 31 | margin: 1.75in; 32 | padding: 0; 33 | @bottom-center { 34 | font: 12pt/1.75 serif; 35 | content: counter(page); 36 | } 37 | } 38 | body, .w a { 39 | font: 10pt/1.3 serif; 40 | } 41 | pre, kbd, samp, code, var, .b { 42 | font: 8pt/1.3 monospace; 43 | } 44 | span { 45 | font-size: 10pt; 46 | } 47 | .baa { 48 | font-size: 11pt; 49 | } 50 | .q span { 51 | font-size: 13pt; 52 | } 53 | .f:first-letter { 54 | color: #888; 55 | font: normal 48pt/0.68 serif; 56 | } 57 | p, ul, ol { 58 | margin: 0; 59 | font-size: 11pt; 60 | } 61 | p + p { 62 | text-indent: 1em; 63 | } 64 | 65 | h1 { 66 | page-break-before: always; 67 | prince-bookmark-level: 1; 68 | } 69 | h2 { 70 | prince-bookmark-level: 2; 71 | } 72 | h3 { 73 | prince-bookmark-level: 3; 74 | } 75 | -------------------------------------------------------------------------------- /mobile.css: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | "Dive Into Python 3" mobile stylesheet for iPhone, Android, and other 4 | small-screen devices 5 | 6 | Copyright (c) 2009, Mark Pilgrim, All rights reserved. 7 | 8 | Redistribution and use in source and binary forms, with or without modification, 9 | are permitted provided that the following conditions are met: 10 | 11 | * Redistributions of source code must retain the above copyright notice, 12 | this list of conditions and the following disclaimer. 13 | * Redistributions in binary form must reproduce the above copyright notice, 14 | this list of conditions and the following disclaimer in the documentation 15 | and/or other materials provided with the distribution. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' 18 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 21 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 | POSSIBILITY OF SUCH DAMAGE. 28 | 29 | 30 | Acknowledgements & Inspirations 31 | 32 | "Return of the Mobile Style Sheet" ....................... http://www.alistapart.com/articles/returnofthemobilestylesheet 33 | "Optimizing Web Content Using Conditional CSS" ........... http://developer.apple.com/safari/library/documentation/AppleApplications/Reference/SafariWebContent/OptimizingforSafarioniPhone/chapter_3_section_2.html 34 | */ 35 | 36 | /* typography */ 37 | 38 | body, .c, span, pre span, .c, .note, p, ul, ol { 39 | font:normal 12px/18px sans-serif; 40 | } 41 | pre, kbd, samp, code, var { 42 | font:normal 12px/18px monospace; 43 | } 44 | .baa { 45 | font:normal 14px/18px serif; 46 | } 47 | abbr { 48 | font-variant:normal; 49 | text-transform:none; 50 | letter-spacing:0; 51 | } 52 | .c, .note, p, ul, ol, h2, h3 { 53 | margin:1.75em 0; 54 | } 55 | 56 | /* basics */ 57 | 58 | html { 59 | color:#000; 60 | } 61 | body { 62 | margin:4px 2px 0 2px; 63 | } 64 | 65 | /* links */ 66 | 67 | a { 68 | text-decoration:underline; 69 | border-bottom:0; 70 | } 71 | pre a { 72 | text-decoration:none; 73 | } 74 | 75 | /* headers and pullquotes */ 76 | 77 | h1, h2, h3, pre { 78 | padding:0; 79 | border:0; 80 | letter-spacing:0; 81 | } 82 | h1 { 83 | margin:0; 84 | } 85 | h1, h1 code { 86 | font:normal 18px/18px serif; 87 | } 88 | h2, h2 code { 89 | font:normal 16px/18px serif; 90 | } 91 | h3, h3 code { 92 | font:normal 14px/18px serif; 93 | } 94 | h1:before { 95 | content:""; 96 | } 97 | 98 | /* overrides */ 99 | 100 | .nm, .w, aside, form, form+p, .note span, .q span, .a { 101 | display:none; 102 | } 103 | dd { 104 | margin:0 0 0 1.75em; 105 | } 106 | .nav span { 107 | font-size:200%; 108 | } 109 | .xxxl { 110 | font-size: xx-large; 111 | line-height: 0.875; 112 | } 113 | -------------------------------------------------------------------------------- /notes.txt: -------------------------------------------------------------------------------- 1 | Python 3.1: 2 | OrderedDict 3 | "".format() auto-numbered format specifiers 4 | unittest: assertRaises context block (?) 5 | importlib 6 | (possibly) yield from 7 | (possibly) IP address library 8 | 9 | http://www.alanwood.net/unicode/general_punctuation.html 10 | http://www.alanwood.net/unicode/arrows.html 11 | http://www.alanwood.net/unicode/miscellaneous_technical.html 12 | http://www.alanwood.net/unicode/miscellaneous_symbols.html 13 | http://www.alanwood.net/unicode/mathematical_operators.html 14 | http://www.alanwood.net/unicode/dingbats.html 15 | 16 | ⚠ - white warning sign (triangle with exclamation point inside) 17 | ☺ - white smiling face 18 | ☜ - white left pointing index 19 | ☞ - white right pointing index 20 | ☚ - black left pointing index 21 | ☛ - black right pointing index 22 | ☠ - skull and crossbones 23 | ☑ - ballot box with checkmark 24 | ⚐ - white flag 25 | ⚑ - black flag 26 | ⍟ - APL circle star 27 | ✪ - circled white star 28 | ∴ - therefore (three dots in a triangle) 29 | ‽ - interrobang 30 | ❝ - heavy double turned left comma quotation mark ornament 31 | ❞ - heavy double turned right comma quotation mark ornament 32 | ◉ - fisheye 33 | ⍥ - APL FUNCTIONAL SYMBOL CIRCLE DIAERESIS 34 | ※ - reference mark 35 | 36 | http://docs.python.org/dev/library/turtle.html 37 | http://svn.python.org/projects/python/trunk/Demo/turtle/ 38 | -------------------------------------------------------------------------------- /prince.css: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | "Dive Into Python 3" Prince stylesheet 4 | 5 | Copyright (c) 2009, Mark Pilgrim, All rights reserved. 6 | 7 | Redistribution and use in source and binary forms, with or without modification, 8 | are permitted provided that the following conditions are met: 9 | 10 | * Redistributions of source code must retain the above copyright notice, 11 | this list of conditions and the following disclaimer. 12 | * Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' 17 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | /* some Prince-specific rules to generate a nicer PDF */ 30 | /* see http://www.princexml.com/ */ 31 | 32 | @page { 33 | size: US-Letter; 34 | margin: 30pt; 35 | padding: 0; 36 | @bottom-center { 37 | font: 12pt/1.75 'Gill Sans', 'Gill Sans MT', Helvetica, Corbel, 'Nimbus Sans L', 'Liberation Sans', 'Deja Vu Sans', FreeSans, 'Arial Unicode', Arial, sans-serif; 38 | content: counter(page); 39 | } 40 | } 41 | pre { 42 | page-break-inside: avoid; 43 | } 44 | h1 { 45 | page-break-before: always; 46 | prince-bookmark-level: 1; 47 | } 48 | h2 { 49 | prince-bookmark-level: 2; 50 | } 51 | h3 { 52 | prince-bookmark-level: 3; 53 | } 54 | ul, ol { 55 | margin: 1.75em 20pt; 56 | } 57 | abbr { 58 | text-decoration: none; 59 | } 60 | -------------------------------------------------------------------------------- /print.css: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | "Dive Into Python 3" print stylesheet 4 | 5 | Copyright (c) 2009, Mark Pilgrim, All rights reserved. 6 | 7 | Redistribution and use in source and binary forms, with or without modification, 8 | are permitted provided that the following conditions are met: 9 | 10 | * Redistributions of source code must retain the above copyright notice, 11 | this list of conditions and the following disclaimer. 12 | * Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' 17 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | /* typography */ 30 | 31 | body, .w a { 32 | font-size: 12pt; 33 | } 34 | pre, kbd, samp, code, var, .b { 35 | font-size: 10pt; 36 | line-height: 2.1; 37 | } 38 | span { 39 | font-size: 12pt; 40 | } 41 | .baa { 42 | font-size: 13pt; 43 | } 44 | .q span { 45 | font-size: 13pt; 46 | } 47 | .f:first-letter { 48 | color: #888; 49 | font: normal 48pt/0.68 serif; 50 | } 51 | p, ul, ol { 52 | font-size: 12pt; 53 | } 54 | 55 | /* basics */ 56 | 57 | html, body { 58 | background: #fff; 59 | margin: 0; 60 | padding: 0; 61 | } 62 | 63 | /* links */ 64 | 65 | a { 66 | text-decoration: none; 67 | border-bottom: 1px dotted; 68 | } 69 | html, a:link, a:visited, .w a, .note span { 70 | color: #000; 71 | } 72 | 73 | /* code blocks */ 74 | 75 | pre { 76 | border: 0; 77 | } 78 | .c { 79 | font-size: 10pt; 80 | line-height: 2.1; 81 | } 82 | 83 | mark { 84 | background: gainsboro; 85 | } 86 | 87 | /* headers and pullquotes */ 88 | 89 | h1, h1 code { 90 | font-size: 24pt; 91 | } 92 | h2, h2 code { 93 | font-size: 18pt; 94 | } 95 | h3, h3 code { 96 | font-size: 13pt; 97 | } 98 | aside { 99 | font-size: 24pt; 100 | background: #667; 101 | color: #fff; 102 | } 103 | 104 | /* overrides */ 105 | 106 | .w, .d, form, form + p, #level, #toc { 107 | display: none !important; 108 | } 109 | 110 | /* syntax highlighting */ 111 | 112 | .str { color: #060; } 113 | .kwd { color: #006; font-weight: bold; } 114 | .com { color: #600; font-style: italic; } 115 | .typ { color: #404; font-weight: bold; } 116 | .lit { color: #044; } 117 | .pun { color: #440; } 118 | .pln { color: #000; } 119 | .tag { color: #006; font-weight: bold; } 120 | .atn { color: #404; } 121 | .atv { color: #060; } 122 | -------------------------------------------------------------------------------- /robots.txt: -------------------------------------------------------------------------------- 1 | User-Agent: * 2 | Disallow: /tmp/ 3 | Disallow: /d/ 4 | -------------------------------------------------------------------------------- /troubleshooting.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Troubleshooting - Dive Into Python 3 4 | 5 | 6 | 8 | 9 | 10 | 11 | 12 |

  
13 |

You are here: Home Dive Into Python 3 14 |

Troubleshooting

15 |
16 |

Where’s the ANY key?
variously attributed 17 |

18 |

  19 | 20 |

Diving In

21 |

FIXME 22 | 23 |

Getting to the Command Line

24 |

Throughout this book, there are examples of executing Python programs from the command line. Where is the command line? 25 | 26 |

On Linux, look in your Applications menu for a program called Terminal. (It may be in a submenu like Accessories or System.) 27 | 28 |

On Mac OS X, there is an application called Terminal in your /Applications/Utilities/ folder. To get there, click on your desktop, open the Go menu, select Go to folder..., and type /Applications/Utilities/. Then double-click the Terminal program. 29 | 30 |

On Windows, click Start, select Run..., type cmd, and press ENTER. 31 | 32 |

Running Python on the command line

33 | 34 |

Once you get to the command line, you should be able to run the Python interactive shell. On the Linux or Mac OS X command line, type python3 and press ENTER. On the Windows command line, type c:\python31\python and press ENTER. If all goes well, you should see something like this: 35 | 36 |

37 | you@localhost:~$ python3
38 | Python 3.1 (r31:73572, Jul 28 2009, 06:52:23) 
39 | [GCC 4.2.4 (Ubuntu 4.2.4-1ubuntu4)] on linux2
40 | Type "help", "copyright", "credits" or "license" for more information.
41 | >>>
42 | 43 |

(Type exit() and press ENTER to exit the Python interactive shell and go back to the command line. This works on all platforms.) 44 | 45 |

If you get a “command not found” error, it probably means you don’t have Python 3 installed. 46 | 47 |

48 | you@localhost:~$ python3
49 | bash: python3: command not found
50 | 51 |

On the other hand, if you get into a Python interactive shell but the version number is not what you expected, you may have more than one version of Python installed. This happens most often on Linux and Mac OS X systems, where an older version of Python is pre-installed. You can install the latest version without deleting the older version (they will live side-by-side in peace), but you will need to be more specific when you run Python from the command line. 52 | 53 |

For example, on my home Linux box, I have several versions of Python installed so I can test the Python software that I write. To run a specific version, I can type python3.0, python3.1, or python2.6. 54 | 55 |

56 | mark@atlantis:~$ python3.0
57 | Python 3.0.1+ (r301:69556, Apr 15 2009, 17:25:52)
58 | [GCC 4.3.3] on linux2
59 | Type "help", "copyright", "credits" or "license" for more information.
60 | >>> exit()
61 | mark@atlantis:~$ python3.1
62 | Python 3.1 (r31:73572, Jul 28 2009, 06:52:23) 
63 | [GCC 4.2.4 (Ubuntu 4.2.4-1ubuntu4)] on linux2
64 | Type "help", "copyright", "credits" or "license" for more information.
65 | >>> exit()
66 | mark@atlantis:~$ python2.6
67 | Python 2.6.5 (r265:79063, Apr 16 2010, 13:57:41) 
68 | [GCC 4.4.3] on linux2
69 | Type "help", "copyright", "credits" or "license" for more information.
70 | >>> exit()
71 | 72 |

73 | 74 |

© 2001–11 Mark Pilgrim 75 | 76 | 77 | -------------------------------------------------------------------------------- /util/buildtoc.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | 3 | import re 4 | 5 | # get list of chapters 6 | chapters = [] 7 | for line in open('index.html', encoding="utf-8"): 8 | if not line.count('', 1)[0]) 10 | sections = {} 11 | 12 | for filename in chapters: 13 | chapter_id = filename.split(".", 1)[0] 14 | with open(filename, encoding="utf-8") as f: data = f.read() 15 | sections[chapter_id] = re.findall("(.*?)')[1].split('')[0] 19 | 20 | full_toc = ['', '

    '] 21 | chapter_id = '' 22 | for line in short_toc.splitlines(): 23 | if not line.count('', '>', line) 26 | line = line.replace('
  1. ', '
  2. '.format(chapter_id)) 27 | full_toc.append(line) 28 | section_number = 0 29 | previous_section_level = section_level = 1 30 | for section_level, section_id, section_title in sections[chapter_id]: 31 | section_level = int(section_level) 32 | if section_level < previous_section_level: 33 | full_toc.append('
') 34 | elif section_level > previous_section_level: 35 | full_toc.append('
    ') 36 | section_number += 1 37 | full_toc.append('
  1. {2}'.format(chapter_id, section_id, section_title)) 38 | previous_section_level = section_level 39 | section_level = int(section_level) 40 | while (section_level > 1): 41 | full_toc.append('
') 42 | section_level -= 1 43 | full_toc.append('') 44 | full_toc.append('') 45 | with open('table-of-contents.html', encoding="utf-8") as f: data = f.read() 46 | with open('table-of-contents.html', mode="w", encoding="utf-8") as f: 47 | f.write(data.split('')[0] + "\n".join(full_toc) + data.split('')[1]) 48 | -------------------------------------------------------------------------------- /util/compiler.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kennethreitz/dive-into-python3/67ef8e6df7adcafec77b8994ee4a79c59d625c45/util/compiler.jar -------------------------------------------------------------------------------- /util/flatten.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | 3 | import re 4 | import time 5 | 6 | # get list of chapters 7 | chapters = [] 8 | for line in open('index.html', encoding="utf-8"): 9 | if not line.count('', 1)[0]) 12 | 13 | # construct regexes used to fix internal xrefs 14 | chapter_href = re.compile("".format("|".join(chapters))) 15 | chapter_fragment_href = re.compile("".format("|".join(chapters))) 16 | same_chapter_fragment_href = re.compile("]") 18 | 19 | # munge and combine chapter-specific styles 20 | out = open('build/single.html', 'w', encoding="utf-8") 21 | out.write(open('util/single-header.html', encoding="utf-8").read().replace('%%DATE%%', time.strftime('%Y-%m-%d', time.localtime()))) 22 | out.write("'): 29 | include = False 30 | if include and not line.count('counter-reset'): 31 | line = "#{0} {1}".format(chapter_id, line) 32 | line = line.replace(",", ", #{0} ".format(chapter_id)) 33 | out.write(line) 34 | if line.count('\n") 37 | out.write(open('util/single-header2.html', encoding="utf-8").read()) 38 | 39 | # munge and combine chapters 40 | for filename in chapters: 41 | include = False 42 | id_prefix = filename.split(".", 1)[0] 43 | chapter_id = "chapter-" + id_prefix 44 | out.write("\n") 60 | 61 | out.write(open('util/single-footer.html', encoding="utf-8").read()) 62 | out.close() 63 | -------------------------------------------------------------------------------- /util/htmlminimizer.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | """Quick-and-dirty HTML minimizer""" 3 | 4 | import sys 5 | import re 6 | import html.entities 7 | import itertools 8 | import os.path 9 | 10 | _SERVERS = ['a.wearehugh.com', 11 | 'b.wearehugh.com', 12 | 'c.wearehugh.com', 13 | 'd.wearehugh.com'] 14 | available_server = itertools.cycle(_SERVERS) 15 | input_file = sys.argv[1] 16 | output_file = sys.argv[2] 17 | in_pre = False 18 | with open(output_file, 'w', encoding="utf-8") as _out, open(input_file, encoding="utf-8") as _in: 19 | for line in _in: 20 | # round-robin image servers 21 | if "', '') 28 | line = line.replace('', '') 29 | 30 | # replace entities with Unicode characters 31 | for e in re.findall('&(.+?);', line): 32 | if e in ('lt', 'amp', 'quot', 'apos', 'nbsp'): 33 | continue 34 | n = html.entities.name2codepoint.get(e) 35 | if not n: 36 | if e.count('#x'): 37 | # it's late, forgive me 38 | n = eval(e.replace('#', '0')) 39 | elif e.count('#'): 40 | n = int(e.replace('#', '')) 41 | else: 42 | continue 43 | line = line.replace('&' + e + ';', chr(n)) 44 | 45 | # strip leading and trailing whitespace, except inside
 blocks
46 |         g = line.strip()
47 |         if g.count('
 in one line
51 |             in_pre = False
52 |             g = line.rstrip()
53 |         if in_pre:
54 |             _out.write(line)
55 |         else:
56 |             _out.write(g)
57 |         if g.lower() == '':
58 |             _out.write('\n\n'.format(os.path.basename(input_file)))
59 | 
60 | 


--------------------------------------------------------------------------------
/util/lesscss.py:
--------------------------------------------------------------------------------
 1 | #!/usr/bin/python2.5
 2 | 
 3 | from pyquery import PyQuery as pq
 4 | import glob
 5 | import sys
 6 | 
 7 | # These selectors are kept regardless of whether this script thinks they are used.
 8 | # Most of these match nodes that are dynamically inserted or manipulated by script
 9 | # after the page has loaded, which is why a static analysis thinks they're unused.
10 | SELECTOR_EXCEPTIONS = ('.w', '.b', '.str', '.kwd', '.com', '.typ', '.lit', '.pun', '.tag', '.atn', '.atv', '.dec', 'pre .u', 'pre .u span', 'td .u', 'li ol', 'a.hl:link', 'a.hl:visited', 'a.hl:hover', 'h2[id]:hover a.hl', 'h3[id]:hover a.hl')
11 | 
12 | filename = sys.argv[1]
13 | cssfilename = sys.argv[2]
14 | pqd = pq(filename=filename)
15 | raw_data = open(filename, 'rb').read()
16 | if raw_data.count('
86 | 
87 | 


--------------------------------------------------------------------------------