Python Tutorials Ation Manual
User Manual:
Open the PDF directly: View PDF .
Page Count: 76
Download | |
Open PDF In Browser | View PDF |
python-tutorials Documentation Release 1.1.1 Jose A. Lerma III Dec 14, 2018 GETTING STARTED 1 Introduction 1.1 Installation . . . . . . . . . . . . . . . . . . . . . . . . . . 1.1.1 Windows . . . . . . . . . . . . . . . . . . . . . . . 1.1.2 Linux . . . . . . . . . . . . . . . . . . . . . . . . 1.1.3 Building Documentation . . . . . . . . . . . . . . 1.1.4 Disclaimer . . . . . . . . . . . . . . . . . . . . . . 1.2 AutomateTheBoringStuffWithPython . . . . . . . . . . . 1.2.1 AutomateTheBoringStuffWithPython Corrections 1.3 CrackingCodesWithPython . . . . . . . . . . . . . . . . . 1.3.1 CrackingCodesWithPython Corrections . . . . . 1.4 wikibook . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.5 Udacity . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.5.1 CS101: Intro to Computer Science . . . . . . . . 1.6 books . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.6.1 CrackingCodesWithPython package . . . . . . . 1.7 Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Python Module Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 3 3 4 6 6 6 7 27 28 32 32 32 32 32 69 71 i ii python-tutorials Documentation, Release 1.1.1 Persistent Python practice produces prodigious productivity. GETTING STARTED 1 python-tutorials Documentation, Release 1.1.1 2 GETTING STARTED CHAPTER ONE INTRODUCTION Python is a great language for getting things done quickly; however, a good deal of resources (mainly RAM (Random Access Memory)) are recommended. There are ways to incorporate C/C++ from within Python, but some may find it easier to port it over. For more thorough intros, get lost in Python’s Beginner’s Guide or Wikipedia’s Python page for a day or so and come back. Looks up, then puts down Steam Controller You’re back? Alright, let’s continue. 1.1 Installation There are many ways to install and use Python depending on platform and IDE (Integrated Development Environment) (if any). These docs cover the methods I frequently use. 1.1.1 Windows For Windows, I use but one editor: Atom; however, I give PyCharm an honorable mention. The Atom setup is lightweight and portable while the Pycharm setup is extensible and full-featured. I have Pycharm on a Windows 10 Technical Preview VM (Virtual Machine), and it works well, but is quite bloated for a Windows VM running in Windows (Windows-ception?). Atom From the Atom.io page: Atom is a text editor that’s modern, approachable, yet hackable to the core—a tool you can customize to do anything but also use productively without ever touching a config file. Personally, I have had to edit a config file to setup a proxy, so YMMV (Your Mileage May Vary). Atom is also surprisingly full-featured (e.g. plugins, themes, file system browsing) given that it can be installed in a portable configuration and is multi-platform. Windows Setup While Atom is multi-platform, I only use it on Windows. 3 python-tutorials Documentation, Release 1.1.1 As aforementioned, I tend to use the zipped Atom files along with the PortableApps.com Platform to create a portable base environment. Next, I extract the zipped Atom files into X:\PortableApps\Atom\, as an example. Then, you’ll need to get the atom-runner package so that you can run the Python programs with an ALT + R key combo. However, atom-runner will not work if you have to input data from terminal, so you will need either the built-in Command Prompt or a PA.com portable enhancement like Console Portable. When you first open Atom, an .atom folder will be created in %USERPROFILE%, this folder will need to be moved into X:\PortableApps\ to keep your settings. As for Python, I get the embeddable zip files and extract them into X:\PortableApps\CommonFiles\python3\ to continue with the portable theme. If you want different versions of Python, you can make different folders e.g. python2.7, python3.6, python3.5 Finally, the easiest way to get Atom to find your portable Python installation is to use a shebang on the first line of code #! X:\PortableApps\CommonFiles\python3\python.exe 1.1.2 Linux For Linux, I have two main IDEs: Vim and PyCharm. The Vim setup is lightweight and available without too much effort while the PyCharm setup is extensible and full-featured. While I have a couple of Linux boxes (at the moment), I am very security minded when it comes to my Linux machines, so I prefer to run a Development VM of Linux on Windows. Excessive, yes, but taking snapshots, cloning, and reinstalling on VMs is easier than on physical machines. I’ve read that some python bots can be run on a Raspberry Pi. I would like to tinker with this concept a bit, but I am concerned that Raspberry Pis do not have enough RAM, so I will be sticking with VMs until I can get more tests done. Vim Vim is a configurable, open source, and cross platform text editor that is an improvement of the vi editor in most Linux distros. It has nifty things like syntax highlighting, colorization, and a scripting language to make your own plugins, etc. Setup As aforementioned, it is cross platform (and open source), so it can run on anything (even Potato). Personally, I prefer to use it on Linux only because it is usually in the default repository and has both syntax highlighting and colorization, which are a great improvement upon vi in CLI. Linux If your distro does not have vim in its default repo, then I fear you will have to compile from source code. Windows If you should want to use Vim on Windows, and not use gVim at PA.com, then both binaries and executables are available for you. 4 Chapter 1. Introduction python-tutorials Documentation, Release 1.1.1 Other Believe it or not, Vim is available on even more architectures: Amiga, OS2, Macintosh, Android, iOS, WindowsCE, Cygwin, and others. Plugins/Scripts Vim has a library of thousands of powerful scripts that are easy to make if it is missing something you want. Personally, I do not use any since I mainly use Vim as a quick, light editor. PyCharm PyCharm is very much like Python itself: quick to develop on, full-featured, and resource heavy. PyCharm is a true IDE: a console and debugger are all built-in. I especially like the PEP8 checks. Linux Setup Though Pycharm is multi-platform, I mainly use it on Linux. Unless you are willing to pay for a license, you are probably going to want the free community edition. Download the tar.gz file wherever you like, then extract the pycharm-community-20xx.x.x folder. Therein, run the pycharm-community-20xx.x.x/bin/pycharm.sh file from within terminal. Once setup is complete, on the menu bar, go to “Tools>Create Desktop Entry…” to make it easier to open later. Do not delete the pycharm-community-20xx.x.x folder because that is where it is running from. Upgrades follow the same procedure, except that you can delete the previous pycharm-community-20xx.x.x version folder. Python Binaries Installing Python will depend on your Linux distro. Most will have some version of Python either built-in or available from the package manager. PyCharm can auto-detect and use these installed versions. The Ubuntu Setup of my ClashCallerBot is an example of how easy setting up Python can be. However, if you are unlucky, you will have to download the source and compile it yourself. Windows Setup Windows installation is very straightforward: • Install Python with the Python executable installer. • Install PyCharm using the Community Edition executable installer. Any extra packages or modules would have to be added, but most programs can be run with the base installations. 1.1. Installation 5 python-tutorials Documentation, Release 1.1.1 1.1.3 Building Documentation Note: Building the documentation is not needed or recommended unless contributing to the documentation. The latest version of the documentation is available at josealermaiii@github.io/python-tutorials or as a PDF in the source code. You have been warned. Building the docs requires a few more pip packages: • sphinx • sphinxcontrib-napoleon • sphinx-rtd-theme Now, we can build the docs in HTML format: cd absolute_path_here/python-tutorials/docs make html This will save the docs website in ../../python-tutorials-docs/. Building the PDF is even more involved. First, LaTeX must be installed on the OS. For example, in Ubuntu 18.04: sudo apt-get install texlive-latex-recommended texlive-latex-extra texlive-fonts,→recommended texlive-xetex Installing these dependencies is not recommended, if not needed, because they require > 330 MB of disk space. We also install XeLaTeX, texlive-xetex, because some of the book corrections contain code snippets with unicode characters that are not supported by the default LaTeX engine. Now, we can build the docs in PDF format: cd absolute_path_here/python-tutorials/docs make latexpdf This will save the doc’s PDF in ../manual.pdf. 1.1.4 Disclaimer Though covered by the MIT License, I reiterate: executable programs written from code on the Internet can end up doing bad things. Read and understand all code you copy and paste before running it. 1.2 AutomateTheBoringStuffWithPython You’ll be seeing a lot of Al Sweigart’s books because he provides them for free online at his website. Please consider donating to show your support. Automate the Boring Stuff with Python is his iconic book for beginners and largely covers automating common computer tasks. 6 Chapter 1. Introduction python-tutorials Documentation, Release 1.1.1 From file manipulation, spreadsheets, and PDFs to web scraping, e-mails, and texts - a little of everything is covered. I use the .epub format of the book, so rather than pages, I provide locations. 1.2.1 AutomateTheBoringStuffWithPython Corrections I don’t expect to find many more, but I’ll update this post if I do. Note: It’s an EPUB copy, published: 2016-01-14T10:12:21-08:00 Also, no page numbers, just reference numbers (refNum/949). In Chapter 10, on reference number 368.7, paragraph 19.30, the code block: >>> >>> >>> >>> podBayDoorStatus = 'open' assert podBayDoorStatus == 'open', 'The pod bay doors need to be "open".' podBayDoorStatus = 'I\'m sorry, Dave. I\'m afraid I can't do that.'' assert podBayDoorStatus == 'open', 'The pod bay doors need to be "open".' should be: >>> >>> >>> >>> podBayDoorStatus = 'open' assert podBayDoorStatus == 'open', 'The pod bay doors need to be "open".' podBayDoorStatus = 'I\'m sorry, Dave. I\'m afraid I can\'t do that.' # Changed assert podBayDoorStatus == 'open', 'The pod bay doors need to be "open".' July 23, 2018 Update In Chapter 11, on reference number 447.4, paragraph 20.247, the code block: from selenium import webdriver browser = webdriver.Firefox() browser.get('http://inventwithpython.com') try: elem = browser.find_element_by_class_name('bookcover') print('Found <%s> element with that class name!' % (elem.tag_name)) except: print('Was not able to find an element with that name.') outputs Was not able to find an element with that name. The following does give the intended output: from selenium import webdriver browser = webdriver.Firefox() browser.get('http://inventwithpython.com') try: elem = browser.find_element_by_class_name('card-img-top') # changed print('Found <%s> element with that class name!' % (elem.tag_name)) except: print('Was not able to find an element with that name.') On reference number 448.7, paragraph 20.249, the code block: 1.2. AutomateTheBoringStuffWithPython 7 python-tutorials Documentation, Release 1.1.1 >>> from selenium import webdriver >>> browser = webdriver.Firefox() >>> browser.get('http://inventwithpython.com') >>> linkElem = browser.find_element_by_link_text('Read It Online') >>> type(linkElem)>>> linkElem.click() # follows the "Read It Online" link should be: >>> from selenium import webdriver >>> browser = webdriver.Firefox() >>> browser.get('http://inventwithpython.com') >>> linkElem = browser.find_element_by_link_text('Read Online for Free') # changed >>> type(linkElem) >>> linkElem.click() # follows the "Read Online for Free" link # changed On reference number 449.3, paragraph 20.252, the line: As long as Gmail hasn’t changed the id of the Username and Password text fields since this book was published… “Gmail” should be “Yahoo Mail” because of line >>> browser.get('https://mail.yahoo.com') in the code block Aug. 5, 2018 Update In Chapter 12, on reference number 459.8, paragraph 21.47, the codeblock: >>> wb.get_sheet_names() ['Sheet1', 'Sheet2', 'Sheet3'] >>> sheet = wb.get_sheet_by_name('Sheet3') >>> sheet >>> type(sheet) >>> sheet.title 'Sheet3' >>> anotherSheet = wb.get_active_sheet() should be: >>> wb.sheetnames # changed ['Sheet1', 'Sheet2', 'Sheet3'] >>> sheet = wb['Sheet3'] # changed >>> sheet >>> type(sheet) >>> sheet.title 'Sheet3' >>> anotherSheet = wb.active # changed because those methods are now depreciated (using OpenPyXL 2.5.5). 8 Chapter 1. Introduction python-tutorials Documentation, Release 1.1.1 Aug. 6, 2018 Update In Chapter 12, on reference number 463.0, paragraph 21.56, the codeblock: >>> sheet = wb.get_sheet_by_name('Sheet1') >>> sheet.get_highest_row() 7 >>> sheet.get_highest_column() 3 should be: >>> sheet = wb['Sheet1'] # changed >>> sheet.max_row # changed 7 >>> sheet.max_column # changed 3 because those methods are also depreciated. On reference number 463.6, paragraph 21.58, the codeblock: >>> from openpyxl.cell import get_column_letter, column_index_from_string --snip-- # omitted to save space >>> sheet = wb.get_sheet_by_name('Sheet1') >>> get_column_letter(sheet.get_highest_column()) 'C' should be: >>> from openpyxl.utils import get_column_letter, column_index_from_string --snip-- # omitted to save space >>> sheet = wb['Sheet1'] # changed >>> get_column_letter(sheet.max_column) # changed 'C' # changed because the functions were relocated and methods depreciated. The lines with openpyxl.cell in the paragraphs above and below should also be changed. In paragraph 21.59, the line “method like get_highest_column() to get an integer” should be changed to “property like max_column to get an integer.” Aug. 7, 2018 Update In Chapter 12, on reference number 465.0, paragraph 21.60 is another get_sheet_by_name('Sheet1') that ought to be >>> sheet = wb['Sheet1']. >>> sheet = wb. On reference number 466.8, paragraph 21.64, the codeblock: --snip-- # omitted to save space >>> sheet = wb.get_active_sheet() >>> sheet.columns[1] ( , | , | , | , | , | , | ) >>> for cellObj in sheet.columns[1]: print(cellObj.value) 1.2. AutomateTheBoringStuffWithPython 9 python-tutorials Documentation, Release 1.1.1 outputs TypeError: 'generator' object is not subscriptable The best way to fix it is debatable, but the easiest was to use the list function: --snip-- # omitted to save space >>> sheet = wb.active # changed >>> list(sheet.columns)[1] # changed ( | , | , | , | , | , | , | ) >>> for cellObj in list(sheet.columns)[1]: # changed print(cellObj.value) On reference number 468.0, paragraph 21.67 the list item 4. Call the get_active_sheet() or get_sheet_by_name() workbook method. ought to be something like 4. Use the .active property or the ["UseThisSheet"] workbook key. On reference number 470.6, paragraph 21.90 the codeblock: --snip-- # omitted to save space � sheet = wb.get_sheet_by_name('Population by Census Tract') countyData = {} # TODO: Fill in countyData with each county's population and tracts. print('Reading rows...') � for row in range(2, sheet.get_highest_row() + 1): --snip-- # omitted to save space ought to be: --snip-- # omitted to save space � sheet = wb['Population by Census Tract'] countyData = {} # changed # TODO: Fill in countyData with each county's population and tracts. print('Reading rows...') � for row in range(2, sheet.max_row + 1): # changed because of depreciated methods. The codeblock on paragraph 21.96 ought to be updated as well. Aug. 8, 2018 Update In Chapter 12, on reference number 477.4, paragraph 21.111, the codeblock: >>> wb.get_sheet_names() ['Sheet'] >>> sheet = wb.get_active_sheet() >>> sheet.title 'Sheet' >>> sheet.title = 'Spam Bacon Eggs Sheet' >>> wb.get_sheet_names() ought to be: 10 Chapter 1. Introduction python-tutorials Documentation, Release 1.1.1 >>> wb.sheetnames # changed ['Sheet'] >>> sheet = wb.active # changed >>> sheet.title 'Sheet' >>> sheet.title = 'Spam Bacon Eggs Sheet' >>> wb.sheetnames # changed In paragraph 21.113 (codeblock directly below) another >>> sheet = wb.get_active_sheet() ought to be >>> sheet = wb.active. On reference number 478.6, paragraph 21.116, the codeblock: >>> wb.get_sheet_names() ['Sheet'] >>> wb.create_sheet() | >>> wb.get_sheet_names() ['Sheet', 'Sheet1'] >>> wb.create_sheet(index=0, title='First Sheet') >>> wb.get_sheet_names() ['First Sheet', 'Sheet', 'Sheet1'] >>> wb.create_sheet(index=2, title='Middle Sheet') >>> wb.get_sheet_names() ['First Sheet', 'Sheet', 'Middle Sheet', 'Sheet1'] ought to be: >>> wb.sheetnames # changed ['Sheet'] >>> wb.create_sheet() >>> wb.sheetnames # changed ['Sheet', 'Sheet1'] >>> wb.create_sheet(index=0, title='First Sheet') >>> wb.sheetnames # changed ['First Sheet', 'Sheet', 'Sheet1'] >>> wb.create_sheet(index=2, title='Middle Sheet') >>> wb.sheetnames # changed In paragraph 21.118 (codeblock directly below): >>> wb.get_sheet_names() ['First Sheet', 'Sheet', 'Middle Sheet', 'Sheet1'] >>> wb.remove_sheet(wb.get_sheet_by_name('Middle Sheet')) >>> wb.remove_sheet(wb.get_sheet_by_name('Sheet1')) >>> wb.get_sheet_names() ought to be 1.2. AutomateTheBoringStuffWithPython 11 python-tutorials Documentation, Release 1.1.1 >>> wb.sheetnames # changed ['First Sheet', 'Sheet', 'Middle Sheet', 'Sheet1'] >>> wb.remove(wb['Middle Sheet']) # changed >>> wb.remove(wb['Sheet1']) # changed >>> wb.sheetnames # changed Aug. 11, 2018 Update In paragraph 21.121 (codeblock directly below), and on reference number 483.6, paragraph 21.144 (updateProduce.py) are more >>> sheet = wb.get_sheet_by_name('Sheet') that should be >>> sheet = wb['Sheet']. On reference number 484.8, paragraph 21.146 (updateProduce.py), the line � for rowNum in range(2, sheet.get_highest_row()): # skip the first row ought to be � for rowNum in range(2, sheet. max_row): # skip the first row. On reference number 486.5, paragraph 21.158, the line: To customize font styles in cells, important, import the Font() and Style() functions from the openpyxl.styles module. Unless, of course, that’s an intended pun. On reference number 486.8, paragraph 21.158, the codeblock: >>> import openpyxl >>> from openpyxl.styles import Font, Style >>> wb = openpyxl.Workbook() >>> sheet = wb.get_sheet_by_name('Sheet') � >>> italic24Font = Font(size=24, italic=True) � >>> styleObj = Style(font=italic24Font) � >>> sheet['A1'].style = styleObj >>> sheet['A1'] = 'Hello world!' >>> wb.save('styled.xlsx') should be: >>> import openpyxl >>> from openpyxl.styles import Font, NamedStyle # changed >>> wb = openpyxl.Workbook() >>> sheet = wb['Sheet'] # changed � >>> italic24Font = NamedStyle(name="italic24Font") # changed � >>> italic24Font.font = Font(size=24, italic=True) # changed � >>> sheet['A1'].style = italic24Font # changed >>> sheet['A1'] = 'Hello world!' >>> wb.save('styled.xlsx') because the Style class is now depreciated. Aug. 12, 2018 Update In Chapter 12, on reference number 488.9, paragraph 21.178, the codeblock: 12 Chapter 1. Introduction python-tutorials Documentation, Release 1.1.1 >>> >>> >>> >>> import openpyxl from openpyxl.styles import Font, Style wb = openpyxl.Workbook() sheet = wb.get_sheet_by_name('Sheet') >>> >>> >>> >>> fontObj1 = Font(name='Times New Roman', bold=True) styleObj1 = Style(font=fontObj1) sheet['A1'].style/styleObj sheet['A1'] = 'Bold Times New Roman' >>> >>> >>> >>> fontObj2 = Font(size=24, italic=True) styleObj2 = Style(font=fontObj2) sheet['B3'].style/styleObj sheet['B3'] = '24 pt Italic' >>> wb.save('styles.xlsx') should be: >>> >>> >>> >>> import openpyxl from openpyxl.styles import Font, NamedStyle wb = openpyxl.Workbook() sheet = wb['Sheet'] # changed >>> >>> >>> >>> >>> fontObj1 = Font(name='Times New Roman', bold=True) styleObj1 = NamedStyle(name="styleObj1") # changed styleObj1.font = fontObj1 # added sheet['A1'].style = styleObj1 # changed sheet['A1'] = 'Bold Times New Roman' >>> >>> >>> >>> >>> fontObj2 = Font(size=24, italic=True) styleObj2 = NamedStyle(name="StyleObj2") styleObj2.font = fontObj2 # added sheet['B3'].style = styleObj2 # changed sheet['B3'] = '24 pt Italic' # changed # changed >>> wb.save('styles.xlsx') Aug. 13, 2018 Update In Chapter 12, reference number 491.5, paragraphs 21.185 and 21.187 are more >>> sheet = wb. get_active_sheet() that should be >>> sheet = wb.active. However, the formula evaluation doesn’t work for me: >>> import openpyxl >>> wbFormulas = openpyxl.load_workbook('writeFormula.xlsx') >>> sheet = wbFormulas.active # changed >>> sheet['A3'].value '=SUM(A1:A2)' 1.2. AutomateTheBoringStuffWithPython 13 python-tutorials Documentation, Release 1.1.1 >>> wbDataOnly = openpyxl.load_workbook('writeFormula.xlsx', data_only=True) >>> sheet = wbDataOnly.active # changed >>> sheet['A3'].value # not working with LibreOffice 6.0.3.2 500 From what I’ve researched on openpyxl.load_workbook(), data_only controls whether cells with formulae have either the formula (default) or the value stored the last time Excel read the sheet. TODO: can someone else confirm with another LibreOffice version? Reference numbers 493.3, 495.0, 496.2, and 497.6 have more >>> sheet = wb.get_active_sheet() that should be >>> sheet = wb.active. Aug. 17, 2018 Update In Chapter 12, reference number 500.4, paragraph 21.234, the codeblock: >>> >>> >>> >>> import openpyxl wb = openpyxl.Workbook() sheet = wb.get_active_sheet() for i in range(1, 11): sheet['A' + str(i)] = i # create some data in column A >>> refObj = openpyxl.charts.Reference(sheet, (1, 1), (10, 1)) >>> seriesObj = openpyxl.charts.Series(refObj, title='First series') >>> >>> >>> >>> >>> >>> chartObj = openpyxl.charts.BarChart() chartObj.append(seriesObj) chartObj.drawing.top = 50 # set the position chartObj.drawing.left = 100 chartObj.drawing.width = 300 # set the size chartObj.drawing.height = 200 >>> sheet.add_chart(chartObj) >>> wb.save('sampleChart.xlsx') works slightly better as: >>> >>> >>> >>> import openpyxl wb = openpyxl.Workbook() sheet = wb.active # changed for i in range(1, 11): sheet['A' + str(i)] = i # create some data in column A >>> refObj = openpyxl.chart.Reference(sheet, min_row=1, min_col=1, max_row=10, max_ ,→col=1) # changed >>> seriesObj = openpyxl.chart.Series(refObj, title='First series') ,→Chart layout is wrong (LibreOffice 6.0.3.2) 14 # changed FIXME:␣ Chapter 1. Introduction python-tutorials Documentation, Release 1.1.1 >>> chartObj = openpyxl.chart.BarChart() # changed >>> chartObj.append(seriesObj) >>> chartObj.anchor = "B3" # set the position; changed >>> chartObj.width = 7.94 # set the size (in centimeters, where 1 cm = 37.8 pixels);␣ ,→changed >>> chartObj.height = 5.29 # changed >>> sheet.add_chart(chartObj) >>> wb.save('sampleChart.xlsx') but the layout of the chart is all wrong. TODO: can someone else confirm it works in Excel? Aug. 19, 2018 Update In Chapter 13 (I made it! Woot!), reference number 511.7, paragraph 22.13, the line: PyPDF2 uses a zero-based index for getting pages: The first page is page 0, the second is Introduction, and so on. “Introduction” links to the introduction of the book. Maybe “page 1” was auto-referenced? On reference number 513.2, paragraph 22.15, the codeblock: � >>> pdfReader.decrypt('rosebud') 1 >>> pageObj = pdfReader.getPage(0) gave me an IndexError, but the following works: >>> pdfReader = PyPDF2.PdfFileReader(open("encrypted.pdf", "rb")) � >>> pdfReader.decrypt('rosebud') 1 >>> pageObj = pdfReader.getPage(0) # added Aug. 21, 2018 Update In Chapter 13, reference number 524.8, paragraph 22.60, the codeblock: #! python3 # combinePdfs.py - Combines all the PDFs in the current working directory into # into a single PDF import PyPDF2, os # Get all the PDF filenames. pdfFiles = [] for filename in os.listdir('.'): if filename.endswith('.pdf'): � pdfFiles.append(filename) � pdfFiles.sort(key = str.lower) should be: 1.2. AutomateTheBoringStuffWithPython 15 python-tutorials Documentation, Release 1.1.1 #! python3 # combinePdfs.py - Combines all the PDFs in the current working directory into # a single PDF # changed import PyPDF2, os # Get all the PDF filenames. pdfFiles = [] for filename in os.listdir('.'): if filename.endswith('.pdf'): � pdfFiles.append(filename) � pdfFiles.sort(key=str.lower) # changed Aug. 22, 2018 Update In Chapter 13, reference number 531.0, paragraph 22.79, the codeblock: � >>> len(doc.paragraphs[1].runs) 4 � >>> doc.paragraphs[1].runs[0].text 'A plain paragraph with some ' � >>> doc.paragraphs[1].runs[1].text 'bold' � >>> doc.paragraphs[1].runs[2].text ' and some ' � >>> doc.paragraphs[1].runs[3].text 'italic' outputs the following in LibreOffice 6.0.3.2 with Python-Docx 0.8.7: � >>> len(doc.paragraphs[1].runs) 5 # changed � >>> doc.paragraphs[1].runs[0].text 'A plain paragraph with' # changed � >>> doc.paragraphs[1].runs[1].text ' some ' # changed � >>> doc.paragraphs[1].runs[2].text 'bold' # changed � >>> doc.paragraphs[1].runs[3].text ' and some ' # changed >>> doc.paragraphs[1].runs[4].text # added 'italic' TODO: can someone confirm in Word on Windows? On reference number 540.1, paragraph 22.163, the codeblock: --snip-- # omitted to save space >>> doc.paragraphs[1].runs[0].style = 'QuoteChar' >>> doc.paragraphs[1].runs[1].underline = True >>> doc.paragraphs[1].runs[3].underline = True >>> doc.save('restyled.docx') 16 Chapter 1. Introduction python-tutorials Documentation, Release 1.1.1 gives a UserWarning: style lookup by style_id is deprecated. Use style name as key instead. return self._get_style_id_from_style(self[style_name], style_type) but the following fixes it: --snip-- # omitted to save space >>> doc.paragraphs[1].runs[0].style = 'Quote Char' >>> doc.paragraphs[1].runs[1].underline = True >>> doc.paragraphs[1].runs[3].underline = True >>> doc.save('restyled.docx') # changed for python-docx 0.8.7 Aug. 23, 2018 Update In Chapter 13, reference number 540.1, paragraph 22.164, the line: We can see that it’s simple to divide a paragraph into runs and access each run individiaully. On reference number 546.9, paragraph 22.183, the codeblock: � >>> doc.paragraphs[0].runs[0].add_break(docx.text.WD_BREAK.PAGE) >>> doc.add_paragraph('This is on the second page!') >>> doc.save('twoPage.docx') ought to be: � >>> doc.paragraphs[0].runs[0].add_break(docx.enum.text.WD_BREAK.PAGE) >>> doc.add_paragraph('This is on the second page!') >>> doc.save('twoPage.docx') # changed Aug. 31, 2018 Update In Chapter 13, reference number 552.0, paragraph 22.228, the line: You should try both the uppercase and lower-case form of each word. In Chapter 14, reference number 561.2, paragraph 23.33, the codeblock: >>> import csv >>> csvFile = open('example.tsv', 'w', newline='') � >>> csvWriter = csv.writer(csvFile, delimiter='\t', lineterminator='\n\n') >>> csvWriter.writerow(['apples', 'oranges', 'grapes']) 24 >>> csvWriter.writerow(['eggs', 'bacon', 'ham']) 17 >>> csvWriter.writerow(['spam', 'spam', 'spam', 'spam', 'spam', 'spam']) 32 outputs: >>> import csv >>> csvFile = open('example.tsv', 'w', newline='') � >>> csvWriter = csv.writer(csvFile, delimiter='\t', lineterminator='\n\n') >>> csvWriter.writerow(['apples', 'oranges', 'grapes']) 23 # changed (continues on next page) 1.2. AutomateTheBoringStuffWithPython 17 python-tutorials Documentation, Release 1.1.1 (continued from previous page) >>> 16 >>> 31 csvWriter.writerow(['eggs', 'bacon', 'ham']) # changed csvWriter.writerow(['spam', 'spam', 'spam', 'spam', 'spam', 'spam']) # changed Sept. 1, 2018 Update In Chapter 14, reference number 565.5, paragraph 23.54, the codeblock: #! python3 # removeCsvHeader.py - Removes the header from all CSV files in the current # working directory. --snip-# Read the CSV file in (skipping first row). csvRows = [] csvFileObj = open(csvFilename) readerObj = csv.reader(csvFileObj) for row in readerObj: if readerObj.line_num == 1: continue # skip first row csvRows.append(row) csvFileObj.close() # TODO: Write out the CSV file. needs to be indented to match the previous codeblock: #! python3 # removeCsvHeader.py - Removes the header from all CSV files in the current # working directory. --snip-print('Removing header from ' + csvFilename + '...') # added # Read the CSV file in (skipping first row). csvRows = [] csvFileObj = open(csvFilename) readerObj = csv.reader(csvFileObj) for row in readerObj: if readerObj.line_num == 1: continue # skip first row csvRows.append(row) csvFileObj.close() # TODO: Write out the CSV file. On reference number 568.2, paragraph 23.58: The CSV Writer object will write the list to a CSV file in headerRemoved using csvFilename (which we also used in the CSV reader). This will overwrite the original file. 18 Chapter 1. Introduction python-tutorials Documentation, Release 1.1.1 I thought the original file won’t be overwritten because the new file is in the headerRemoved folder? TODO: Can someone please confirm? On reference number 575.4, paragraph 23.98, the link http://api.openweathermap.org /data/2.5/ forecast/daily?q=%3CLocation%3E&cnt=3 no longer works. The OpenWeatherMap.org API now needs an API key. So, sign up if you really want to run quickWeather.py. Alternatively, the Weather.gov API (United States only, at the moment) does not require an API key (only a User Agent), but it will require one in the future. Sept. 4, 2018 Update In Chapter 14, reference number 582.0, paragraph 23.130, the codeblock: for excelFile in os.listdir('.'): # Skip non-xlsx files, load the workbook object. for sheetName in wb.get_sheet_names(): # Loop through every sheet in the workbook. sheet = wb.get_sheet_by_name(sheetName) # Create the CSV filename from the Excel filename and sheet title. # Create the csv.writer object for this CSV file. # Loop through every row in the sheet. for rowNum in range(1, sheet.get_highest_row() + 1): rowData = [] # append each cell to this list # Loop through each cell in the row. for colNum in range(1, sheet.get_highest_column() + 1): # Append each cell's data to rowData. # Write the rowData list to the CSV file. csvFile.close() should be: for excelFile in os.listdir('.'): # Skip non-xlsx files, load the workbook object. for sheetName in wb.sheetnames: # changed # Loop through every sheet in the workbook. sheet = wb[sheetName] # changed # Create the CSV filename from the Excel filename and sheet title. # Create the csv.writer object for this CSV file. # Loop through every row in the sheet. for rowNum in range(1, sheet.max_row + 1): # changed rowData = [] # append each cell to this list # Loop through each cell in the row. for colNum in range(1, sheet.max_column + 1): # changed # Append each cell's data to rowData. # Write the rowData list to the CSV file. (continues on next page) 1.2. AutomateTheBoringStuffWithPython 19 python-tutorials Documentation, Release 1.1.1 (continued from previous page) csvFile.close() Sept. 5, 2018 Update In Chapter 15, reference number 595.7, paragraph 24.42, the codeblock: >>> datetime.datetime.fromtimestamp(1000000) datetime.datetime(1970, 1, 12, 5, 46, 40) >>> datetime.datetime.fromtimestamp(time.time()) datetime.datetime(2015, 2, 27, 11, 13, 0, 604980) might need to be: >>> import time # added >>> datetime.datetime.fromtimestamp(1000000) datetime.datetime(1970, 1, 12, 5, 46, 40) >>> datetime.datetime.fromtimestamp(time.time()) datetime.datetime(2015, 2, 27, 11, 13, 0, 604980) In case IDLE was closed to write the stopwatch.py program. Sept. 6, 2018 Update In Chapter 15, reference number 598.0, paragraph 24.47, the str line in codeblock needs bolding: --snip-- # omitted to save space >>> str(delta) # bold me, pls '11 days, 10:09:08' On reference number 599.5, paragraph 24.49, the line: Finally, passing the timedelta object to str() returns a string clearly explaning the duration. Sept. 7, 2018 Update In Chapter 15, reference number 612.3, paragraph 24.125, the line: To make sure the keyword argument sep=’ & ‘ gets passed to print() in the new thread, we pass kwargs={‘sep’: ‘& ‘} to threading.Thread(). On reference number 616.0, paragraph 24.136 (multidownloadXkcd.py), the codeblock: � 20 --snip-- # omitted if comicElem == []: print('Could not find comic image.') else: comicUrl = comicElem[0].get('src') # Download the image. print('Downloading image %s...' % (comicUrl)) --snip-- # omitted Chapter 1. Introduction python-tutorials Documentation, Release 1.1.1 should be: � --snip-- # omitted if comicElem == []: print('Could not find comic image.') else: comicUrl = 'http:' + comicElem[0].get('src') # changed # Download the image. print('Downloading image %s...' % (comicUrl)) --snip-- # omitted On reference number 627.6, paragraph 24.161, the codeblock: >>> subprocess.Popen(['C:\\python34\\python.exe', 'hello.py']) might need to be: >>> subprocess.Popen(['C:\\python34\\python.exe', 'hello.py']).communicate() # changed I could not get it to accept input without it in Ubuntu 18.04. TODO: Can someone confirm they got it to work in Windows? Sept. 8, 2018 Update In Chapter 15, reference number 631.7, paragraph 24.183 (countdown.py), the codeblock: --snip-- # omitted � timeLeft = 60 while timeLeft > 0: � print(timeLeft, end='') � time.sleep(1) --snip-- # omitted may need to be: --snip-- # omitted � timeLeft = 60 while timeLeft > 0: � print(timeLeft) # changed � time.sleep(1) --snip-- # omitted It wouldn’t print remaining time in Python 3.6.5 (Ubuntu 18.04) until the while loop finished. It seemed to wait until the line was done before printing it. TODO: Can someone else please confirm? Sept. 14, 2018 Update In Chapter 16, reference number 648.4, paragraph 25.52, the line: Install imapclient and pyzmail from a Terminal window. Appendix A has steps on how to install third-party modules. I had to install pyzmail36 (possibly because I’m using Python 3.6.5). Appendix A may have to be updated. 1.2. AutomateTheBoringStuffWithPython 21 python-tutorials Documentation, Release 1.1.1 Sept. 15, 2018 Update In Chapter 16, reference number 658.7, paragraph 25.115, the lines: imapObj.search(['ON 05-Jul-2015']). Returns every message sent on July 5, 2015. imapObj.search(['SINCE 01-Jan-2015', 'BEFORE 01-Feb-2015', 'UNSEEN']). Returns every␣ ,→message sent in January 2015 that is unread. (Note that this means on and after January 1 and up to but not including␣ ,→February 1.) imapObj.search(['SINCE 01-Jan-2015', 'FROM alice@example.com']). Returns every message␣ ,→from alice@example.com sent since the start of 2015. imapObj.search(['SINCE 01-Jan-2015', 'NOT FROM alice@example.com']). Returns every␣ ,→message sent from everyone except alice@example.com␣ ,→since the start of 2015. imapObj.search(['OR FROM alice@example.com FROM bob@example.com']). Returns every␣ ,→message ever sent from alice@example.com or␣ ,→bob@example.com. imapObj.search(['FROM alice@example.com', 'FROM bob@example.com']). Trick example! This␣ ,→search will never return any messages,␣ ,→because messages must match all search keywords.␣ ,→Since there can be only one “from” address, it␣ ,→is impossible for a message to be from both␣ ,→alice@example.com and bob@example.com. should be: imapObj.search(['ON', '05-Jul-2015']). Returns every message sent on July 5, 2015. imapObj.search(['SINCE', '01-Jan-2015', 'BEFORE', '01-Feb-2015', 'UNSEEN']). Returns␣ ,→every message sent in January 2015 that␣ ,→is unread. (Note that this means on␣ ,→and after January 1 and up to but not␣ ,→including February 1.) imapObj.search(['SINCE', '01-Jan-2015', 'FROM', 'alice@example.com']). Returns every␣ ,→message from alice@example.com sent since the␣ ,→start of 2015. imapObj.search(['SINCE', '01-Jan-2015', 'NOT', 'FROM', 'alice@example.com']). Returns␣ ,→every message sent from everyone␣ ,→except alice@example.com since the␣ ,→start of 2015. (continues on next page) 22 Chapter 1. Introduction python-tutorials Documentation, Release 1.1.1 (continued from previous page) imapObj.search(['OR', 'FROM', 'alice@example.com', 'FROM', 'bob@example.com']). Returns␣ ,→every message ever sent from␣ ,→alice@example.com or ␣ ,→bob@example.com. imapObj.search(['FROM', 'alice@example.com', 'FROM', 'bob@example.com']). Trick example!␣ ,→This search will never return any␣ ,→messages, because messages must match all␣ ,→search keywords. Since there can be␣ ,→only one “from” address, it is impossible␣ ,→for a message to be from both␣ ,→alice@example.com and bob@example. ,→com. because criteria should be a sequence of items. Plus, trying imapObj.search(['SINCE 01-Jan-2015', 'NOT FROM alice@exmaple.com']) outputs imaplib.error: SEARCH command error: BAD [b'Error in IMAP command UID SEARCH: Unexpected string as search key: SINCE 01-Jan-2015 (0.001 + 0.088 + 0.087 secs).'] Alternatively, imapObj.search('SINCE "01-Jan-2015" NOT FROM "alice@exmaple.com"') works, but isn’t recommended according to the docs. On reference number 664.6, paragraph 25.141, the line >>> message = pyzmail.PyzMessage. factory(rawMessages[40041]['BODY[]']) gave me a KeyError (even after using proper UIDs) that was only fixed by changing it to >>> message = pyzmail.PyzMessage. factory(rawMessages[40041][b'BODY[]']) On reference number 668.9, paragraph 25.148, the line � >>> UIDs = imapObj.search(['ON 09-Jul-2015']) should be � >>> UIDs = imapObj.search(['ON', '09-Jul-2015']) Sept. 16, 2018 Updates In Chapter 16, reference number 674.0, paragraph 25.168 (sendDuesReminders.py), the codeblock: import openpyxl, smtplib, sys --snip-- # omitted � sheet = wb.get_sheet_by_name('Sheet1') � lastCol = sheet.get_highest_column() � latestMonth = sheet.cell(row=1, column=lastCol).value --snip-- # omitted should be: 1.2. AutomateTheBoringStuffWithPython 23 python-tutorials Documentation, Release 1.1.1 import openpyxl, smtplib, sys, datetime --snip-- # omitted � sheet = wb['Sheet1'] # changed # changed � lastCol = sheet.max_column # changed � latestMonth = sheet.cell(row=1, column=lastCol).value latestMonth = datetime.datetime.strftime(latestMonth, '%b %Y') ,→LibreOffice 6.0.3.2 --snip-- # omitted # added for␣ Sept. 17, 2018 Update: In LibreOffice, latestMonth = 2018-06-01 00:00:00, so I had to use datetime to format it as Jun 2018. TODO: Can someone please confirm it works in Excel? On reference number 676.3, paragraph 25.170, the line � for r in range(2, sheet.get_highest_row() + 1): should be � for r in range(2, sheet.max_row + 1): On reference number 678.1, paragraph 25.174, the line body = "Subject: %s dues unpaid.\nDear %s,\nRecords show that you have not paid dues for %s. Please make this payment as soon as possible. Thank you!'" % (latestMonth, name, latestMonth) should be body = "Subject: %s dues unpaid.\nDear %s,\nRecords show that you have not paid dues for %s. Please make this payment as soon as possible. Thank you!" % (latestMonth, name, latestMonth) Sept. 17, 2018 Update In Chapter 16, reference number 682.8, paragraph 25.190, the codeblock: � >>> from twilio.rest import TwilioRestClient --snip-- # omitted � >>> twilioCli = TwilioRestClient(accountSID, authToken) should be: � >>> from twilio.rest import Client # changed --snip-- # omitted � >>> twilioCli = Client(accountSID, authToken) # changed because TwilioRestClient has been depreciated (using twilio 6.16.4). On reference number 685.5, paragraph 25.195, the line � >>> updatedMessage = twilioCli.messages. get(message.sid) should be � >>> updatedMessage = twilioCli.messages(message.sid).fetch() because the attributes of messages.get() were changed. Sept. 18, 2018 Update In Chapter 16, reference number 687.8, paragraph 25.201 (textMyself.py), the codeblock: --snip-- # omitted from twilio.rest import TwilioRestClient � def textmyself(message): � twilioCli = TwilioRestClient(accountSID, authToken) --snip-- # omitted 24 Chapter 1. Introduction python-tutorials Documentation, Release 1.1.1 should be: --snip-- # omitted from twilio.rest import Client # changed � def textmyself(message): � twilioCli = Client(accountSID, authToken) --snip-- # omitted # changed In paragraph 25.202, the line: It then defined textmyself() to take on argument �, make a TwilioRestClient object �, and call create() with the message you passed �. Sept. 27, 2018 Update In Chapter 17, reference number 724.1, paragraph 26.122, the line � im = im.resize((width, height)) is over indented. On reference number 734.5, paragraph 26.163, the codeblock: --snip-- # omitted >>> fontsFolder = 'FONT_FOLDER' # e.g. 'Library/Fonts' � >>> arialFont = ImageFont.truetype(os.path.join(fontsFolder, 'arial.ttf'), 32) � >>> draw.text((100, 150), 'Howdy', fill='gray', font=arialFont) --snip-- # omitted will need to be changed for those on Ubuntu, specifically: --snip-- # omitted >>> fontsFolder = '/usr/share/fonts/truetype' # e.g. 'Library/Fonts' # modified � >>> liberationFont = ImageFont.truetype(os.path.join(fontsFolder, '/liberation/ ,→LiberationSerif-Regular.ttf'), 32) # modified � >>> draw.text((100, 150), 'Howdy', fill='gray', font=liberationFont) # modified --snip-- # omitted However, everyone will have to modify it for their system. Sept. 28, 2018 Update In Chapter 17, reference number 738.6, paragraph 26.194, the line: Other wise, it should skip adding the logo. Sept. 29, 2018 Update In Chapter 17, reference number 739.4, paragraph 26.198, the codeblock: #! python3 # Import modules and write comments to describe this program. --snip-- # omitted may need to be: 1.2. AutomateTheBoringStuffWithPython 25 python-tutorials Documentation, Release 1.1.1 #! python3 # Import modules and write comments to describe this program. --snip-- # omitted On reference number 740.0, paragraph 26.200, the line: For each of the guests listed in the guests.txt file from the resources at http://nostarch.com/ automatestuff/, generate an image file with the guest name and some flowery decoration. may need to be: For each of the guests listed in the guests.txt file from the resources at http://nostarch.com/ automatestuff/, generate an image file with the guest’s name and some flowery decoration. I couldn’t find the public domain flower image mentioned in the book, so I used this one. Oct. 2, 2018 Update For Chapter 18, if running Ubuntu 18.04.1 in a VirtualBox virtual machine, mouse integration needs to be turned off so that the pyautogui module can control the mouse. Remember that the Host Key will need to be pressed to manually toggle keyboard/mouse capture. Oct. 3, 2018 Update In Chapter 18, reference number 764.0, paragraph 27.77, the codeblock: #! python3 # mouseNow.py - Displays the mouse cursor's current position. --snip-positionStr = 'X: ' + str(x).rjust(4) + ' Y: ' + str(y).rjust(4) pixelColor = pyautogui.screenshot().getpixel((x, y)) positionStr += ' RGB: (' + str(pixelColor[0]).rjust(3) positionStr += ', ' + str(pixelColor[1]).rjust(3) positionStr += ', ' + str(pixelColor[2]).rjust(3) + ')' print(positionStr, end='') --snip-may need to be: #! python3 # mouseNow.py - Displays the mouse cursor's current position. import pyautogui, os # changed --snip-positionStr = 'X: ' + str(x).rjust(4) + ' Y: ' + str(y).rjust(4) pixelColor = pyautogui.screenshot().getpixel((x, y)) positionStr += ' RGB: (' + str(pixelColor[0]).rjust(3) positionStr += ', ' + str(pixelColor[1]).rjust(3) positionStr += ', ' + str(pixelColor[2]).rjust(3) + ')' print(positionStr, end='') print('\b' * len(positionStr), end='', flush=True) except KeyboardInterrupt: files = os.listdir('./') # added (continues on next page) 26 Chapter 1. Introduction python-tutorials Documentation, Release 1.1.1 (continued from previous page) for file in files: # added if file.startswith('.screenshot'): # added os.remove(os.path.join('./', file)) # added print('\nDone.') to cleanup all the .screenshot### files left behind in Ubuntu 18.04. This could be because the exception handler doesn’t give PyAutoGUI a chance to do it. Oct. 4, 2018 Update In Chapter 18, reference number 765.5, paragraph 27.81, the line: … replacing ‘submit. png’ with the filename of your screenshot: Oct. 7, 2018 Update In Chapter 18, reference number 781.5, paragraph 27.192, the line: … then mouse over the Name field to figure out its the x- and y-coordinates. Setting up formFiller.py coordinates To set up the coordinates for formFiller.py, you need to open a terminal window (or command prompt), run the mouseNow.py script, resize it to something small, keep it in the foreground, and hover over the maximized browser in the background as you note the mouseNow.py data. As you enter data in the form, you may need to keep bringing back the mouseNow.py window into the foreground. For some reason, that wasn’t explained clearly enough for me. Tip: If “This is a required question” appears below the Name field, it will affect the coordinates of the Submit button. On reference number 791.8, paragraph 27.213, the lines: … whether it has gotten offtrack. You can even give PyAutoGUI a screen-shot and … On reference number 793.8, paragraph 27.236, the line: Your program will have to take screen-shots to guide… 1.3 CrackingCodesWithPython You’ll be seeing a lot of Al Sweigart’s books because he provides them for free online at his website. Please consider donating to show your support. Cracking Codes with Python is his latest release and largely covers how to use and compromise various ciphers with Python. Granted, most of the ciphers are old enough to be broken with a Raspberry Pi, but the general idea is how they are implemented and what about them are easy to break. For detailed answers to Practice Questions, check the No Starch Press Website. 1.3. CrackingCodesWithPython 27 python-tutorials Documentation, Release 1.1.1 1.3.1 CrackingCodesWithPython Corrections Note: My PDF copy was created 12/1/2017 7:03:06PM and was last modified 12/4/2017 5:30:14PM • Chapter 1 Practice Questions: The answer for Practice Question 1, part b: Encrypt “GUILLOTINE: A machine which makes a Frenchman shrug his shoulders with good reason.” with a key of 17 should be “XlZccfkZeV:NRN4rtyz5vN.yztyN4r2v0NrNW9v5ty4r5N0y9!xNyz0N0y6!3u v90N.z yNx66uN9vr065Q”, not “bpdggjodiZ:RVR8vx349zRD34x3R8v6z.RvRa?z9x38v9R.3?B2R34.R.30B7yz?.RD4A3R200yR?zv.09U” (that’s key of 21) Scratch that, with SYMBOLS = “ABCDEFGHIJKLMNOPQRSTUVWXYZ”, even the messages should be in all caps with totally different outputs, like the decryption in question 2. Question 1 answers should be: a. EQFMHIBXVSYW: EFPI XS TMGO AMXL IUYEP WOMPP E VMKLX-LERH TSGOIX SV E PIJX. b. XLZCCFKZEV: R DRTYZEV NYZTY DRBVJ R WIVETYDRE JYILX YZJ JYFLCUVIJ NZKY XFFU IVRJFE. c. DHKDZOT: TJPM DMMZQZMZIXZ OJRVMY HT YZDOT. and Question 3 should be using all caps as well. • On page 57, the final paragraph reads: “Just as in the reverse cipher in Chapter 5, …” However, the reverse cipher was in chapter 4 because chapter 5 is the Caesar cipher! • On page 84, end of the third-to-last paragraph: “(All the variables in the reverse cipher and Caesar cipher programs in Chapters 5 and 6, respectively, were global.)” Chapter 6 was the Caesar cipher hacker program! • On page 166, the fourth paragraph: Line 30 uses string interpolation to print the key currently being tested using string interpolation to provide feedback to the user. • On page 236, the code block: >>> letterMapping1 = simpleSubHacker.addLettersToMapping(letterMapping1, 'OLQIHXIRCKGNZ', ,→ candidates[0]) >>> letterMapping1 Should be >>> simpleSubHacker.addLettersToMapping(letterMapping1, 'OLQIHXIRCKGNZ', candidates[0]) >>> letterMapping1 • On page 237, the code blocks: >>> letterMapping1 = simpleSubHacker.addLettersToMapping(letterMapping1, 'OLQIHXIRCKGNZ', ,→ candidates[1]) >>> letterMapping1 and 28 Chapter 1. Introduction python-tutorials Documentation, Release 1.1.1 >>> letterMapping2 = simpleSubHacker.getBlankCipherletterMapping() >>> wordPat = makeWordPatterns.getWordPattern('PLQRZKBZB') >>> candidates = wordPatterns.allPatterns[wordPat] >>> candidates ['CONVERSES', 'INCREASES', 'PORTENDED', 'UNIVERSES'] >>> for candidate in candidates: ... letterMapping2 = simpleSubHacker.addLettersToMapping(letterMapping2, 'PLQRZKBZB', ,→ candidate) ... >>> letterMapping2 should be >>> simpleSubHacker.addLettersToMapping(letterMapping1, 'OLQIHXIRCKGNZ', candidates[1]) >>> letterMapping1 and >>> letterMapping2 = simpleSubHacker.getBlankCipherletterMapping() >>> wordPat = makeWordPatterns.getWordPattern('PLQRZKBZB') >>> candidates = wordPatterns.allPatterns[wordPat] >>> candidates ['CONVERSES', 'INCREASES', 'PORTENDED', 'UNIVERSES'] >>> for candidate in candidates: ... simpleSubHacker.addLettersToMapping(letterMapping2, 'PLQRZKBZB', candidate) ... >>> letterMapping2 • On page 238, the code block: >>> letterMapping3 = simpleSubHacker.getBlankCipherletterMapping() >>> wordPat = makeWordPatterns.getWordPattern('MPBKSSIPLC') >>> candidates = wordPatterns.allPatterns[wordPat] >>> for i in range(len(candidates)): ... letterMapping3 = simpleSubHacker.addLettersToMapping(letterMapping3, 'MPBKSSIPLC ,→', candidates[i]) ... >>> letterMapping3 should be >>> >>> >>> >>> ... ... >>> letterMapping3 = simpleSubHacker.getBlankCipherletterMapping() wordPat = makeWordPatterns.getWordPattern('MPBKSSIPLC') candidates = wordPatterns.allPatterns[wordPat] for i in range(len(candidates)): simpleSubHacker.addLettersToMapping(letterMapping3, 'MPBKSSIPLC', candidates[i]) letterMapping3 May 14, 2018 Update • On page 253, the code block: 1.3. CrackingCodesWithPython 29 python-tutorials Documentation, Release 1.1.1 >>> building = '' >>> for c in 'Hello world!': >>> building += c >>> print(building) should be >>> building = '' >>> for c in 'Hello world!': ... building += c ... >>> print(building) • On page 254, the code block: >>> >>> >>> >>> >>> building = [] for c in 'Hello world!': building.append(c) building = ''.join(building) print(building) should be >>> >>> ... ... >>> >>> building = [] for c in 'Hello world!': building.append(c) building = ''.join(building) print(building) May 15, 2018 Update • On page 260, the last line: Similarly, the letters that appear least often in the ciphertext are more likely to have been encrypted from to X, Q, and Z in plaintext. May 18, 2018 Update • On page 298, the code: >>> set([1, 2, 3, 3, 4]) set([1, 2, 3, 4]) outputs >>> set([1, 2, 3, 3, 4]) {1, 2, 3, 4} for me, but that may be the interactive shell or OS I’m using (Ubuntu 16.04 with Python 3.5.2). TODO: Can anyone else confirm? • On page 306, the code: 30 Chapter 1. Introduction python-tutorials Documentation, Release 1.1.1 >>> def printStuff(): print('Hello', end='\n') print('Howdy', end='') print('Greetings', end='XYZ') print('Goodbye') >>> printStuff() should be >>> def printStuff(): ... print('Hello', end='\n') ... print('Howdy', end='') ... print('Greetings', end='XYZ') ... print('Goodbye') ... >>> printStuff() May 19, 2018 Update • On page 318, the code block: >>> import secrets >>> otp = '' >>> for i in range(55): otp += secrets.choice('ABCDEFGHIJKLMNOPQRSTUVWXYZ') >>> otp should be >>> >>> >>> ... >>> import secrets otp = '' for i in range(55): otp += secrets.choice('ABCDEFGHIJKLMNOPQRSTUVWXYZ') otp I think. Ubuntu 16.04 LTS doesn’t have Python 3.6 or above. TODO: Can someone confirm? • On page 326, the code block: >>> primeNum.isPrime(13) True should be >>> primeNum.isPrime(13) False Here’s the thing: isPrime() checks a number for divisibility by low prime numbers (which would make it not prime). Therefore, 13 is divisible by the low prime number 13 and is not prime by that definition. You’d have to add something like: if num in LOW_PRIMES: return True # Low prime numbers are still prime numbers 1.3. CrackingCodesWithPython 31 python-tutorials Documentation, Release 1.1.1 to isPrime() to keep it from doing that. May 20, 2018 Update • On page 341 and 347, the code: 64. print('The private key is a %s and a %s digit number.' % (len(str(publicKey[0])),␣ ,→len(str(publicKey[1])))) should be 64. print('The private key is a %s and a %s digit number.' % (len(str(privateKey[0])),␣ ,→len(str(privateKey[1])))) 1.4 wikibook This is a set of examples from Wikibook’s Non-Programmer’s Tutorial for Python 3. I like the concept of an open tutorial for users to learn from and add to so I went along with it and typed up all the relevant examples from all the chapters with code. They are a great resource to follow along with and contain some notes I added. 1.5 Udacity It is fantastic that classes can be taken for free, though a machine does all the grading. The only downside is there is little feedback, but that may be what the forums are for. Included are my answers to the given problems. As I learn more about Python, I will go back and make corrections/improvements. Regardless, given these are tutorials, feedback is welcome. 1.5.1 CS101: Intro to Computer Science These are sets of problems given in Udacity’s CS101 Course. Unfortunately, Python 2.x is used in the course, so these problem sets may not be forwards compatible. The goal of the CS101 class is to create an Internet search engine from scratch in Python. The final is creating a social network in Python. Although the basics of Python are covered, I still recommend reading a primer on Python programming to better understand how programs are written. To that end, I recommend Cracking Codes with Python by Al Sweigart because it demonstrates in-depth usage of strings, lists, and dictionaries with full explanations in a short-form book. 1.6 books 1.6.1 CrackingCodesWithPython package Subpackages 32 Chapter 1. Introduction python-tutorials Documentation, Release 1.1.1 CrackingCodesWithPython.Chapter01 package Submodules CrackingCodesWithPython.Chapter01.PracticeQuestions module Chapter 1 Practice Questions. Answers Chapter 1 Practice Questions via Python code. Notes • Contains spoilers from Chapter 5 (caesar cipher), Chapter 6 (caesar hacker), and Chapter 7 (functions) • Corrections submitted for Questions 1, 3, 4, and 5 CrackingCodesWithPython.Chapter01.PracticeQuestions.main() CrackingCodesWithPython.Chapter01.caesarCipher module Caesar Cipher improved. Rewritten as function with wrapper functions for importing. Note: Contains spoilers from Chapter 5 (caesarCipher) and Chapter 7 (functions) CrackingCodesWithPython.Chapter01.caesarCipher.caesarCipher(key: int, message: str, mode: str) → str Implement caesar cipher. Encrypts or decrypts given message with given key depending on given mode. Parameters • key – Key to use for [de|en]cryption. • message – Message to encrypt/decrypt. • mode – Specifies encryption or decryption. Returns Encrypted/decrypted message string. Example >>> from pythontutorials.books.CrackingCodesWithPython.Chapter01.caesarCipher␣ ,→import caesarCipher >>> caesarCipher(4, 'IMPIETY: YOUR IRREVERENCE TOWARD MY DEITY.', 'encrypt') 'MQTMIXc:AcSYVAMVVIZIVIRGIAXSaEVHAQcAHIMXcD' CrackingCodesWithPython.Chapter01.caesarCipher.decryptMessage(key: int, message: str) → str Decrypts encrypted caesar cipher. Wrapper function that calls caesarCipher() to decrypt given message with given key. Parameters 1.6. books 33 python-tutorials Documentation, Release 1.1.1 • key – Key to use to decrypt message. • message – Message to decrypt. Returns Decrypted message string. CrackingCodesWithPython.Chapter01.caesarCipher.encryptMessage(key: int, message: str) → str Encrypts message with caesar cipher. Wrapper function that calls caesarCipher() to encrypt given message with given key. Parameters • key – Key to use to encrypt message. • message – Message to encrypt. Returns Encrypted message string. CrackingCodesWithPython.Chapter01.caesarHacker module Caesar Hacker improved. Rewritten as function for importing. Note: Contains spoilers from Chapter 6 (caesarHacker) and Chapter 7 (functions) CrackingCodesWithPython.Chapter01.caesarHacker.hackCaesar(message: str) → None Hacks caesar cipher. Loops through and displays every possible key. Parameters message – Message to be decrypted. Returns Prints each decryption with every possible key. CrackingCodesWithPython.Chapter01.constants module Configuration file with global variables. Mainly contains definition of every possible encryptable symbol. CrackingCodesWithPython.Chapter01.constants.SYMBOLS Every possible symbol that can be encrypted. Type str Module contents CrackingCodesWithPython.Chapter02 package Submodules CrackingCodesWithPython.Chapter02.PracticeQuestions module Chapter 2 Practice Questions 34 Chapter 1. Introduction python-tutorials Documentation, Release 1.1.1 Answers Chapter 2 Practice Questions via Python code. Note: To check these questions, they should be entered in IDLE; otherwise print statements would be needed. CrackingCodesWithPython.Chapter02.PracticeQuestions.main() Module contents CrackingCodesWithPython.Chapter03 package Submodules CrackingCodesWithPython.Chapter03.PracticeQuestions module Chapter 3 Practice Questions Answers Chapter 3 Practice Questions via Python code. CrackingCodesWithPython.Chapter03.PracticeQuestions.main() CrackingCodesWithPython.Chapter03.hello module Asks for name and says hello. This program says hello and asks for my name. Notes • Using double quotes for strings because I’m a nitpicker - author admits that he uses single quotes because it is easier to type and it technically doesn’t matter. • Nov. 22, 2018 Update: Switching back to single quotes because a system was compromised because of double quotes. CrackingCodesWithPython.Chapter03.hello.main() Module contents CrackingCodesWithPython.Chapter04 package Submodules CrackingCodesWithPython.Chapter04.PracticeQuestions module Chapter 4 Practice Questions Answers Chapter 4 Practice Questions via Python code. CrackingCodesWithPython.Chapter04.PracticeQuestions.main() 1.6. books 35 python-tutorials Documentation, Release 1.1.1 CrackingCodesWithPython.Chapter04.reverseCipher module Reverse Cipher https://www.nostarch.com/crackingcodes/ (BSD Licensed) Note: Pretty much the same, except I use double quotes, expand variable names for readability, simplify the while loop, and use fancier operators CrackingCodesWithPython.Chapter04.reverseCipher.main() Module contents CrackingCodesWithPython.Chapter05 package Subpackages CrackingCodesWithPython.Chapter05.PracticeQuestions package Submodules CrackingCodesWithPython.Chapter05.PracticeQuestions.Question1 module Chapter 5 Practice Question 1 Using caesarCipher.py, encrypt the following sentences with the given keys. Note: Contains spoilers for Chapter 7 (functions) CrackingCodesWithPython.Chapter05.PracticeQuestions.Question1.main() CrackingCodesWithPython.Chapter05.PracticeQuestions.Question2 module Chapter 5 Practice Question 2 Using caesarCipher.py, decrypt the following ciphertexts with the given keys Note: Contains spoilers for Chapter 7 (functions) CrackingCodesWithPython.Chapter05.PracticeQuestions.Question2.main() CrackingCodesWithPython.Chapter05.PracticeQuestions.Question3 module Chapter 5 Practice Question 3 Which Python instruction would import a module named watermelon.py? 36 Chapter 1. Introduction python-tutorials Documentation, Release 1.1.1 Note: Contains spoilers for Chapter 7 (functions) CrackingCodesWithPython.Chapter05.PracticeQuestions.Question3.main() CrackingCodesWithPython.Chapter05.PracticeQuestions.Question4 module Chapter 5 Practice Question 4 What do the following pieces of code display on the screen? Note: Contains spoilers for Chapter 7 (functions) CrackingCodesWithPython.Chapter05.PracticeQuestions.Question4.main() CrackingCodesWithPython.Chapter05.PracticeQuestions.watermelon module Watermelon.py Demonstration for CrackingCodesWithPython.Chapter05.PracticeQuestions.Question3 Note: Contains spoilers for Chapter 7 (functions) CrackingCodesWithPython.Chapter05.PracticeQuestions.watermelon.main() CrackingCodesWithPython.Chapter05.PracticeQuestions.watermelon.nutrition() → None Watermelon nutrition info. Contains nutrition facts of a serving of watermelon. Returns Prints a series of strings containing the nutrition facts of a serving of watermelon. Module contents Submodules CrackingCodesWithPython.Chapter05.caesarCipher module Caesar Cipher Demonstrates the use of a caesar cipher. Prints output and copies to clipboard. Note: https://www.nostarch.com/crackingcodes/ (BSD Licensed) CrackingCodesWithPython.Chapter05.caesarCipher.main() 1.6. books 37 python-tutorials Documentation, Release 1.1.1 CrackingCodesWithPython.Chapter05.checkPw module Password checker. Checks given input to saved password. CrackingCodesWithPython.Chapter05.checkPw.main() Module contents CrackingCodesWithPython.Chapter06 package Submodules CrackingCodesWithPython.Chapter06.PracticeQuestion module Chapter 6 Practice Questions Answers Chapter 6 Practice Questions via Python code. Break the following ciphertext one line at a time because each line has a different key. Remember to escape any quote characters Note: Contains spoilers for chapter 7 (functions) CrackingCodesWithPython.Chapter06.PracticeQuestion.main() CrackingCodesWithPython.Chapter06.caesarHacker module Caesar Cipher Hacker Demonstrates how to implement a program that hacks a caesar cipher. Note: https://www.nostarch.com/crackingcodes/ (BSD Licensed) CrackingCodesWithPython.Chapter06.caesarHacker.main() Module contents CrackingCodesWithPython.Chapter07 package Subpackages CrackingCodesWithPython.Chapter07.PracticeQuestions package Submodules 38 Chapter 1. Introduction python-tutorials Documentation, Release 1.1.1 CrackingCodesWithPython.Chapter07.PracticeQuestions.Question1 module Chapter 7 Practice Question 1 Encrypt the following with the transposition cipher (with paper and pencil, cough). Note: Contains spoilers for Chapter 9 (importing transpositionEncrypt) CrackingCodesWithPython.Chapter07.PracticeQuestions.Question1.main() CrackingCodesWithPython.Chapter07.PracticeQuestions.Question2 module Chapter 7 Practice Question 2 Is each spam a global or local variable? CrackingCodesWithPython.Chapter07.PracticeQuestions.Question2.foo() → None Prints spam. Prints the contents of the spam variable. Returns Prints spam variable. CrackingCodesWithPython.Chapter07.PracticeQuestions.Question2.main() CrackingCodesWithPython.Chapter07.PracticeQuestions.Question3 module Chapter 7 Practice Question 3 What value does each of the following expressions evaluate to? Note: aka “The power of lists” CrackingCodesWithPython.Chapter07.PracticeQuestions.Question3.main() CrackingCodesWithPython.Chapter07.PracticeQuestions.Question4 module Chapter 7 Practice Question 4 What value does each of the following expressions evaluate to? Note: aka “Lists are OP” CrackingCodesWithPython.Chapter07.PracticeQuestions.Question4.main() CrackingCodesWithPython.Chapter07.PracticeQuestions.Question5 module Chapter 7 Practice Question 5 What are the four augmented assignment operators? 1.6. books 39 python-tutorials Documentation, Release 1.1.1 Note: Hint: Table 7-1 on pg 92 CrackingCodesWithPython.Chapter07.PracticeQuestions.Question5.main() Module contents Submodules CrackingCodesWithPython.Chapter07.addNumbers module Addition function Contains a function that adds two numbers. CrackingCodesWithPython.Chapter07.addNumbers.addNumbers(a: int, b: int) → int Adds two numbers. Performs addition operation to two numbers. Parameters • a – Input to add to • b – Input to be added Returns Result of addition of two inputs. CrackingCodesWithPython.Chapter07.addNumbers.main() CrackingCodesWithPython.Chapter07.helloFunction module Hello function. Contains function that prints hello to given name. CrackingCodesWithPython.Chapter07.helloFunction.hello(name: str) → None Prints hello. Prints hello to given name. Parameters name – Name to say hello to. Returns Prints hello to given name. CrackingCodesWithPython.Chapter07.helloFunction.main() CrackingCodesWithPython.Chapter07.transpositionEncrypt module Transposition Cipher Encryption Demonstrates how to implement a transposition cipher. Note: https://www.nostarch.com/crackingcodes/ (BSD Licensed) 40 Chapter 1. Introduction python-tutorials Documentation, Release 1.1.1 CrackingCodesWithPython.Chapter07.transpositionEncrypt.encryptMessage(key: int, message: str) → str Transposition Cipher Encrypt Encrypts given message using a transposition cipher with given key. Parameters • key – Numeric key to encrypt with. • message – Message to encrypt. Returns Message encrypted in a string. Example >>> encryptMessage(9, 'Underneath a huge oak tree there was of swine a huge company, ,→') 'Uhot on ahoamdakef pe r harhtesunnur wgyegewie,aeean t sec' CrackingCodesWithPython.Chapter07.transpositionEncrypt.main() Module contents CrackingCodesWithPython.Chapter08 package Subpackages CrackingCodesWithPython.Chapter08.PracticeQuestions package Submodules CrackingCodesWithPython.Chapter08.PracticeQuestions.Question1 module Chapter 8 Practice Question 1 Using paper and pencil (cough), decrypt the following messages with the key 9. Note: Contains spoilers for Chapter 9 (importing transpositionDecrypt) CrackingCodesWithPython.Chapter08.PracticeQuestions.Question1.main() CrackingCodesWithPython.Chapter08.PracticeQuestions.Question2 module Chapter 8 Practice Question 2 When you enter the following code into the interactive shell (cough), what does each line print? CrackingCodesWithPython.Chapter08.PracticeQuestions.Question2.main() 1.6. books 41 python-tutorials Documentation, Release 1.1.1 CrackingCodesWithPython.Chapter08.PracticeQuestions.Question3 module Chapter 8 Practice Question 3 Draw the complete truth tables for the and, or, and not operators. CrackingCodesWithPython.Chapter08.PracticeQuestions.Question3.andTruthTable() → None And truth table. Prints a truth table for the and operator. Returns None. Only prints out a table. CrackingCodesWithPython.Chapter08.PracticeQuestions.Question3.main() CrackingCodesWithPython.Chapter08.PracticeQuestions.Question3.notTruthTable() → None Not truth table. Prints a truth table for the not operator. Returns None. Only prints out a table. CrackingCodesWithPython.Chapter08.PracticeQuestions.Question3.orTruthTable() → None Or truth table. Prints a truth table for the or operator. Returns None. Only prints out a table. CrackingCodesWithPython.Chapter08.PracticeQuestions.Question4 module Chapter 8 Practice Question 4 Which of the following is correct? if __name__ == ‘__main__’: if __main__ == ‘__name__’: if _name_ == ‘_main_’: if _main_ == ‘_name_’: Note: answer variable needs to be decrypted with the specified key CrackingCodesWithPython.Chapter08.PracticeQuestions.Question4.main() Module contents Submodules CrackingCodesWithPython.Chapter08.transpositionDecrypt module Transposition Cipher Decryption Decrypts transposition cipher messages. Note: https://www.nostarch.com/crackingcodes/ (BSD Licensed) 42 Chapter 1. Introduction python-tutorials Documentation, Release 1.1.1 CrackingCodesWithPython.Chapter08.transpositionDecrypt.decryptMessage(key: int, message: str) → str Decrypt transposition cipher. Decrypts transposition cipher messages with given key. Parameters • key – Numeric key to use for decryption. • message – Message string to decrypt. Returns Decrypted message in a string. CrackingCodesWithPython.Chapter08.transpositionDecrypt.main() Module contents CrackingCodesWithPython.Chapter09 package Submodules CrackingCodesWithPython.Chapter09.PracticeQuestions module Chapter 9 Practice Questions Answers Chapter 9 Practice Questions via Python code. CrackingCodesWithPython.Chapter09.PracticeQuestions.main() CrackingCodesWithPython.Chapter09.passingReference module Passing references in a function Demonstrates how to pass a reference to a function. CrackingCodesWithPython.Chapter09.passingReference.eggs(someParameter: list) → None Append to a parameter. Appends ‘Hello’ to a given parameter. Parameters someParameter – List of elements. Returns None. Only appends a string to a provided parameter. CrackingCodesWithPython.Chapter09.passingReference.main() CrackingCodesWithPython.Chapter09.transpositionTest module Transposition Cipher Test Demonstrates a unit test for the transposition encrypt and decrypt functions. Note: https://www.nostarch.com/crackingcodes/ (BSD Licensed) CrackingCodesWithPython.Chapter09.transpositionTest.main() 1.6. books 43 python-tutorials Documentation, Release 1.1.1 Module contents CrackingCodesWithPython.Chapter10 package Submodules CrackingCodesWithPython.Chapter10.PracticeQuestions module Chapter 10 Practice Questions Answers Chapter 10 Practice Questions via Python code. CrackingCodesWithPython.Chapter10.PracticeQuestions.main() CrackingCodesWithPython.Chapter10.transpositionFileCipher module Transposition Cipher Encrypt/Decrypt File Implements a transposition cipher that can encrypt/decrypt a file. Note: https://www.nostarch.com/crackingcodes/ (BSD Licensed) CrackingCodesWithPython.Chapter10.transpositionFileCipher.main() Module contents CrackingCodesWithPython.Chapter11 package Submodules CrackingCodesWithPython.Chapter11.PracticeQuestions module Chapter 11 Practice Questions Answers Chapter 11 Practice Questions via Python code. CrackingCodesWithPython.Chapter11.PracticeQuestions.main() CrackingCodesWithPython.Chapter11.detectEnglish module Detect English Module Provides functions to determine whether a given string is in the English language. CrackingCodesWithPython.Chapter11.detectEnglish.UPPERLETTERS String containing all latin-based letters in uppercase. Type str CrackingCodesWithPython.Chapter11.detectEnglish.LETTERS_AND_SPACE String containing upper and lowercase letters as well as space, newline, and tab. Type str 44 Chapter 1. Introduction python-tutorials Documentation, Release 1.1.1 CrackingCodesWithPython.Chapter11.detectEnglish.DICTIONARY_FILE String containing absolute path of dictionary.txt file. Type str CrackingCodesWithPython.Chapter11.detectEnglish.ENGLISH_WORDS Dictionary containing all words from dictionary.txt as keys. Type dict Example >>> import pythontutorials.books.CrackingCodesWithPython.Chapter11.detectEnglish as␣ ,→detectEnglish >>> someString = 'Enthusiasm is contagious. Not having enthusiasm is also contagious.' >>> detectEnglish.isEnglish(someString) # Returns True or False True Note: • https://www.nostarch.com/crackingcodes/ (BSD Licensed) • There must be a “dictionary.txt” file in this directory with all English words in it, one word per line. You can download this from https://www.nostarch.com/crackingcodes/. CrackingCodesWithPython.Chapter11.detectEnglish.getEnglishCount(message: str) → float Get count of English words For given message, counts number of words in English dictionary and returns ratio of English words out of total words. Parameters message – String with message to check for English words. Returns Ratio of number of English words / total number of words. CrackingCodesWithPython.Chapter11.detectEnglish.isEnglish(message: str, wordPercentage: int = 20, letterPercentage: int = 85) → bool Determines whether message is English Using given word percentage and letter percentage, determines if a given message is in the English language. Parameters • message – String containing message to determine if it is English. • wordPercentage – Integer representing percentage of words in message that must be English. • letterPercentage – Integer representing percentage of characters in message that must be letters or spaces. Returns True if message is in English language, False otherwise. Note: • By default, 20% of the words must exist in the dictionary file, and 85% of all the characters in the message must be letters or spaces (not punctuation or numbers). 1.6. books 45 python-tutorials Documentation, Release 1.1.1 CrackingCodesWithPython.Chapter11.detectEnglish.loadDictionary() → dict Load dictionary file Loads dictionary.txt file and creates a dictionary with all words as keys. Returns Dictionary with all words in dictionary.txt as keys. CrackingCodesWithPython.Chapter11.detectEnglish.removeNonLetters(message: str) → str Removes non-letters Removes non-letter characters from given message. Parameters message – String with message to remove non-letter characters from. Returns New string with non-letter characters removed. Module contents CrackingCodesWithPython.Chapter12 package Submodules CrackingCodesWithPython.Chapter12.PracticeQuestions module Chapter 12 Practice Questions Answers Chapter 12 Practice Questions via Python code. CrackingCodesWithPython.Chapter12.PracticeQuestions.main() CrackingCodesWithPython.Chapter12.transpositionHacker module Transposition Cipher Hacker Implements a function that can hack a transposition cipher encrypted message. Note: • https://www.nostarch.com/crackingcodes/ (BSD Licensed) CrackingCodesWithPython.Chapter12.transpositionHacker.hackTransposition(message: str) Hacks transposition cipher encrypted messages Brute-forces a given encrypted message by looping through all the keys, checking if the result is English, and prompting the user for confirmation of decryption. Parameters message – String with message to brute-force. Returns Prints out possible results and prompts user for confirmation. If confirmed, prints out and returns full decrypted message, otherwise returns None. CrackingCodesWithPython.Chapter12.transpositionHacker.main() 46 Chapter 1. Introduction python-tutorials Documentation, Release 1.1.1 Module contents CrackingCodesWithPython.Chapter13 package Submodules CrackingCodesWithPython.Chapter13.PracticeQuestions module Chapter 13 Practice Questions Answers Chapter 13 Practice Questions via Python code. CrackingCodesWithPython.Chapter13.PracticeQuestions.main() CrackingCodesWithPython.Chapter13.cryptomath module Cryptomath Module Provides mathematical functions for use in cryptography. (Discrete mathematics FTW!) Note: • https://www.nostarch.com/crackingcodes/ (BSD Licensed) CrackingCodesWithPython.Chapter13.cryptomath.findModInverse(a: int, m: int) Modular inverse Returns modular inverse of given inputs using Euclid’s extended algorithm. Parameters • a – First integer input. • m – Second integer input. Returns Modular inverse as an integer if it exists, None otherwise. CrackingCodesWithPython.Chapter13.cryptomath.gcd(a: int, b: int) → int Greatest common divisor Returns greatest common divisor of given inputs using Euclid’s algorithm. Parameters • a – First integer input. • b – Second integer input. Returns Integer representing GCD. Module contents CrackingCodesWithPython.Chapter14 package Submodules 1.6. books 47 python-tutorials Documentation, Release 1.1.1 CrackingCodesWithPython.Chapter14.PracticeQuestions module Chapter 14 Practice Questions Answers Chapter 14 Practice Questions via Python code. CrackingCodesWithPython.Chapter14.PracticeQuestions.main() CrackingCodesWithPython.Chapter14.affineCipher module Affine Cipher Provides functions that implement affine cipher encryption and decryption. CrackingCodesWithPython.Chapter14.affineCipher.SYMBOLS String containing all symbols that can be encrypted/decrypted. Type str Example >>> import pythontutorials.books.CrackingCodesWithPython.Chapter14.affineCipher as␣ ,→affineCipher >>> someString = 'Enthusiasm is contagious. Not having enthusiasm is also contagious.' >>> key = affineCipher.getRandomKey() # key = 921, in this example >>> affineCipher.encryptMessage(key, someString) 'xq3eBprFpdLrpLf4q3FRr4BpyLi43LeFOrqRL6q3eBprFpdLrpLFQp4Lf4q3FRr4Bpy' Note: • https://www.nostarch.com/crackingcodes/ (BSD Licensed) • There must be a “dictionary.txt” file in this directory with all English words in it, one word per line. You can download this from https://www.nostarch.com/crackingcodes/. CrackingCodesWithPython.Chapter14.affineCipher.checkKeys(keyA: int, keyB: int, mode: str) → None Checks keys for validity. Prevents keyA from being 1 and keyB from being 0 (if encrypting). Makes sure keyA is relatively prime with the length of SYMBOLS. Ensures keyA is greater than 0 and that keyB is between 0 and length of SYMBOLS. Parameters • keyA – Integer integral of the original key after floor division by length of SYMBOLS. • keyB – Integer remainder of the original key after modulus by length of SYMBOLS. • mode – String specifying whether to ‘encrypt’ or ‘decrypt’. Returns None if successful, exits program with error message otherwise. CrackingCodesWithPython.Chapter14.affineCipher.decryptMessage(key: int, message: str) → str Affine cipher decryption Decrypts given affine cipher encrypted message with given key. 48 Chapter 1. Introduction python-tutorials Documentation, Release 1.1.1 Parameters • key – Integer decryption key to decrypt affine cipher. • message – Message string to decrypt. Returns Decrypted message string. CrackingCodesWithPython.Chapter14.affineCipher.encryptMessage(key: int, message: str) → str Affine cipher encryption Encrypts given message with given key using the affine cipher. Parameters • key – Integer encryption key to encrypt with affine cipher. • message – Message string to encrypt. Returns Encrypted message string. CrackingCodesWithPython.Chapter14.affineCipher.getKeyParts(key: int) -> ( , ) Split key into parts Splits key into keyA and keyB via floor division and modulus by length of SYMBOLS. Parameters key – Integer key used to encrypt message. Returns Tuple containing the integral and remainder. CrackingCodesWithPython.Chapter14.affineCipher.getRandomKey() → int Affine cipher key generator Generates a random key that can be used with the affine cipher. Returns Random, valid integer key CrackingCodesWithPython.Chapter14.affineCipher.main() CrackingCodesWithPython.Chapter14.affineKeyTest module Test affine cipher keyspace This program proves that the keyspace of the affine cipher is limited to less than len(SYMBOLS) ^ 2. Note: Tests every key from 2 through 80 and prints it with the encrypted message if the key and length of SYMBOLS have a gcd. CrackingCodesWithPython.Chapter14.affineKeyTest.main() Module contents CrackingCodesWithPython.Chapter15 package Submodules 1.6. books 49 python-tutorials Documentation, Release 1.1.1 CrackingCodesWithPython.Chapter15.PracticeQuestions module Chapter 15 Practice Questions Answers Chapter 15 Practice Questions via Python code. CrackingCodesWithPython.Chapter15.PracticeQuestions.main() CrackingCodesWithPython.Chapter15.affineHacker module Affine Cipher Hacker Implements a function that can hack an affine cipher encrypted message. CrackingCodesWithPython.Chapter15.affineHacker.SILENT_MODE Specifies whether to print all key attempts. Type bool Note: • https://www.nostarch.com/crackingcodes/ (BSD Licensed) CrackingCodesWithPython.Chapter15.affineHacker.hackAffine(message: str) Hacks affine cipher encrypted messages Brute-forces a given encrypted message by looping through all the keys, checking if the result is English, and prompting the user for confirmation of decryption. Parameters message – String with message to brute-force. Returns Prints out possible results and prompts user for confirmation. If confirmed, prints out and returns full decrypted message, otherwise returns None. CrackingCodesWithPython.Chapter15.affineHacker.main() Module contents CrackingCodesWithPython.Chapter16 package Submodules CrackingCodesWithPython.Chapter16.PracticeQuestions module Chapter 16 Practice Questions Answers Chapter 16 Practice Questions via Python code. CrackingCodesWithPython.Chapter16.PracticeQuestions.main() CrackingCodesWithPython.Chapter16.simpleSubCipher module Simple Substitution Cipher Provides functions that implement a substitution cipher. 50 Chapter 1. Introduction python-tutorials Documentation, Release 1.1.1 CrackingCodesWithPython.Chapter16.simpleSubCipher.LETTERS String containing uppercase latin letters. Type str Example >>> import pythontutorials.books.CrackingCodesWithPython.Chapter16.simpleSubCipher as␣ ,→simpleSubCipher >>> key = simpleSubCipher.getRandomKey() # key = 'VIAXLGJBKSZDUTRPYCEWNFHOMQ', in this␣ ,→example >>> message = 'You\'d be surprised what you can live through.' >>> simpleSubCipher.encryptMessage(key, message) "Mrn'x il encpckelx hbvw mrn avt dkfl wbcrnjb" Note: • https://www.nostarch.com/crackingcodes/ (BSD Licensed) CrackingCodesWithPython.Chapter16.simpleSubCipher.decryptMessage(key: str, message: str) → str Substitution Cipher Decrypt Wrapper function that decrypts given substitution cipher encrypted message with the given key. Parameters • key – String containing key used to decrypt substitution cipher. • message – String containing message to decrypt. Returns Decrypted message. CrackingCodesWithPython.Chapter16.simpleSubCipher.encryptMessage(key: str, message: str) → str Substitution Cipher Encrypt Wrapper function that encrypts given message with the given key using the substitution cipher. Parameters • key – String containing key used to encrypt with substitution cipher. • message – String containing message to encrypt. Returns Encrypted message. CrackingCodesWithPython.Chapter16.simpleSubCipher.getRandomKey() → str Substitution cipher key generator Generates a random key that can be used with the substitution cipher. Returns String with a random, valid key. CrackingCodesWithPython.Chapter16.simpleSubCipher.keyIsValid(key: str) → bool Checks key for validity. Ensures key contains all letters in LETTERS. Parameters key – String containing key used to encrypt with substitution cipher. Returns True if key and LETTERS match, False otherwise. 1.6. books 51 python-tutorials Documentation, Release 1.1.1 CrackingCodesWithPython.Chapter16.simpleSubCipher.main() CrackingCodesWithPython.Chapter16.simpleSubCipher.translateMessage(key: str, message: str, mode: str) → str Substitution Cipher Implements a substitution cipher that can encrypt or decrypt messages depending on the given mode. Parameters • key – String containing key used to decrypt/encrypt messages. • message – String containing message to decrypt/encrypt. • mode – String specifying whether to ‘encrypt’ or ‘decrypt’. Returns Encrypted or decrypted message. Module contents CrackingCodesWithPython.Chapter17 package Submodules CrackingCodesWithPython.Chapter17.PracticeQuestions module Chapter 17 Practice Questions Answers Chapter 17 Practice Questions via Python code. CrackingCodesWithPython.Chapter17.PracticeQuestions.main() CrackingCodesWithPython.Chapter17.makeWordPatterns module Make wordPatterns.py file Creates CrackingCodesWithPython.Chapter17.wordPatterns based on the words in our dictionary text file, dictionary.txt. A word pattern assigns a number to each letter in a word, then generates a pattern representation of that word based on the number assigned to each letter. CrackingCodesWithPython.Chapter17.makeWordPatterns.DICTIONARY_FILE String containing absolute path to dictionary.txt file. Type str Note: • Download the dictionary file from https://invpy.com/dictionary.txt • https://www.nostarch.com/crackingcodes (BSD Licensed) CrackingCodesWithPython.Chapter17.makeWordPatterns.getWordPattern(word: str) → str Get word pattern Returns a string of the pattern form of the given word. Parameters word – String containing word to convert into word pattern. 52 Chapter 1. Introduction python-tutorials Documentation, Release 1.1.1 Example: >>> import pythontutorials.books.CrackingCodesWithPython.Chapter17.makeWordPatterns as makeWordPatterns >>> makeWordPatterns.getWordPattern(‘DUSTBUSTER’) ‘0.1.2.3.4.1.2.3.5.6’ Returns String containing word pattern. CrackingCodesWithPython.Chapter17.makeWordPatterns.main() CrackingCodesWithPython.Chapter17.simpleSubHacker module Simple Substitution Cipher Hacker Implements a function that can hack a substitution cipher encrypted message. CrackingCodesWithPython.Chapter17.simpleSubHacker.LETTERS String containing uppercase latin letters. Type str CrackingCodesWithPython.Chapter17.simpleSubHacker.nonLettersOrSpacePattern Regular expression object representing all non-letter characters and space. Type re._sre.SRE_Pattern Note: • https://www.nostarch.com/crackingcodes/ (BSD Licensed) CrackingCodesWithPython.Chapter17.simpleSubHacker.addLettersToMapping(letterMapping: dict, cipherword: str, candidate: str) → None Add letters to cipherletter mapping The letterMapping parameter takes a dictionary value that stores a cipherletter mapping, which is copied by the function. The cipherword parameter is a string value of the ciphertext word. The candidate parameter is a possible English word that the cipherword could decrypt to. This function adds the letters in the candidate as potential decryption letters for the cipherletters in the cipherletter mapping. Parameters • letterMapping – Dictionary containing a cipherletter mapping. • cipherword – String containing an encrypted ciphertext word. • candidate – String containing an English word the cipherword could potentially decrypt to. Returns None. Modifies contents of letterMapping by adding letters to the cipherletter mapping. CrackingCodesWithPython.Chapter17.simpleSubHacker.decryptWithCipherletterMapping(ciphertext: str, letterMapping: dict) → str 1.6. books 53 python-tutorials Documentation, Release 1.1.1 Decrypt substitution cipher message with cipherletter map Decrypts given substitution cipher encrypted message with given dictionary containing a cipherletter map. Parameters • ciphertext – Substitution cipher encrypted message to decrypt. • letterMapping – Dictionary with cipherletter map that may decrypt the ciphertext. Returns String containing decrypted ciphertext message. Note: • Ambiguous decrypted letters are replaced with an underscore, ‘_’ CrackingCodesWithPython.Chapter17.simpleSubHacker.getBlankCipherletterMapping() → dict Get blank cipherletter mapping Returns a dictionary value that is a blank cipherletter mapping Returns Returns dictionary with uppercase latin letters as keys and empty lists as values. CrackingCodesWithPython.Chapter17.simpleSubHacker.hackSimpleSub(message: str) → dict Hack simple substitution cipher Hacks simple substitution cipher and returns dictionary with cipherletter map that may be able to decrypt given message. Parameters message – String containing substitution cipher encrypted message. Returns Dictionary with cipherletter map that may decrypt given message. CrackingCodesWithPython.Chapter17.simpleSubHacker.intersectMappings(mapA: dict, mapB: dict) → dict Intersects two cipherletter mappings Checks each letter in LETTERS and adds to intersected map if it exists in both given maps. If either map is empty, the non-empty map is copied to the intersected map. Parameters • mapA – Dictionary containing potential decryption letters. • mapB – Dictionary containing potential decryption letters. Returns Dictionary containing intersected map of potential decryption letters. CrackingCodesWithPython.Chapter17.simpleSubHacker.main() CrackingCodesWithPython.Chapter17.simpleSubHacker.removeSolvedLettersFromMapping(letterMapping: dict) → dict Removes solved letters from cipherletter mapping Cipherletters in the mapping that map to only one letter are “solved” and can be removed from the other letters. For example, if ‘A’ maps to potential letters [‘M’, ‘N’] and ‘B’ maps to [‘N’], then we know that ‘B’ must map to ‘N’, so we can remove ‘N’ from the list of what ‘A’ could map to. So ‘A’ then maps to [‘M’]. 54 Chapter 1. Introduction python-tutorials Documentation, Release 1.1.1 Note that now that ‘A’ maps to only one letter, we can remove ‘M’ from the list of letters for every other letter. (This is why there is a loop that keeps reducing the map.) Parameters letterMapping – Cipherletter map dictionary to remove solved letters from. Returns Dictionary containing cipherletter map with solved letters removed. CrackingCodesWithPython.Chapter17.wordPatterns module Word patterns file Dictionary with word patterns as keys and a list of words matching the word pattern as values. CrackingCodesWithPython.Chapter17.wordPatterns.allPatterns Dictionary containing all word patterns in dictionary.txt Type dict Example >>> {'0.0.1': ['EEL']} Note: • Docstring gets erased when wordPatterns.py is generated by CrackingCodesWithPython.Chapter17. makeWordPatterns Module contents CrackingCodesWithPython.Chapter18 package Submodules CrackingCodesWithPython.Chapter18.PracticeQuestions module Chapter 18 Practice Questions Answers Chapter 18 Practice Questions via Python code. CrackingCodesWithPython.Chapter18.PracticeQuestions.main() CrackingCodesWithPython.Chapter18.stringTest module Create string test Timing string concatenation vs list appending to make a string. Note: • Prints time to make a 10000 character string 10000 times as seconds since the Unix epoch. 1.6. books 55 python-tutorials Documentation, Release 1.1.1 CrackingCodesWithPython.Chapter18.stringTest.main() CrackingCodesWithPython.Chapter18.vigenereCipher module Vigenère Cipher (Polyalphabetic Substitution Cipher) Provides functions that implement a Vigenère cipher. CrackingCodesWithPython.Chapter18.vigenereCipher.LETTERS String containing uppercase latin letters. Type str Example >>> import pythontutorials.books.CrackingCodesWithPython.Chapter18.vigenereCipher as␣ ,→vigenereCipher >>> key = 'supercalifragilisticexpialidocious' >>> message = 'A soul shines brightest when it stands alongside the darkness. -Anon,␣ ,→probably' >>> vigenereCipher.encryptMessage(key, message) 'S mdyc uhtvjj bxqrplxav aetv ie awoplg udghvwzfe epj uaxsymkl. -Ipsk, ezomieza' Note: • https://www.nostarch.com/crackingcodes/ (BSD Licensed) CrackingCodesWithPython.Chapter18.vigenereCipher.decryptMessage(key: str, message: str) → str Vigenère cipher decryption Wrapper function that decrypts given message with given key using the Vigenère cipher. Parameters • key – String decryption key to encrypt with Vigenère cipher. • message – Message string to decrypt. Returns Decrypted message string. CrackingCodesWithPython.Chapter18.vigenereCipher.encryptMessage(key: str, message: str) → str Vigenère cipher encryption Wrapper function that encrypts given message with given key using the Vigenère cipher. Parameters • key – String encryption key to encrypt with Vigenère cipher. • message – Message string to encrypt. Returns Encrypted message string. CrackingCodesWithPython.Chapter18.vigenereCipher.main() 56 Chapter 1. Introduction python-tutorials Documentation, Release 1.1.1 CrackingCodesWithPython.Chapter18.vigenereCipher.translateMessage(key: str, message: str, mode: str) → str Vigenère cipher Implements a Vigenère cipher that can encrypt or decrypt messages depending on the given mode. Parameters • key – String containing key used to decrypt/encrypt messages. • message – String containing message to decrypt/encrypt. • mode – String specifying whether to ‘encrypt’ or ‘decrypt’. Returns Encrypted or decrypted message. Module contents CrackingCodesWithPython.Chapter19 package Submodules CrackingCodesWithPython.Chapter19.PracticeQuestions module Chapter 19 Practice Questions Answers Chapter 19 Practice Questions via Python code. CrackingCodesWithPython.Chapter19.PracticeQuestions.main() CrackingCodesWithPython.Chapter19.freqAnalysis module Frequency Finder Analyzes frequency of letters in given message compared to the most common occurring letters to determine if message is in the English language. CrackingCodesWithPython.Chapter19.freqAnalysis.ETAOIN String containing uppercase latin letters in order from most to least common. Type str CrackingCodesWithPython.Chapter19.freqAnalysis.LETTERS String containing uppercase latin letters in alphabetical order. Type str Note: • Compares six most and six least common letters in the English language. • https://www.nostarch.com/crackingcodes/ (BSD Licensed) CrackingCodesWithPython.Chapter19.freqAnalysis.englishFreqMatchScore(message: int English Frequency Match Score str) → Calculates number of matches that the string in the message parameter has when its letter frequency is compared to English letter frequency. 1.6. books 57 python-tutorials Documentation, Release 1.1.1 Parameters message – String containing message to calculate English match score. Returns Number representing message’s matches to English letter frequency. Note: • A “match” is how many of its six most frequent and six least frequent letters are among the six most frequent and six least frequent letters for English. • A “perfect score” is 12 CrackingCodesWithPython.Chapter19.freqAnalysis.getFrequencyOrder(message: str) → str Get frequency order Analyzes frequency of each letter in given message and returns string with each letter from most to least frequent. Parameters message – String containing message to analyze frequency. Returns String of the alphabet letters arranged in order of most frequently occurring in the message parameter. CrackingCodesWithPython.Chapter19.freqAnalysis.getItemAtIndexZero(items: tuple) Get element at index zero Helper function that returns the first element of a given tuple. Parameters items – Tuple containing a latin letter and its frequency count. Returns the latin letter. Return type The first element of the given tuple CrackingCodesWithPython.Chapter19.freqAnalysis.getLetterCount(message: str) → dict Get letter count Counts the frequency of all latin letters in a given message. Parameters message – String containing message to analyze letter frequency. Returns Dictionary with keys of single letters and values of the count of how many times they appear in the message parameter. Module contents CrackingCodesWithPython.Chapter20 package Submodules CrackingCodesWithPython.Chapter20.PracticeQuestions module Chapter 20 Practice Questions Answers Chapter 20 Practice Questions via Python code. CrackingCodesWithPython.Chapter20.PracticeQuestions.main() 58 Chapter 1. Introduction python-tutorials Documentation, Release 1.1.1 CrackingCodesWithPython.Chapter20.vigenereDictionaryHacker module Vigenère Cipher Dictionary Hacker Implements a function that can hack a Vigenère cipher encrypted message using a dictionary. CrackingCodesWithPython.Chapter20.vigenereDictionaryHacker.DICTIONARY_FILE String with absolute location of dictionary.txt file. Type str Note: • https://www.nostarch.com/crackingcodes/ (BSD Licensed) CrackingCodesWithPython.Chapter20.vigenereDictionaryHacker.hackVigenereDictionary(ciphertext: str) Hack Vigenère Dictionary Brute-forces ciphertext by using every word in the dictionary file as a key. Checks if decrypted message is English with the isEnglish() module, and prompts user for confirmation by displaying first 100 characters. Parameters ciphertext – String containing Vigenère cipher encrypted message. Returns Decrypted message, if confirmed, None otherwise. CrackingCodesWithPython.Chapter20.vigenereDictionaryHacker.main() CrackingCodesWithPython.Chapter20.vigenereHacker module Vigenère Cipher Hacker Implements a series of functions that can hack a Vigenère cipher encrypted message by brute-forcing key lengths. CrackingCodesWithPython.Chapter20.vigenereHacker.LETTERS String with uppercase latin letters. Type str CrackingCodesWithPython.Chapter20.vigenereHacker.MAX_KEY_LENGTH Will not attempt keys longer than this. Type int CrackingCodesWithPython.Chapter20.vigenereHacker.NUM_MOST_FREQ_LETTERS Attempt this many letters per subkey. Type int CrackingCodesWithPython.Chapter20.vigenereHacker.SILENT_MODE If set to True, program doesn’t print anything. Type bool CrackingCodesWithPython.Chapter20.vigenereHacker.NONLETTERS_PATTERN Regular expression object representing all non-letter characters. Type re._sre.SRE_Pattern 1.6. books 59 python-tutorials Documentation, Release 1.1.1 Note: • https://www.nostarch.com/crackingcodes/ (BSD Licensed) CrackingCodesWithPython.Chapter20.vigenereHacker.attemptHackWithKeyLength(ciphertext: str, mostLikelyKeyLength: int) Attempt hack with key length Brute-forces ciphertext using every key of a given length, checks if decrypted message is English with the isEnglish() module, and prompts user for confirmation by displaying first 200 characters. Parameters • ciphertext – String with encrypted message. • mostLikelyKeyLength – Integer representing the length of the key used to encrypt message. Returns Decrypted message, if confirmed, None otherwise. Note: • Key length is not limited to likely key lengths from kasiskiExamination(). CrackingCodesWithPython.Chapter20.vigenereHacker.findRepeatSequencesSpacings(message: str) → dict Find spacing between repeat sequences Goes through the message and finds any 3- to 5-letter sequences that are repeated. Then counts the number of letters between the repeated sequences. Parameters message – String with message to find repeat sequence spacing. Returns Dictionary with the keys of the sequence and values of a list of spacings (num of letters between the repeats). CrackingCodesWithPython.Chapter20.vigenereHacker.getItemAtIndexOne(x: tuple) → int Get item at index one Helper function that returns the second element of given tuple. Parameters x – Tuple with integers as values. Returns Second element of x. CrackingCodesWithPython.Chapter20.vigenereHacker.getMostCommonFactors(seqFactors: dict) → list Get most common factors Counts how often each factor in the seqFactors dictionary occurs and returns a list of tuples with each factor and its count. Parameters seqFactors – Dictionary with 3- to 5- letter sequences as keys and the factors of the spacings between them as values. Returns A list of tuples of each factor and its count. 60 Chapter 1. Introduction python-tutorials Documentation, Release 1.1.1 CrackingCodesWithPython.Chapter20.vigenereHacker.getNthSubkeysLetters(nth: int, keyLength: int, message: str) → str Get nth subkeys letters Gets every nth letter for each set of letters of a given length in a given text. Parameters • nth – Integer representing desired letter in message (similar to an index number). • keyLength – Integer representing length of key to use (spacing between nth letters). • message – String containing text to extract subkey letters from. Returns String with every nth letter for each specified key length. Examples >>> getNthSubkeysLetters(1, 'AAA' >>> getNthSubkeysLetters(2, 'BBB' >>> getNthSubkeysLetters(3, 'CCC' >>> getNthSubkeysLetters(1, 'AF' 3, 'ABCABCABC') 3, 'ABCABCABC') 3, 'ABCABCABC') 5, 'ABCDEFGHI') CrackingCodesWithPython.Chapter20.vigenereHacker.getUsefulFactors(num: int) → list Get useful factors Returns a list of useful factors of num. By “useful” we mean factors less than MAX_KEY_LENGTH + 1 and not 1. Parameters num – Integer to get useful factors of. Returns List of useful factors, if found, empty list otherwise. Example >>> getUsefulFactors(144) [2, 3, 4, 6, 8, 9, 12, 16] CrackingCodesWithPython.Chapter20.vigenereHacker.hackVigenere(ciphertext: str) Hack vigenere Hacks Vigenère cipher encrypted message using likely key lengths, otherwise all possible key lengths. Parameters ciphertext – String containing Vigenère cipher encrypted message. Returns Decrypted message, if confirmed, None otherwise. CrackingCodesWithPython.Chapter20.vigenereHacker.kasiskiExamination(ciphertext: str) → list Kasiski Examination Uses Kasiski Examination to determine the likely length of the key used to encrypt the given ciphertext. Parameters ciphertext – String containing encrypted message. 1.6. books 61 python-tutorials Documentation, Release 1.1.1 Returns List of likely key lengths used to encrypt message. CrackingCodesWithPython.Chapter20.vigenereHacker.main() Module contents CrackingCodesWithPython.Chapter21 package Submodules CrackingCodesWithPython.Chapter21.PracticeQuestions module Chapter 21 Practice Questions Answers Chapter 21 Practice Questions via Python code. CrackingCodesWithPython.Chapter21.PracticeQuestions.main() Module contents CrackingCodesWithPython.Chapter22 package Submodules CrackingCodesWithPython.Chapter22.PracticeQuestions module Chapter 22 Practice Questions Answers Chapter 22 Practice Questions via Python code. CrackingCodesWithPython.Chapter22.PracticeQuestions.main() CrackingCodesWithPython.Chapter22.primeNum module Prime Number Sieve Implements a series of functions that determine if a given number is prime. CrackingCodesWithPython.Chapter22.primeNum.LOW_PRIMES List containing prime numbers <= 100 (aka ‘low primes’). Type list Note: • https://www.nostarch.com/crackingcodes/ (BSD Licensed) CrackingCodesWithPython.Chapter22.primeNum.generateLargePrime(keysize: int = 1024) → int Generate large prime number Generates random numbers of given bit size until one is prime. Parameters keysize – Number of bits prime number should be. 62 Chapter 1. Introduction python-tutorials Documentation, Release 1.1.1 Returns Random prime number that is keysize bits in size. Note: • keysize defaults to 1024 bits. CrackingCodesWithPython.Chapter22.primeNum.isPrime(num: int) → bool Is prime This function checks divisibility by LOW_PRIMES before calling rabinMiller(). Parameters num – Integer to check if prime. Returns True if num is prime, False otherwise. Note: • If a number is divisible by a low prime number, it is not prime. CrackingCodesWithPython.Chapter22.primeNum.isPrimeTrialDiv(num: int) → bool Is prime trial division Uses the trial division algorithm for testing if a given number is prime. Parameters num – Integer to determine if prime. Returns True if num is a prime number, otherwise False. CrackingCodesWithPython.Chapter22.primeNum.primeSieve(sieveSize: int) → list Prime sieve Calculates prime numbers using the Sieve of Eratosthenes algorithm. Parameters sieveSize – Largest number to check if prime starting from zero. Returns List containing prime numbers from 0 to given number. CrackingCodesWithPython.Chapter22.primeNum.rabinMiller(num: int) → bool Rabin-Miller primality test Uses the Rabin-Miller primality test to check if a given number is prime. Parameters num – Number to check if prime. Returns True if num is prime, False otherwise. Note: • The Rabin-Miller primality test relies on unproven assumptions, therefore it can return false positives when given a pseudoprime. Module contents CrackingCodesWithPython.Chapter23 package Submodules 1.6. books 63 python-tutorials Documentation, Release 1.1.1 CrackingCodesWithPython.Chapter23.PracticeQuestions module Chapter 23 Practice Questions Answers Chapter 23 Practice Questions via Python code. CrackingCodesWithPython.Chapter23.PracticeQuestions.main() CrackingCodesWithPython.Chapter23.makePublicPrivateKeys module Public Key Generator Implements series of functions capable of creating a textbook RSA public/private keypair and saves them to text files. Note: • https://www.nostarch.com/crackingcodes/ (BSD Licensed) • ‘Textbook/Plain’ RSA keys are not secure and should not be used to encrypt sensitive data. CrackingCodesWithPython.Chapter23.makePublicPrivateKeys.generateKey(keySize: int) → tuple Generate public/private keypair Creates public/private keys keySize bits in size. Parameters keySize – Bit size to make public/private keys. Returns Tuples containing the public and private keypair split into their two halves. CrackingCodesWithPython.Chapter23.makePublicPrivateKeys.main() CrackingCodesWithPython.Chapter23.makePublicPrivateKeys.makeKeyFiles(name: str, keySize: int) → None Make key files Creates two files ‘x_pubkey.txt’ and ‘x_privkey.txt’ (where x is the value in name) with the n,e and d,e integers written in them, delimited by a comma. Parameters • name – Name to append to public/private key files. • keySize – Bit size to make public/private keys. Returns None. Key files are created in current working directory. Note: • Checks if key files with given name already exist and exits with warning if so. Module contents CrackingCodesWithPython.Chapter24 package 64 Chapter 1. Introduction python-tutorials Documentation, Release 1.1.1 Submodules CrackingCodesWithPython.Chapter24.publicKeyCipher module Public Key Cipher Implements a series of functions capable of encrypting and decrypting with textbook RSA public/private keypairs. CrackingCodesWithPython.Chapter24.publicKeyCipher.SYMBOLS String with all characters to be encrypted/decrypted. Type str CrackingCodesWithPython.Chapter24.publicKeyCipher.PUBLIC_KEY_PATH String with absolute location of public key file. Type str CrackingCodesWithPython.Chapter24.publicKeyCipher.PRIVATE_KEY_PATH String with absolute location of private key file. Type str Note: • https://www.nostarch.com/crackingcodes/ (BSD Licensed) • The public and private keys are created by the CrackingCodesWithPython.Chapter23. makePublicPrivateKeys module. • ‘Textbook/Plain’ RSA keys are not secure and should not be used to encrypt sensitive data. CrackingCodesWithPython.Chapter24.publicKeyCipher.decryptMessage(encryptedBlocks: list, messageLength: int, key: tuple, blockSize: int) → str Decrypt Message Decrypts a list of encrypted block integers back to the original message string. Parameters • encryptedBlocks – List containing block integers encrypted with PUBLIC key. • messageLength – Length of the original message. • key – Tuple with PRIVATE key used to decryption. • blockSize – Bit size of block integers (usually specified in PRIVATE key file). Returns Original message before block integer conversion and PUBLIC key encryption. Notes • The original message length is required to properly decrypt the last block. • Ensure to pass the PRIVATE key to decrypt. 1.6. books 65 python-tutorials Documentation, Release 1.1.1 CrackingCodesWithPython.Chapter24.publicKeyCipher.encryptAndWriteToFile(messageFilename: str, keyFilename: str, message: str, blockSize: int = None) → str Encrypt and write to file Using a key from a keyfile, encrypt the message and save it to a file. Parameters • messageFilename – String containing name of file to save encrypted message to. • keyFilename – String containing absolute file path of PUBLIC key file. • message – String containing message to encrypt and save. • blockSize – Bit size of blocks of integers used to convert and encrypt message (usually specified in PUBLIC key file). Returns Encrypted message string. CrackingCodesWithPython.Chapter24.publicKeyCipher.encryptMessage(message: str, key: tuple, blockSize: int) → list Encrypt message Converts the message string into a list of block integers, and then encrypts each block integer. Parameters • message – String containing message to encrypt with PUBLIC key. • key – Tuple with PUBLIC key used for encryption. • blockSize – Bit size of block integers (usually specified in the PUBLIC key file). Returns List of block integers encrypted with PUBLIC key. Note: • Ensure to pass the PUBLIC key to encrypt. CrackingCodesWithPython.Chapter24.publicKeyCipher.getBlocksFromText(message: str, blockSize: int) → list Get blocks from text Converts a string message to a list of block integers. Parameters • message – String containing message to convert into blocks of integers. • blockSize – Size of each block of integers. Returns List with blocks of integers of the given size. Note: • If a character in the message is not in SYMBOLS, program exits with an error. 66 Chapter 1. Introduction python-tutorials Documentation, Release 1.1.1 CrackingCodesWithPython.Chapter24.publicKeyCipher.getTextFromBlocks(blockInts: list, messageLength: int, blockSize: int) → str Get text from blocks Converts a list of block integers to the original message string. Parameters • blockInts – List of block integers of specified size. • messageLength – Length of the original message. • blockSize – Bit size of each block of integers. Returns Original message string before block integer conversion. Note: • The original message length is needed to properly convert the last block integer. CrackingCodesWithPython.Chapter24.publicKeyCipher.main() CrackingCodesWithPython.Chapter24.publicKeyCipher.readFromFileAndDecrypt(messageFilename: str, keyFilename: str) → str Read from file and decrypt Using a key from a key file, read an encrypted message from a file and then decrypt it. Parameters • messageFilename – String containing name of file with encrypted message saved to it. • keyFilename – String containing absolute file path of PRIVATE key file. Returns Decrypted message string. Note: • Checks block size in key file and exits with error if too large. CrackingCodesWithPython.Chapter24.publicKeyCipher.readKeyFile(keyFilename: str) → tuple Read key from key file Reads the given public/private key file and returns the key. Parameters keyFilename – String containing absolute path to public/private key file. Returns The key as a (n,e) or (n,d) tuple value. Module contents Submodules 1.6. books 67 python-tutorials Documentation, Release 1.1.1 CrackingCodesWithPython.pyperclip module Pyperclip A cross-platform clipboard module for Python, with copy & paste functions for plain text. By Al Sweigart al@inventwithpython.com BSD License Usage: import pyperclip pyperclip.copy(‘The text to be copied to the clipboard.’) spam = pyperclip.paste() if not pyperclip.is_available(): print(“Copy functionality unavailable!”) On Windows, no additional modules are needed. On Mac, the pyobjc module is used, falling back to the pbcopy and pbpaste cli commands. (These commands should come with OS X.). On Linux, install xclip or xsel via package manager. For example, in Debian: sudo apt-get install xclip sudo apt-get install xsel Otherwise on Linux, you will need the gtk or PyQt5/PyQt4 modules installed. gtk and PyQt4 modules are not available for Python 3, and this module does not work with PyGObject yet. Note: There seem sto be a way to get gtk on Python 3, according to: https://askubuntu.com/ questions/697397/python3-is-not-supporting-gtk-module Cygwin is currently not supported. Security Note: This module runs programs with these names: • which • where • pbcopy • pbpaste • xclip • xsel • klipper • qdbus A malicious user could rename or add programs with these names, tricking Pyperclip into running them with whatever permissions the Python process has. CrackingCodesWithPython.pyperclip.copy(text) A stub function for copy(), which will load the real copy() function when called so that the real copy() function is used for later calls. This allows users to import pyperclip without having determine_clipboard() automatically run, which will automatically select a clipboard mechanism. This could be a problem if it selects, say, the memoryheavy PyQt4 module but the user was just going to immediately call set_clipboard() to use a different clipboard mechanism. The lazy loading this stub function implements gives the user a chance to call set_clipboard() to pick another clipboard mechanism. Or, if the user simply calls copy() or paste() without calling set_clipboard() first, will fall back on whatever clipboard mechanism that determine_clipboard() automatically chooses. CrackingCodesWithPython.pyperclip.paste() A stub function for paste(), which will load the real paste() function when called so that the real paste() function is used for later calls. 68 Chapter 1. Introduction python-tutorials Documentation, Release 1.1.1 This allows users to import pyperclip without having determine_clipboard() automatically run, which will automatically select a clipboard mechanism. This could be a problem if it selects, say, the memoryheavy PyQt4 module but the user was just going to immediately call set_clipboard() to use a different clipboard mechanism. The lazy loading this stub function implements gives the user a chance to call set_clipboard() to pick another clipboard mechanism. Or, if the user simply calls copy() or paste() without calling set_clipboard() first, will fall back on whatever clipboard mechanism that determine_clipboard() automatically chooses. CrackingCodesWithPython.pyperclip.set_clipboard(clipboard) Explicitly sets the clipboard mechanism. The “clipboard mechanism” is how the copy() and paste() functions interact with the operating system to implement the copy/paste feature. The clipboard parameter must be one of: • pbcopy • pbobjc (default on Mac OS X) • gtk • qt • xclip • xsel • klipper • windows (default on Windows) • no (this is what is set when no clipboard mechanism can be found) CrackingCodesWithPython.pyperclip.determine_clipboard() Determine the OS/platform and set the copy() and paste() functions accordingly. Module contents 1.7 Index 1.7. Index 69 python-tutorials Documentation, Release 1.1.1 70 Chapter 1. Introduction PYTHON MODULE INDEX c 38 CrackingCodesWithPython.Chapter06.PracticeQuestion, CrackingCodesWithPython, 69 38 CrackingCodesWithPython.Chapter01, 34 CrackingCodesWithPython.Chapter07, 41 CrackingCodesWithPython.Chapter01.caesarCipher, CrackingCodesWithPython.Chapter07.addNumbers, 33 40 CrackingCodesWithPython.Chapter01.caesarHacker, CrackingCodesWithPython.Chapter07.helloFunction, 34 40 CrackingCodesWithPython.Chapter01.constants, CrackingCodesWithPython.Chapter07.PracticeQuestions, 34 CrackingCodesWithPython.Chapter01.PracticeQuestions, 40 CrackingCodesWithPython.Chapter07.PracticeQuestions.Questi 33 39 CrackingCodesWithPython.Chapter02, 35 CrackingCodesWithPython.Chapter07.PracticeQuestions.Questi CrackingCodesWithPython.Chapter02.PracticeQuestions, 39 34 CrackingCodesWithPython.Chapter07.PracticeQuestions.Questi CrackingCodesWithPython.Chapter03, 35 39 CrackingCodesWithPython.Chapter03.hello, 35 CrackingCodesWithPython.Chapter07.PracticeQuestions.Questi CrackingCodesWithPython.Chapter03.PracticeQuestions, 39 35 CrackingCodesWithPython.Chapter07.PracticeQuestions.Questi CrackingCodesWithPython.Chapter04, 36 CrackingCodesWithPython.Chapter04.PracticeQuestions, 39 CrackingCodesWithPython.Chapter07.transpositionEncrypt, 35 40 CrackingCodesWithPython.Chapter04.reverseCipher, CrackingCodesWithPython.Chapter08, 43 36 CrackingCodesWithPython.Chapter08.PracticeQuestions, CrackingCodesWithPython.Chapter05, 38 42 CrackingCodesWithPython.Chapter05.caesarCipher, CrackingCodesWithPython.Chapter08.PracticeQuestions.Questi 37 41 CrackingCodesWithPython.Chapter05.checkPw, CrackingCodesWithPython.Chapter08.PracticeQuestions.Questi 38 CrackingCodesWithPython.Chapter05.PracticeQuestions, 41 CrackingCodesWithPython.Chapter08.PracticeQuestions.Questi 37 42 CrackingCodesWithPython.Chapter05.PracticeQuestions.Question1, CrackingCodesWithPython.Chapter08.PracticeQuestions.Questi 36 42 CrackingCodesWithPython.Chapter05.PracticeQuestions.Question2, CrackingCodesWithPython.Chapter08.transpositionDecrypt, 36 42 CrackingCodesWithPython.Chapter05.PracticeQuestions.Question3, CrackingCodesWithPython.Chapter09, 44 36 CrackingCodesWithPython.Chapter09.passingReference, CrackingCodesWithPython.Chapter05.PracticeQuestions.Question4, 43 37 CrackingCodesWithPython.Chapter09.PracticeQuestions, CrackingCodesWithPython.Chapter05.PracticeQuestions.watermelon, 43 37 CrackingCodesWithPython.Chapter09.transpositionTest, CrackingCodesWithPython.Chapter06, 38 43 CrackingCodesWithPython.Chapter06.caesarHacker, 71 python-tutorials Documentation, Release 1.1.1 CrackingCodesWithPython.Chapter10, 44 CrackingCodesWithPython.Chapter19.freqAnalysis, CrackingCodesWithPython.Chapter10.PracticeQuestions, 57 44 CrackingCodesWithPython.Chapter19.PracticeQuestions, CrackingCodesWithPython.Chapter10.transpositionFileCipher, 57 44 CrackingCodesWithPython.Chapter20, 62 CrackingCodesWithPython.Chapter11, 46 CrackingCodesWithPython.Chapter20.PracticeQuestions, CrackingCodesWithPython.Chapter11.detectEnglish, 58 44 CrackingCodesWithPython.Chapter20.vigenereDictionaryHacker CrackingCodesWithPython.Chapter11.PracticeQuestions, 59 44 CrackingCodesWithPython.Chapter20.vigenereHacker, CrackingCodesWithPython.Chapter12, 47 59 CrackingCodesWithPython.Chapter12.PracticeQuestions, CrackingCodesWithPython.Chapter21, 62 46 CrackingCodesWithPython.Chapter21.PracticeQuestions, CrackingCodesWithPython.Chapter12.transpositionHacker,62 46 CrackingCodesWithPython.Chapter22, 63 CrackingCodesWithPython.Chapter13, 47 CrackingCodesWithPython.Chapter22.PracticeQuestions, CrackingCodesWithPython.Chapter13.cryptomath, 62 47 CrackingCodesWithPython.Chapter22.primeNum, CrackingCodesWithPython.Chapter13.PracticeQuestions, 62 47 CrackingCodesWithPython.Chapter23, 64 CrackingCodesWithPython.Chapter14, 49 CrackingCodesWithPython.Chapter23.makePublicPrivateKeys, CrackingCodesWithPython.Chapter14.affineCipher, 64 48 CrackingCodesWithPython.Chapter23.PracticeQuestions, CrackingCodesWithPython.Chapter14.affineKeyTest, 64 49 CrackingCodesWithPython.Chapter24, 67 CrackingCodesWithPython.Chapter14.PracticeQuestions, CrackingCodesWithPython.Chapter24.publicKeyCipher, 48 65 CrackingCodesWithPython.Chapter15, 50 CrackingCodesWithPython.pyperclip, 68 CrackingCodesWithPython.Chapter15.affineHacker, 50 CrackingCodesWithPython.Chapter15.PracticeQuestions, 50 CrackingCodesWithPython.Chapter16, 52 CrackingCodesWithPython.Chapter16.PracticeQuestions, 50 CrackingCodesWithPython.Chapter16.simpleSubCipher, 50 CrackingCodesWithPython.Chapter17, 55 CrackingCodesWithPython.Chapter17.makeWordPatterns, 52 CrackingCodesWithPython.Chapter17.PracticeQuestions, 52 CrackingCodesWithPython.Chapter17.simpleSubHacker, 53 CrackingCodesWithPython.Chapter17.wordPatterns, 55 CrackingCodesWithPython.Chapter18, 57 CrackingCodesWithPython.Chapter18.PracticeQuestions, 55 CrackingCodesWithPython.Chapter18.stringTest, 55 CrackingCodesWithPython.Chapter18.vigenereCipher, 56 CrackingCodesWithPython.Chapter19, 58 72 Python Module Index
Source Exif Data:
File Type : PDF File Type Extension : pdf MIME Type : application/pdf PDF Version : 1.5 Linearized : No Page Mode : UseOutlines Page Count : 76 Creator : LaTeX with hyperref package Title : python-tutorials Documentation Author : Jose A. Lerma III Producer : XeTeX 0.99998 Create Date : 2018:12:14 04:45:46-06:00EXIF Metadata provided by EXIF.tools