├── .bashrc ├── .gitignore ├── .vimrc ├── AllTinyCCShortLinks.txt ├── AppleScript └── ToggleDarkMode.scpt ├── Bash ├── .gitignore ├── ScreenshotRename.sh └── ShortenURL.sh ├── GoogleDuplicatePhotoRemover.java ├── Java ├── GoogleDuplicatePhotoRemover.java ├── MergeDirectories.java ├── README.md └── ResetImageTimes.java ├── Python ├── CredentialManager.py ├── CredentialManagerExample.py ├── CredentialManager_Legacy.py ├── Dictionary.py ├── EmailAttachment.py ├── EmailMe.py ├── NoteTaker │ ├── Dubliners Notes.docx │ ├── Dubliners Notes.md │ ├── Dubliners Notes.pdf │ ├── Dubliners.pdf │ ├── NoteTaker.py │ ├── README.md │ ├── docx │ │ ├── __init__.py │ │ ├── api.py │ │ ├── blkcntnr.py │ │ ├── compat.py │ │ ├── dml │ │ │ ├── __init__.py │ │ │ └── color.py │ │ ├── document.py │ │ ├── enum │ │ │ ├── __init__.py │ │ │ ├── base.py │ │ │ ├── dml.py │ │ │ ├── section.py │ │ │ ├── shape.py │ │ │ ├── style.py │ │ │ ├── table.py │ │ │ └── text.py │ │ ├── exceptions.py │ │ ├── image │ │ │ ├── __init__.py │ │ │ ├── bmp.py │ │ │ ├── constants.py │ │ │ ├── exceptions.py │ │ │ ├── gif.py │ │ │ ├── helpers.py │ │ │ ├── image.py │ │ │ ├── jpeg.py │ │ │ ├── png.py │ │ │ └── tiff.py │ │ ├── opc │ │ │ ├── __init__.py │ │ │ ├── compat.py │ │ │ ├── constants.py │ │ │ ├── coreprops.py │ │ │ ├── exceptions.py │ │ │ ├── oxml.py │ │ │ ├── package.py │ │ │ ├── packuri.py │ │ │ ├── part.py │ │ │ ├── parts │ │ │ │ ├── __init__.py │ │ │ │ └── coreprops.py │ │ │ ├── phys_pkg.py │ │ │ ├── pkgreader.py │ │ │ ├── pkgwriter.py │ │ │ ├── rel.py │ │ │ ├── shared.py │ │ │ └── spec.py │ │ ├── oxml │ │ │ ├── __init__.py │ │ │ ├── coreprops.py │ │ │ ├── document.py │ │ │ ├── exceptions.py │ │ │ ├── ns.py │ │ │ ├── numbering.py │ │ │ ├── section.py │ │ │ ├── shape.py │ │ │ ├── shared.py │ │ │ ├── simpletypes.py │ │ │ ├── styles.py │ │ │ ├── table.py │ │ │ ├── text │ │ │ │ ├── __init__.py │ │ │ │ ├── font.py │ │ │ │ ├── paragraph.py │ │ │ │ ├── parfmt.py │ │ │ │ └── run.py │ │ │ └── xmlchemy.py │ │ ├── package.py │ │ ├── parts │ │ │ ├── __init__.py │ │ │ ├── document.py │ │ │ ├── image.py │ │ │ ├── numbering.py │ │ │ └── styles.py │ │ ├── section.py │ │ ├── shape.py │ │ ├── shared.py │ │ ├── styles │ │ │ ├── __init__.py │ │ │ ├── latent.py │ │ │ ├── style.py │ │ │ └── styles.py │ │ ├── table.py │ │ ├── templates │ │ │ ├── default-src.docx │ │ │ ├── default-styles.xml │ │ │ └── default.docx │ │ └── text │ │ │ ├── __init__.py │ │ │ ├── font.py │ │ │ ├── paragraph.py │ │ │ ├── parfmt.py │ │ │ └── run.py │ └── pyPdf │ │ ├── __init__.py │ │ ├── filters.py │ │ ├── generic.py │ │ ├── pdf.py │ │ ├── utils.py │ │ └── xmp.py ├── PasswordGenerator.py ├── README.md ├── TextAttachment.py ├── TextLink.py ├── TextPeople.py ├── TextPhone.py ├── TextPhoneP.py ├── User-Agent │ ├── 100useragents.txt │ ├── 50useragents.txt │ ├── useragents.txt │ └── useragenttuner.py └── iOSAppIconResizer.py ├── README.md └── Solarized Dark.terminal /.bashrc: -------------------------------------------------------------------------------- 1 | ################################## 2 | # Written by Ryan D'souza 3 | # A collection of my aliases 4 | ################################## 5 | 6 | export PATH=/path/to/dir:$PATH 7 | 8 | #Copy current directory to clipboard 9 | alias cpwd='pwd | xclip -selection clipboard' 10 | 11 | #Quickly find file 12 | alias ff='find . -type f -name' 13 | 14 | #Quickly find directory 15 | alias fd='find . -type d -name' 16 | 17 | #get internet speed 18 | alias speedtest='wget -O /dev/null http://speedtest.wdc01.softlayer.com/downloads/test500.zip' 19 | 20 | #Short form for where most of my code is stored 21 | dboxprogram="~/Dropbox/All\ Good\ Programming\ Books" 22 | 23 | #DOTFILES SHORTCUTS 24 | dotfiles="$dboxprogram/dotfiles" 25 | 26 | #Renames all pngs in a directory with a file name that includes 'Screenshot' with the format Screenshot_X.png 27 | alias renamescreenshot="$dotfiles/Bash/./ScreenshotRename.sh" 28 | 29 | #Counts number of files in directories and subdirectories 30 | alias countall="find */ -type f | wc -l" 31 | 32 | #Runs a python script that converts an image to all the necessary sizes for an iOS app 33 | alias iOSImageConverter="python $dotfiles/Python/iOSAppIconResizer.py" 34 | 35 | #Runs a python script to email a file to myself as an attachment 36 | alias EmailAttachment="python $dotfiles/Python/EmailAttachment.py" 37 | alias EmailAttch="EmailAttachment" 38 | 39 | #Runs a python script to securely save my credentials 40 | alias CredentialManager="python $dotfiles/Python/CredentialManager.py" 41 | 42 | #Runs a python script to send a text to my phone 43 | alias TextPhone="python $dotfiles/Python/Textphone.py" 44 | 45 | #Runs a python script that sends a link to my phone 46 | alias TextLink="python $dotfiles/Python/TextLink.py" 47 | 48 | #Runs a python script to text people 49 | alias TextPeople="python $dotfiles/Python/TextPeople.py" 50 | 51 | #Runs a python script to email stuff to myself 52 | alias EmailLink="python $dotfiles/Python/EmailLink.py" 53 | alias EmailMe="python $dotfiles/Python/EmailMe.py" 54 | 55 | #Runs a bash script to shorten a link, print the shortened URL, and copy it to clipboard 56 | alias ShortenLink="$dotfiles/Bash/./ShortenURL.sh" 57 | 58 | #Prints the definition of a word and its usage in a sentence 59 | alias define="python $dotfiles/Python/Dictionary.py" 60 | 61 | #Prints current external IP Address 62 | alias myIP="curl http://api.ipify.org; echo" #Other option: 'curl ifconfig.me' 63 | alias myip="myIP" 64 | 65 | #Prints local IP Address 66 | alias myIPL="ipconfig getifaddr en1" 67 | alias myipl="myIPL" 68 | 69 | #Go places 70 | alias toprogramming="cd $dboxprogram" 71 | alias toalgos="toprogramming; cd Algorithms\ and\ Data\ Structures" 72 | alias todotfiles="toprogramming; cd dotfiles" 73 | alias toios="cd ~/iOS\ Development" 74 | alias topython="toprogramming; cd Python" 75 | alias todownloads="cd; cd Downloads" 76 | alias tobmf="toprogramming; cd Bring\ Me\ Food" 77 | alias tocharles="toprogramming; cd Charles\ Proxying" 78 | 79 | #Downloads any website's content 80 | downloadsite() { 81 | wget --random-wait -r -p -e robots=off -U mozilla $1 82 | } 83 | 84 | #Normal ls but displays '/' for directories 85 | alias ls="ls -CF" 86 | 87 | #Shortens git commiting everything 88 | commitall() { 89 | git add --all 90 | 91 | #Gets all the input into one string 92 | message="$*" 93 | 94 | git commit -m "$message" 95 | } 96 | 97 | #Prints the contents of that directory. No formatting 98 | peekn() { 99 | 100 | #If there is no input directory, print the current one 101 | if [ -z "$1"] 102 | then 103 | ls 104 | 105 | #But if there is an input 106 | else 107 | #Get into it 108 | cd $1 109 | 110 | #Print in nice columns format 111 | ls 112 | 113 | #Go back 114 | cd .. 115 | fi 116 | } 117 | 118 | #Prints the contents of that directory in a nice format 119 | peek() { 120 | 121 | #If there is no input directory, print the current one 122 | if [ -z "$1"] 123 | then 124 | ls | column -c 200 125 | 126 | #But if there is an input 127 | else 128 | #Get into it 129 | cd $1 130 | 131 | #Print in nice columns format 132 | ls | column -c 200 133 | 134 | #Go back 135 | cd .. 136 | fi 137 | } 138 | 139 | #Make a directory and navigate into it 140 | mcd() { 141 | mkdir -p $1 142 | cd $1 143 | } 144 | 145 | #Copy file to clipboard 146 | copyfile() { 147 | cat $1 | xclip -selection clipboard 148 | } 149 | 150 | #Last 10 modified files 151 | last() { 152 | ls -lt -a $1 | head 153 | } 154 | 155 | #Convert all .jpg files to .png 156 | pngtojpg() { 157 | for i in *.jpg ; do 158 | convert "$i" "${i%.*}.png" 159 | done 160 | } 161 | 162 | #Convert all .png files to .jpg 163 | jpgtopng() { 164 | for i in *.png ; do 165 | convert "$i" "${i%.*}.png" 166 | done 167 | } 168 | 169 | #Whether to use .bashrc or other files 170 | if [ -f $HOME/.bash_aliases ] 171 | then 172 | . $HOME/.bash_aliases 173 | fi 174 | 175 | #Causes the changes to .bashrc to come true 176 | alias bashme="cp ~/.bashrc ~/.bash_profile && source ~/.bashrc && echo Successfully bashed" 177 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | #Extensions I frequently add to .gitignore 2 | 3 | #Python 4 | config.py 5 | *.pyc 6 | 7 | #Vim 8 | *.swp 9 | 10 | #Java 11 | *.class 12 | 13 | #iOS Development 14 | *.plist 15 | /AppDelegate.m 16 | AppDelegate.m 17 | misc/ 18 | build/ 19 | *.pbxuser 20 | !default.pbxuser 21 | *.mode1v3 22 | !default.mode1v3 23 | *.mode2v3 24 | !default.mode2v3 25 | *.perspectivev3 26 | !default.perspectivev3 27 | xcuserdata 28 | *.xccheckout 29 | *.moved-aside 30 | DerivedData 31 | *.hmap 32 | *.ipa 33 | *.xcuserstate 34 | -------------------------------------------------------------------------------- /.vimrc: -------------------------------------------------------------------------------- 1 | " Keyboard controls for switching between vim tabs 2 | nnoremap 3 | nnoremap 4 | nnoremap 5 | nnoremap 6 | 7 | " Suffixes to put to the end of the list when completing file names 8 | " set suffixes=.bak,~,.o,.h,.info,.swp,.class 9 | 10 | " Or, completely ignore the following file extensions 11 | set wildignore=*.class,*.rbc 12 | 13 | :imap jk 14 | 15 | set formatoptions+=r 16 | 17 | " Sets how many lines of history VIM has to remember 18 | set history=7000 19 | 20 | " Set 7 lines to the cursor - when moving vertically using j/k 21 | set so=7 22 | 23 | " Set line numbers 24 | set number 25 | 26 | "Always show current position 27 | set ruler 28 | 29 | " Height of the command bar 30 | set cmdheight=2 31 | 32 | " Configure backspace so it acts as it should act 33 | set backspace=eol,start,indent 34 | set whichwrap+=<,>,h,l 35 | 36 | " Ignore case when searching 37 | set ignorecase 38 | 39 | " When searching try to be smart about cases 40 | set smartcase 41 | 42 | " Highlight search results 43 | set hlsearch 44 | 45 | " Makes search act like search in modern browsers 46 | set incsearch 47 | 48 | " For regular expressions turn magic on 49 | set magic 50 | 51 | " Show matching brackets when text indicator is over them 52 | set showmatch 53 | " How many tenths of a second to blink when matching brackets 54 | set mat=2 55 | 56 | 57 | """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" 58 | " => Colors and Fonts 59 | """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" 60 | " Enable syntax highlighting 61 | syntax enable 62 | 63 | colorscheme desert 64 | set background=dark 65 | 66 | " Set extra options when running in GUI mode 67 | if has("gui_running") 68 | set guioptions-=T 69 | set guioptions+=e 70 | set t_Co=256 71 | set guitablabel=%M\ %t 72 | endif 73 | 74 | " Set utf8 as standard encoding and en_US as the standard language 75 | set encoding=utf8 76 | 77 | " Use Unix as the standard file type 78 | set ffs=unix,dos,mac 79 | 80 | 81 | """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" 82 | " => Text, tab and indent related 83 | """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" 84 | " Use spaces instead of tabs 85 | set expandtab 86 | 87 | " Be smart when using tabs ;) 88 | set smarttab 89 | 90 | " 1 tab == 4 spaces 91 | set shiftwidth=4 92 | set tabstop=4 93 | 94 | " Linebreak on 500 characters 95 | set lbr 96 | set tw=500 97 | 98 | set ai "Auto indent 99 | set si "Smart indent 100 | set wrap "Wrap lines 101 | -------------------------------------------------------------------------------- /AllTinyCCShortLinks.txt: -------------------------------------------------------------------------------- 1 | Resume: tiny.cc/dsouzarcResume 2 | All CS Projects: tiny.cc/dsouzarcCSProjects 3 | Website: tiny.cc/dsouzarc 4 | 5 | .vimrc: tiny.cc/dsouzarcVIMRC 6 | .gitignore: tiny.cc/dsouzarcGITIGNORE 7 | .bashrc: tiny.cc/dsouzarcBASHRC 8 | 9 | Solarized Dark: tiny.cc/solarizedDark 10 | 11 | Credential Manager: tiny.cc/credentialManager 12 | 13 | TextPhone: tiny.cc/textPhone 14 | TextPhone Plain: tiny.cc/textPhoneP 15 | TextLink: tiny.cc/textLink 16 | TextPeople: tiny.cc/textPeople 17 | 18 | This File: tiny.cc/dsouzarcTINYCC 19 | -------------------------------------------------------------------------------- /AppleScript/ToggleDarkMode.scpt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsouzarc/dotfiles/f771532b0f512efcefa3dc0ede31deceaf0e9acc/AppleScript/ToggleDarkMode.scpt -------------------------------------------------------------------------------- /Bash/.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *.pyc 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | env/ 12 | build/ 13 | develop-eggs/ 14 | dist/ 15 | downloads/ 16 | eggs/ 17 | .eggs/ 18 | lib/ 19 | lib64/ 20 | parts/ 21 | sdist/ 22 | var/ 23 | *.egg-info/ 24 | .installed.cfg 25 | *.egg 26 | 27 | # PyInstaller 28 | # Usually these files are written by a python script from a template 29 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 30 | *.manifest 31 | *.spec 32 | 33 | # Installer logs 34 | pip-log.txt 35 | pip-delete-this-directory.txt 36 | 37 | # Unit test / coverage reports 38 | htmlcov/ 39 | .tox/ 40 | .coverage 41 | .coverage.* 42 | .cache 43 | nosetests.xml 44 | coverage.xml 45 | *,cover 46 | 47 | # Translations 48 | *.mo 49 | *.pot 50 | 51 | #Vim stuff 52 | *.swp 53 | 54 | # Django stuff: 55 | *.log 56 | 57 | # Sphinx documentation 58 | docs/_build/ 59 | 60 | # PyBuilder 61 | target/ 62 | -------------------------------------------------------------------------------- /Bash/ScreenshotRename.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ################################################################# 4 | #Written by Ryan D'souza 5 | #Goes through each file in a directory 6 | #If the name contains either 'Screenshot' or 'Screen shot' 7 | #It renames it to Screenshot_X.yyy where 8 | #X increments each time and yyy is the file's extension 9 | ################################################################# 10 | 11 | #Start off with Screenshot_1 12 | i=1; 13 | 14 | for f in * 15 | do 16 | 17 | #Screenshot classification 18 | if [[ $f == *"Screenshot"* ]] || [[ $f == *"Screen shot"* ]] 19 | then 20 | 21 | #Dealing with PNGs 22 | if [[ $f == *".png"* ]] 23 | then 24 | newFileName="Screenshot_$i.png"; 25 | mv "$f" "$newFileName" 26 | echo Renamed $f to $newFileName 27 | i=$((i+1)); 28 | 29 | #Dealing with JPGs 30 | elif [[ $f == *".jpg"* ]] 31 | then 32 | newFileName="Screenshot_$i.jpg"; 33 | mv "$f" "$newFileName" 34 | echo Renamed $f to $newFileName 35 | i=$((i+1)) 36 | fi 37 | fi 38 | done 39 | 40 | echo Renamed all files 41 | -------------------------------------------------------------------------------- /Bash/ShortenURL.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | #Sends a request to the po.st API with the long url. po.st returns JSON with result information 4 | JSONResult=$(python2 -c "import urllib; print urllib.urlopen(\"http://po.st/api/shorten?longUrl=$1&apiKey=3E5C05F5-DDED-4485-A193-F486E947F547\",'r').read()") 5 | 6 | #Parses result to see if it was successful 7 | Success=$(node -pe 'JSON.parse(process.argv[1]).status_txt' "$JSONResult") 8 | 9 | #If it successfully shortened the link 10 | if [ "$Success" == "OK" ]; then 11 | 12 | #The shortened link 13 | ShortenedURL=$(node -pe 'JSON.parse(process.argv[1]).short_url' "$JSONResult") 14 | 15 | #Print it 16 | echo $ShortenedURL 17 | 18 | #Copy to clipboard 19 | echo $ShortenedURL | pbcopy 20 | 21 | #If there was an error, print it 22 | else 23 | echo $JSONResult 24 | fi 25 | 26 | -------------------------------------------------------------------------------- /GoogleDuplicatePhotoRemover.java: -------------------------------------------------------------------------------- 1 | import java.util.HashSet; 2 | import java.io.File; 3 | /** 4 | * Written by Ryan D'souza 5 | * When downloading a photo library from Google Photos, Google includes two copies of each photo: the raw picture and an edited - enhanced - photo. 6 | * "rsync -av *'/' All\ Photos" in the terminal 7 | gets all the photos from the folders (day1/photo1_1, day1/photo1_2, day2/photo2_1, day2/photo2_2) and 8 | moves them to a single directory (allPhotos/photo1_1, allPhotos/photo1_2, allPhotos/photos2_1, allPhotos/photos2_2) 9 | * The raw and edited-photo versions take use significant memory and causes duplicates 10 | when just viewing the files ie.- photo1_1.jpg photo1_1-edited.jpg, photo2_1.jpg photo2_2-edited.jpg 11 | * This program looks through all the photos in a directory and, if there is an edited version, deletes the original. 12 | * If there is no edited version, the program does nothing*/ 13 | 14 | public class GoogleDuplicatePhotoRemover { 15 | 16 | public static void main(String[] ryan) throws Exception { 17 | 18 | //To hold all the file names 19 | final HashSet fileNames = new HashSet(); 20 | 21 | //All the files in the directory this program is run from 22 | final File folderWithAllFiles = new File(System.getProperty("user.dir")); 23 | final File[] allFiles = folderWithAllFiles.listFiles(); 24 | 25 | //Go through all the files 26 | for(File file : allFiles) { 27 | if(file.isFile()) { 28 | 29 | //Just the file name without the extension 30 | final String newFileName = file.getName.replace(".jpg", "").replace(".png", "").replace(".jpeg", "") 31 | .replace(".3gp", "").replace(".gif", "").replace(".mov", "").replace(".mp4", ""); 32 | 33 | //Add it to our set of names 34 | fileNames.add(newFileName); 35 | } 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Java/GoogleDuplicatePhotoRemover.java: -------------------------------------------------------------------------------- 1 | import java.util.HashMap; 2 | import java.io.File; 3 | /** 4 | * Written by Ryan D'souza 5 | * When downloading a photo library from Google Photos, Google includes two copies of each photo: the raw picture and an edited - enhanced - photo. 6 | * "rsync -av *'/' All\ Photos" in the terminal 7 | gets all the photos from the folders (day1/photo1_1, day1/photo1_2, day2/photo2_1, day2/photo2_2) and 8 | moves them to a single directory (allPhotos/photo1_1, allPhotos/photo1_2, allPhotos/photos2_1, allPhotos/photos2_2) 9 | * The raw and edited-photo versions take use significant memory and causes duplicates 10 | when just viewing the files ie.- photo1_1.jpg photo1_1-edited.jpg, photo2_1.jpg photo2_2-edited.jpg 11 | * This program looks through all the photos in a directory and, if there is an edited version, deletes the original. 12 | * If there is no edited version, the program does nothing*/ 13 | 14 | public class GoogleDuplicatePhotoRemover { 15 | 16 | public static void main(String[] ryan) throws Exception { 17 | 18 | //For fun statistics 19 | int numPhotosDeleted = 0; 20 | long bytesDeleted = 0; 21 | 22 | //To hold all the file names 23 | final HashMap fileNames = new HashMap(); 24 | 25 | //All the files in the directory this program is run from 26 | final File folderWithAllFiles = new File(System.getProperty("user.dir")); 27 | final File[] allFiles = folderWithAllFiles.listFiles(); 28 | 29 | //Go through all the files 30 | for(File file : allFiles) { 31 | if(file.isFile()) { 32 | 33 | //Just the file name without the extension 34 | final String newFileName = file.getName().replace(".jpg", "").replace(".png", "").replace(".jpeg", "") 35 | .replace(".3gp", "").replace(".gif", "").replace(".mov", "").replace(".mp4", ""); 36 | 37 | //Add it to our set of names 38 | fileNames.put(newFileName, file.getName()); 39 | } 40 | } 41 | 42 | //Go through all of our names 43 | for(String file : fileNames.keySet()) { 44 | 45 | //If there is an edited version in the directory 46 | if(fileNames.containsKey(file + "-edited")) { 47 | 48 | //Get the original 49 | final File toDelete = new File(fileNames.get(file)); 50 | 51 | //Update the stats 52 | numPhotosDeleted++; 53 | bytesDeleted += toDelete.length(); 54 | 55 | //And delete the original, keeping the edited version 56 | if(toDelete.delete()) { 57 | System.out.println("Deleted: " + file); 58 | } 59 | else { 60 | System.out.println("Problem deleting: " + file); 61 | } 62 | } 63 | } 64 | 65 | System.out.println("NUM DELETED FILES: " + numPhotosDeleted); 66 | 67 | final double MBDeleted = bytesDeleted / Math.pow(1024, 2); 68 | 69 | System.out.println("MBDELETED: " + MBDeleted + "\tBYTES DELETED: " + bytesDeleted); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /Java/MergeDirectories.java: -------------------------------------------------------------------------------- 1 | import java.io.File; 2 | import java.util.HashMap; 3 | import java.util.HashSet; 4 | 5 | public class MergeDirectories { 6 | 7 | public static void main(String[] ryan) throws Exception { 8 | 9 | final File folderWithAllFiles = new File(System.getProperty("user.dir")); 10 | final File[] allFiles = folderWithAllFiles.listFiles(); 11 | 12 | final HashSet directoryNames = new HashSet(); 13 | //Store all the directories in the hashset 14 | for(File file : allFiles) { 15 | if(file.isDirectory()) { 16 | directoryNames.add(file.getName()); 17 | } 18 | } 19 | 20 | int counter = 0; 21 | 22 | //Go through our directories 23 | for(String directoryName : directoryNames) { 24 | 25 | if(counter < 2) { 26 | if(directoryName.length() > 10 && directoryNames.contains(directoryName.substring(0, 10))) { 27 | System.out.println(directoryName); 28 | moveFiles(new File(directoryName), new File(directoryName.substring(0, 10))); 29 | } 30 | } 31 | } 32 | } 33 | 34 | public static void moveFiles(final File directoryToMoveFrom, final File directoryToMoveTo) { 35 | 36 | //All the files names in the second directory 37 | final HashSet alreadyFiles = new HashSet(); 38 | final File[] allFiles = directoryToMoveTo.listFiles(); 39 | for(File file : allFiles) { 40 | alreadyFiles.add(file.getName()); 41 | } 42 | 43 | //Go through all the files we need to move 44 | final File[] toMove = directoryToMoveFrom.listFiles(); 45 | for(File move : toMove) { 46 | 47 | final String newFileName; 48 | if(alreadyFiles.contains(move.getName())) { 49 | //Append a random string 50 | newFileName = System.currentTimeMillis() + move.getName(); 51 | } 52 | else { 53 | newFileName = move.getName(); 54 | } 55 | 56 | //Move the file 57 | if(move.renameTo(new File(directoryToMoveTo.getAbsolutePath() + "/" + newFileName))) { 58 | //System.out.println("Successful relocation: " + newFileName); 59 | } 60 | else { 61 | System.out.println("PROBLEM"); 62 | } 63 | } 64 | 65 | if(directoryToMoveFrom.listFiles().length == 0) { 66 | final String name = directoryToMoveFrom.getName(); 67 | if(directoryToMoveFrom.delete()) { 68 | System.out.println("SUCCESSFULLY EMPTIED AND DELETED: " + name); 69 | } 70 | else { 71 | System.out.println("PROBLEM DELETING: " + name); 72 | } 73 | } 74 | else { 75 | System.out.println("FILES LEFT"); 76 | } 77 | } 78 | 79 | } 80 | 81 | -------------------------------------------------------------------------------- /Java/README.md: -------------------------------------------------------------------------------- 1 | # The Story 2 | 3 | ### 2014 4 | Throughout all of 2014, I had the Samsung Galaxy S4. I primarily used stock-apps with the exception of texting (QKSMS) and camera (switched to using Google Camera in May 2014) 5 | 6 | I would backup my photos to Google+ Photos, where they would remain hidden. 7 | 8 | ### What went wrong - Multifold 9 | 10 | + Many, many duplicates 11 | - If I took a photo on Snapchat and downloaded the snap, the photo would show up in two folders: 'All Photos' and 'Snapchat' 12 | - I had the enhance quality enabled on Google+ Photos so for every photo I backed up, Google+ would store two versions: a slightly compressed version of the original photo I took on my device (Version B) and an edited/enhanced version (Version C). I did not know about the 'Version C' photo until I downloaded all of my Google+ Photos to my computer and looked through them 13 | 14 | + SD Card problems 15 | - On Android version 4.4 (Kitkat), Google had taken steps to stop rogue apps from viewing other apps' data stored on the SD card by restricting what data could be stored on the card and which apps had access to it 16 | - For some unknown reason - probably because of TouchWiz + Kitkat - I was unable to store my photos on my SD Card. I was also unable to store my downloaded songs/playlists from Spotify (Spotify Premium user) to my SD card, most likely because of Spotify's restrictions 17 | - I decided it was best to root my 16GB Galaxy S4 in order to use an app that would trick apps into thinking my SD card was internal memory and would allow me to store a ton of apps' data on my SD card 18 | + My phone setup became like this: Spotify music on SD Card, old photos on SD card, newest photos on phone's internal memory before being moved to SD Card when space ran out. Also, all photos were backed up to Google+. 19 | - Worked well until I was halfway through my trip to Vienna, Salzburg, and Prague. For some weird reason, something happened to the write permissions that did not allow me to move my photos from my internal memory to SD Card. **I lost over 450 photos of the most historic and beautiful places in Vienna and Salzburg because Samsung 'successfully moved' photos to the SD card when it really did not**. 20 | - I thought it was a glitch and continued on with my trip, but the problems just got worse and worse. 21 | - In July, my write problems were severe - I could not even delete files from the SD card - and I broke the card in half and sent it to SanDisk to get a replacement 64GB SD card (under warranty) 22 | - I kept a few photos on that SD card, but nothing from that year's earlier trips to **London, Paris, Salzburg, Vienna, and Prague**. 23 | 24 | ### Fast-forward a few months 25 | 26 | + I converted to iOS/iPhone 6 and absolutely loved it. When I made the switch, I was able to successfully transfer all the photos on my Android phone (both internal memory and SD card) to my new iPhone 27 | - Unfortunately, I still had a lot of duplicate photos (ie. screenshots and snapchat downloads that were saved twice) 28 | - Some of the photos and dates were off 29 | 30 | + I eventually became frustrated with the duplicate, out-of-order photos and decided I would somehow transfer all the photos backed up to Google+ to my iPhone 31 | 32 | ### The problem 33 | 34 | + When I downloaded my photos from Google+ as a 10.5GB .tgz file, I discovered that: 35 | - Not only were there the duplicate photos, but there were also other edited/enhanced copies Google+ stored but did not display on either the Google+ Photos website or Photos section of the Google+ app. 36 | - The dates were completely wrong on a significant number of the photos, which meant that when I transferred them to my iPhone, they would show up incorrect spots on the Photos app 37 | - File names were really different and not uniform 38 | + Some photos saved from my iTouch (back in 2013) were saved in the typical iOS-taken-photo format: IMG_NUMBER.jpg 39 | + Photos from my Galaxy S4 were saved as DATE_TIME_NUMBER.jpg 40 | + Miscellaneous screenshots & downloaded photos were saved completely differently 41 | 42 | ### The silver lining 43 | 44 | + Even though the photo date-added and date-edited timestamp was wrong, it was still in a folder named with the photo's correct date taken stamp (YEAR_DAY_MONTH) 45 | - One slight problem was that multiple back-ups on the same day caused multiple folders (ie. 'DATE', 'DATE #2', 'DATE #3') 46 | + The edited/enhanced photos Google+ added were uniform ie. ORIGINALFILENAME-EDITED.jpg 47 | 48 | ### What I did 49 | 50 | + Decided to solve this problem programmatically 51 | 52 | 1. Delete duplicated photos 53 | + [GoogleDuplicatePhotoRemover.java](https://github.com/dsouzarc/dotfiles/blob/master/Java/GoogleDuplicatePhotoRemover.java) recursively looks through all the photos in folders of a directory and deletes the original photo if it finds an enhanced version of that photo 54 | 2. Merge the directories with photos taken on the same day 55 | + [MergeDirectories.java](https://github.com/dsouzarc/dotfiles/blob/master/Java/MergeDirectories.java) looks at all the directory names inside a folder and if it finds names like 'DATE' 'DATE #2' 'DATE #3', moves all the photos from 'DATE #2' and 'DATE #3' to 'DATE' 56 | 3. Reset the file created time and date to the day it was created 57 | + [ResetImageTimes.java](https://github.com/dsouzarc/dotfiles/blob/master/Java/ResetImageTimes.java) resets the date created timestamp of each photo in a directory to a date version of that directory's name and changes the image's name to a uniform version 58 | + For example, if a folder is named: 2015-02-22 59 | - Images in that folder would be named 2015-02-22_01.jpg 2015-02-22_02.jpg 2015-02-22_03.jpg 60 | - The date created/last modified timestamp of that photo would be: "Sunday, February 22nd 2015" 61 | 62 | 63 | # My solution worked and I was able to successfully transfer all the photos backed up on Google+ to my iPhone 6 :) 64 | -------------------------------------------------------------------------------- /Java/ResetImageTimes.java: -------------------------------------------------------------------------------- 1 | import java.io.File; 2 | import java.util.HashMap; 3 | import java.util.Date; 4 | import java.text.SimpleDateFormat; 5 | 6 | public class ResetImageTimes { 7 | 8 | public static final SimpleDateFormat googleDateFormat = new SimpleDateFormat("yyyy-MM-dd"); 9 | 10 | public static void main(String[] ryan) throws Exception { 11 | 12 | final File currentDirectory = new File(System.getProperty("user.dir")); 13 | final File[] directoryFiles = currentDirectory.listFiles(); 14 | 15 | int numFileNamesChanged = 0; 16 | 17 | for(File directory : directoryFiles) { 18 | 19 | //We are only going to deal with directories 20 | if(directory.isDirectory()) { 21 | 22 | //Turn the directories name into a date/time 23 | final String directoryName = directory.getName(); 24 | 25 | final Date pictureTakenDate = googleDateFormat.parse(directoryName); 26 | 27 | //All the images in the folder 28 | final File[] imagesInFolder = directory.listFiles(); 29 | 30 | //Go through all of the images 31 | for(int i = 0; i < imagesInFolder.length; i++) { 32 | 33 | final String fileExtension = getFileExtension(imagesInFolder[i].getName()); 34 | 35 | final File newFileName = new File(imagesInFolder[i].getAbsolutePath() + "/" + directoryName + "-" + i + fileExtension); 36 | 37 | if(newFileName.exists()) { 38 | System.out.println("DUPLICATE EXISTS: " + imagesInFolder[i].getName()); 39 | } 40 | 41 | else { 42 | numFileNamesChanged++; 43 | 44 | final File newestFile = new File(directoryName + "/" + directoryName + "-" + i + fileExtension); 45 | if(imagesInFolder[i].renameTo(newestFile)) { 46 | System.out.println("Successfully changed name to: " + newFileName); 47 | 48 | if(newestFile.setLastModified(pictureTakenDate.getTime())) { 49 | System.out.println("SUCCESSFUL DATE MODIFICATION"); 50 | } 51 | else { 52 | System.out.println("UNSUCCESSFUL DATE MODIFICATION"); 53 | } 54 | } 55 | else { 56 | System.out.println("PROBLEM CHANGING FILE NAME: " + imagesInFolder[i].getName()); 57 | } 58 | } 59 | } 60 | } 61 | } 62 | 63 | System.out.println("CHANGED: " + numFileNamesChanged); 64 | } 65 | 66 | public static String getFileExtension(final String original) { 67 | int lastPeriod = original.lastIndexOf("."); 68 | 69 | if(lastPeriod == -1) { 70 | return ""; 71 | } 72 | 73 | return original.substring(lastPeriod); 74 | } 75 | 76 | } 77 | 78 | -------------------------------------------------------------------------------- /Python/CredentialManagerExample.py: -------------------------------------------------------------------------------- 1 | import CredentialManager; 2 | 3 | #Tests CredentialManager.py 4 | 5 | #Two ways to save credentials: 6 | 7 | #1 8 | CredentialManager.save_credentials("gmailUsernameKey", "secretUsername", "gmailPasswordKey", "secretPassword"); 9 | #2. Prompts for info to be entered 10 | #Enter 'python CredentialManager.py' in terminal 11 | 12 | CredentialManager.save_key("gmailUsername", "gmailPassword"); 13 | 14 | password = CredentialManager.get_value("gmailUsername"); 15 | 16 | if CredentialManager.does_key_exist("gmailUsername"): 17 | CredentialManager.delete_key("gmailUsername"); 18 | -------------------------------------------------------------------------------- /Python/CredentialManager_Legacy.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | import base64 4 | import json 5 | import getpass 6 | import os 7 | import sys 8 | 9 | """Note: This is not a secure password manager for production purposes. 10 | It sacrifices security at the expense of convenience and quicker speed. 11 | I mainly use it as a fast way to access (centralized) credentials for my personal side projects 12 | """ 13 | 14 | 15 | ###################################################################################### 16 | # Written by Ryan D'souza in 2015 17 | # A password manager completely written in Python 18 | # 19 | # For run instructions, see 20 | # https://github.com/dsouzarc/dotfiles/tree/master/Python#credential-manager 21 | ###################################################################################### 22 | 23 | 24 | #Store data in hidden file in hidden folder in home directory 25 | directory_path = str(os.path.expanduser("~")) + "/.my_credential_manager/" 26 | file_path = directory_path + ".credential_files.json" 27 | 28 | 29 | #Create path if needed 30 | if not os.path.exists(directory_path): 31 | print("Initialized credential manager: " + file_path) 32 | os.makedirs(directory_path) 33 | 34 | 35 | #Load data from file 36 | if os.path.isfile(file_path): 37 | try: 38 | with open(file_path) as credential_file: 39 | credentials = json.load(credential_file) 40 | except ValueError: 41 | print("Value error for loading existing credentials from file. Building new file") 42 | credentials = {} 43 | else: 44 | print("No existing credentials") 45 | credentials = {} 46 | 47 | 48 | ################################# 49 | # UTILITY & MANAGERIAL METHODS 50 | ################################# 51 | 52 | 53 | def save_credentials_prompt(): 54 | """Prompts user to enter username and password for an account and then saves it""" 55 | 56 | account_name = raw_input("Enter account name: ") 57 | username_raw = raw_input("Enter username for account: ") 58 | password_raw = getpass.getpass("Enter password for account: ") 59 | 60 | username_key = account_name + "_Username" 61 | password_key = account_name + "_Password" 62 | 63 | save_credentials(username_key, username_raw, password_key) 64 | 65 | 66 | def get_credentials(account_name): 67 | """Retrieves the (username, password) as a tuple for the given account name 68 | 69 | Args: 70 | account_name (str): Name of the service 71 | 72 | Returns: 73 | tuple(str, str): Username and password for the service 74 | """ 75 | 76 | username_key = account_name + "_Username" 77 | password_key = account_name + "_Password" 78 | 79 | username = get_value(username_key) 80 | password = get_value(password_key) 81 | 82 | return (username, password) 83 | 84 | 85 | def get_credentials_prompt(): 86 | """Prompts the user to enter an account name. Prints the credentials""" 87 | 88 | account_name = raw_input("Enter account name: ") 89 | username, password = get_credentials(account_name) 90 | 91 | print(username) 92 | print(password) 93 | 94 | 95 | def encrypt_value(value): 96 | """Convenience method to centrally handle encryption/encoding 97 | 98 | Args: 99 | value (str): Value to encrypt 100 | 101 | Returns: 102 | encoded value 103 | """ 104 | 105 | return base64.b64encode(value) 106 | 107 | 108 | def save_credentials(usernameKey, username, password, passwordKey): 109 | """Updates the dictionary with the key and saves it to the file""" 110 | 111 | credentials[usernameKey] = base64.b64encode(username) 112 | credentials[passwordKey] = base64.b64encode(password) 113 | 114 | with open(file_path, 'w') as credential_file: 115 | json.dump(credentials, credential_file, sort_keys=True, indent=4, ensure_ascii=False) 116 | print("Credentials saved") 117 | 118 | def save_credentials(credentials): 119 | """Convenience method to centrally handle saving the file""" 120 | 121 | with open(file_path, 'w') as credential_file: 122 | json.dump(credentials, credential_file, sort_keys=True, indent=4 123 | 124 | #Save key to value (with secure prompt) 125 | def save_key_prompt(): 126 | key = raw_input("Key: ") 127 | value = raw_input("Value: ") 128 | save_key(key, value) 129 | 130 | 131 | #Get value/credential associated with key 132 | def get_value(key): 133 | if key in credentials: 134 | return base64.b64decode(credentials[key]) 135 | else: 136 | raise KeyError("No value found for: " + key) 137 | 138 | def get(key): 139 | return get_value(key) 140 | 141 | def get_value_prompt(): 142 | return get_value(raw_input("Enter key: ")) 143 | 144 | #Check to see if a value/credential exists 145 | def does_key_exist(key): 146 | return key in credentials 147 | 148 | def does_key_exist_prompt(): 149 | return does_key_exist(raw_input("Enter key: ")) 150 | 151 | #Delete a credential 152 | def delete_key(key): 153 | 154 | if key in credentials: 155 | del credentials[key] 156 | 157 | with open(file_path, 'w') as file: 158 | json.dump(credentials, file, sort_keys = True, indent = 4, ensure_ascii = False) 159 | print("Value for '" + key + "' has been deleted. Credentials saved") 160 | return 161 | print("Error saving credentials") 162 | else: 163 | print("Delete failed '" + key + "' does not exist") 164 | 165 | 166 | def delete_key_prompt(): 167 | delete_key(raw_input("Enter key to delete: ")) 168 | 169 | #Prompts for credentials, then saves them 170 | def save_credentials_prompt(): 171 | usernameKey = raw_input("Username key: ") 172 | username = raw_input("Username: ") 173 | passwordKey = raw_input("Password key: ") 174 | password = getpass.getpass("Password: ") 175 | 176 | save_credentials(usernameKey, username, password, passwordKey) 177 | 178 | #Only prompt for credentials and then save them if this file is run from main ( 'python CredentialManager.py' ) 179 | if __name__ == "__main__": 180 | 181 | if len(sys.argv) == 1: 182 | save_credentials_prompt() 183 | 184 | elif len(sys.argv) == 2: 185 | 186 | if sys.argv[1] == "save_credentials": 187 | save_credentials_prompt() 188 | elif sys.argv[1] == "save_key": 189 | save_key_prompt() 190 | elif sys.argv[1] == "set_value": 191 | save_key_prompt() 192 | 193 | elif sys.argv[1] == "get_credentials": 194 | get_credentials_prompt() 195 | elif sys.argv[1] == "get_value": 196 | print(get_value_prompt()) 197 | elif sys.argv[1] == "does_key_exist": 198 | print(does_key_exist_prompt()) 199 | elif sys.argv[1] == "delete_key": 200 | delete_key_prompt() 201 | -------------------------------------------------------------------------------- /Python/Dictionary.py: -------------------------------------------------------------------------------- 1 | import sys; 2 | import urllib; 3 | import json; 4 | 5 | ######################################################################### 6 | # Written by Ryan D'souza 7 | # Prints the definition of a word and an example of it in a sentence 8 | # Uses Pearson Dictionary API 9 | # 10 | # Dependencies: None 11 | # Usage: 12 | # python Dictionary.py perfunctory 13 | # 14 | # Or, to prompt: 15 | # python Dictionary.py 16 | ######################################################################### 17 | 18 | 19 | #Prints results in a nice format 20 | def printResults(dictionary): 21 | 22 | senses = dictionary['senses']; 23 | 24 | for sense in senses: 25 | 26 | if 'definition' in sense: 27 | definition = sense['definition']; 28 | 29 | #Multiple definitions 30 | if isinstance(definition, list): 31 | for defi in definition: 32 | print("Definition: " + defi); 33 | else: 34 | print("Definition: " + definition); 35 | 36 | #Not all definitions include an example 37 | if 'examples' in sense: 38 | examples = sense['examples']; 39 | 40 | #Multiple examples 41 | for example in examples: 42 | print("\tExample: " + example['text']); 43 | 44 | #API URL 45 | url = "https://api.pearson.com:443/v2/dictionaries/entries?headword="; 46 | 47 | if len(sys.argv) == 1: 48 | word = raw_input("Enter word to define: "); 49 | else: 50 | word = sys.argv[1]; 51 | 52 | url += word; 53 | 54 | request = urllib.urlopen(url); 55 | response = request.read(); 56 | 57 | if request.getcode() != 200: 58 | print("Error getting data: " + str(response)); 59 | 60 | response = json.loads(response); 61 | 62 | if int(response["total"]) == 0: 63 | print("No definitions"); 64 | else: 65 | results = response["results"]; 66 | 67 | for array in results: 68 | dataset = array["datasets"][0]; 69 | if dataset == "laad3" or dataset == "ldoce5" or dataset == "lasde" or dataset == "laes" or dataset == "brep": 70 | printResults(array); 71 | 72 | -------------------------------------------------------------------------------- /Python/EmailAttachment.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | import CredentialManager; 3 | import os; 4 | import sys; 5 | import urllib2; 6 | import urllib; 7 | 8 | ###################################################### 9 | # Written by Ryan D'souza 10 | # Sends an attachment to myself using SendGrid's API 11 | # Can be run from any directory 12 | # 13 | # Dependencies: CredentialManager 14 | # tiny.cc/credentialManager 15 | # 16 | # Run Instructions: 17 | # python EmailAttachment.py fileName 18 | ###################################################### 19 | 20 | 21 | #If filename is commandline argument 22 | if len(sys.argv) == 2: 23 | fileName = sys.argv[1]; 24 | else: 25 | fileName = raw_input("Enter file name: "); 26 | 27 | #Url for POST request 28 | url = "https://api.sendgrid.com/api/mail.send.json"; 29 | 30 | #My Information 31 | username = CredentialManager.get_value("SendGridUsername"); 32 | password = CredentialManager.get_value("SendGridPassword"); 33 | from_ = "MBProCL"; 34 | to = "dsouzarc@gmail.com"; 35 | 36 | #Parameters, same as usual 37 | params = { 38 | "api_user": username, 39 | "api_key": password, 40 | "from": from_, 41 | "to": to, 42 | "subject": " ", 43 | "text": fileName, 44 | }; 45 | 46 | #Current working directory + file name 47 | filePath = str(os.getcwd()) + "/" + fileName; 48 | 49 | #Add the file to the params 50 | with open(filePath, 'rb') as f: 51 | params['files[' + fileName + ']'] = f.read(); 52 | 53 | #Encode them 54 | params = urllib.urlencode(params); 55 | 56 | #Request/response 57 | request = urllib.urlopen(url, params); 58 | response = request.read(); 59 | 60 | if response.find("success") == -1: 61 | print(response); 62 | else: 63 | print("Successfully sent"); 64 | -------------------------------------------------------------------------------- /Python/EmailMe.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | import CredentialManager; 3 | import sys; 4 | import urllib2; 5 | import urllib; 6 | 7 | ###################################################### 8 | # Written by Ryan D'souza 9 | # Sends an email to myself using SendGrid's API 10 | # 11 | # Dependencies: CredentialManager 12 | # tiny.cc/credentialManager 13 | # 14 | # Run Instructions: 15 | # python EmailMe.py 16 | ###################################################### 17 | 18 | #If message is commandline argument 19 | if len(sys.argv) == 2: 20 | message = sys.argv[1]; 21 | else: 22 | message = raw_input("Enter message: "); 23 | 24 | #Url for POST request 25 | url = "https://api.sendgrid.com/api/mail.send.json"; 26 | 27 | #My Information 28 | username = CredentialManager.get_value("SendGridUsername"); 29 | password = CredentialManager.get_value("SendGridPassword"); 30 | from_ = "RyansMacbookProCommandLine"; 31 | to = "dsouzarc@gmail.com"; 32 | 33 | params = { 34 | "api_user": username, 35 | "api_key": password, 36 | "from": from_, 37 | "to": to, 38 | "subject": "MBPro CL", 39 | "text": message 40 | }; 41 | 42 | params = urllib.urlencode(params); 43 | 44 | request = urllib.urlopen(url, params); 45 | response = request.read(); 46 | 47 | if response.find("success") == -1: 48 | print(response); 49 | else: 50 | print("Successfully sent"); 51 | -------------------------------------------------------------------------------- /Python/NoteTaker/Dubliners Notes.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsouzarc/dotfiles/f771532b0f512efcefa3dc0ede31deceaf0e9acc/Python/NoteTaker/Dubliners Notes.docx -------------------------------------------------------------------------------- /Python/NoteTaker/Dubliners Notes.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsouzarc/dotfiles/f771532b0f512efcefa3dc0ede31deceaf0e9acc/Python/NoteTaker/Dubliners Notes.pdf -------------------------------------------------------------------------------- /Python/NoteTaker/Dubliners.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsouzarc/dotfiles/f771532b0f512efcefa3dc0ede31deceaf0e9acc/Python/NoteTaker/Dubliners.pdf -------------------------------------------------------------------------------- /Python/NoteTaker/NoteTaker.py: -------------------------------------------------------------------------------- 1 | import pyPdf; 2 | import random; 3 | 4 | from docx import Document; 5 | 6 | #################################################################### 7 | # Written by Ryan D'souza 8 | # Generates notes randomly from a PDF 9 | # See: github.com/dsouzarc/dotfiles/tree/master/Python/NoteTaker 10 | #################################################################### 11 | 12 | #UPDATE THESE 13 | fileName = "Dubliners.pdf"; 14 | noteSheetName = "Dubliners Notes.md"; 15 | noteSheetWordName = "Dubliners Notes.docx"; 16 | startPage = 4; #The actual first page of the book 17 | 18 | #Optional Update 19 | noteFrequency = 2; 20 | minWordsInLine = 5; 21 | 22 | failCounter = 0; 23 | 24 | #Returns a random note line based on some conditions 25 | def randomNote(lines): 26 | 27 | global failCounter; 28 | 29 | #If, within 6 tries, we cannot find a sentence that matches what we want, just return 30 | if failCounter > 5: 31 | failCounter = 0; 32 | return None; 33 | 34 | #Choose a random sentence 35 | randomNoteLine = random.choice(lines); 36 | 37 | #If it doesn't match the conditions we want, recurse until we find a sentence that does 38 | if len(randomNoteLine.split(" ")) <= minWordsInLine: 39 | failCounter += 1; 40 | return randomNote(lines); 41 | 42 | #Otherwise, just return the line we found 43 | else: 44 | failCounter = 0; 45 | return randomNoteLine + "."; 46 | 47 | #Markdown format line for notes 48 | def formatLine(pageNumber, line): 49 | formattedLine = "- **Page " + str(pageNumber) + "**: " + line + "\n"; 50 | return formattedLine; 51 | 52 | #PDF version of the book 53 | book = file(fileName, "rb"); 54 | pdf = pyPdf.PdfFileReader(book); 55 | 56 | if pdf.isEncrypted: 57 | pdf.decrypt(''); 58 | 59 | #Create a notes file 60 | notes = open(noteSheetName, "w"); 61 | wordDocument = Document(); 62 | 63 | for i in range(startPage, pdf.getNumPages()): 64 | 65 | #If it is time to take a note 66 | if (i - startPage) % noteFrequency == 0: 67 | 68 | #Gets each line on the page 69 | page = pdf.getPage(i); 70 | text = page.extractText(); 71 | text = text.replace("\n", " "); 72 | lines = text.split("."); 73 | 74 | failCounterLocal = 0; 75 | 76 | #While loop for continually retrying 'try' until there is no exception 77 | while True: 78 | 79 | #If we keep on getting errors (like encoding errors), try the prior page 80 | if failCounterLocal > 5: 81 | page = pdf.getPage(i - 1); 82 | text = page.extractText(); 83 | text = text.replace("\n", " "); 84 | lines = text.split("."); 85 | failCounterLocal = 0; 86 | 87 | #Try writing to both files (possible encoding error) 88 | try: 89 | 90 | #Get a formatted line at random from the page 91 | randomNoteLine = randomNote(lines); 92 | 93 | #If we can't find a line that satisfies our conditions, reset to the for-loop which will give us a new page and new lines 94 | if randomNoteLine is None: 95 | break; 96 | 97 | #Markdown formatted line 98 | formattedLine = formatLine(i + 1, randomNoteLine); 99 | 100 | #Add the line to the word document note sheet and the markdown note sheet 101 | notes.write(formattedLine); 102 | noteLine = wordDocument.add_paragraph('', style='ListBullet'); 103 | noteLine.add_run('Page ' + str(i + 1) + ': ').bold = True 104 | noteLine.add_run(randomNoteLine).bold = False; 105 | break; 106 | 107 | #Sometimes there is an encoding error. Increment our problem counter. Head back to while 108 | except (UnicodeError): 109 | failCounterLocal += 1; 110 | 111 | #Save and print mission success :) 112 | notes.close(); 113 | wordDocument.save(noteSheetWordName); 114 | print("Notes created. Check: " + noteSheetName + " and " + noteSheetWordName); 115 | -------------------------------------------------------------------------------- /Python/NoteTaker/README.md: -------------------------------------------------------------------------------- 1 | #Written by Ryan D'souza 2 | ###Takes notes on a book 3 | 4 | Book must be formatted as a PDF for page number reasons. 5 | 6 | Disclaimer: I do not condone cheating. 7 | 8 | ####Dependencies & Installation 9 | None, just download this directory 10 | 11 | ####Run Instructions 12 | Change the variables in lines 13 - 16 of **NoteTaker.py** 13 | 14 | python NoteTaker.py 15 | 16 | Takes about 2 seconds to generate 5 pages of notes for a 250 page book 17 | 18 | Each time you run the above line, a different set of notes is generated, so if you're not happy with the current notes, you can run it again to regenerate a new set of notes. 19 | 20 | The notes will be created and stored as both a .docx and a .markdown file for your convenience. 21 | 22 | In both file cases, the format for a note is: 23 | - **Page X:** Some note or quotation. 24 | 25 | I strongly recommend reading through the resulting files to fix grammatical errors, strange formatting, and misplaced titles. 26 | 27 | For exporting .markdown notes to a neatly generated PDF, I recommend Byword 28 | -------------------------------------------------------------------------------- /Python/NoteTaker/docx/__init__.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | from docx.api import Document # noqa 4 | 5 | __version__ = '0.8.5' 6 | 7 | 8 | # register custom Part classes with opc package reader 9 | 10 | from docx.opc.constants import CONTENT_TYPE as CT, RELATIONSHIP_TYPE as RT 11 | from docx.opc.part import PartFactory 12 | from docx.opc.parts.coreprops import CorePropertiesPart 13 | 14 | from docx.parts.document import DocumentPart 15 | from docx.parts.image import ImagePart 16 | from docx.parts.numbering import NumberingPart 17 | from docx.parts.styles import StylesPart 18 | 19 | 20 | def part_class_selector(content_type, reltype): 21 | if reltype == RT.IMAGE: 22 | return ImagePart 23 | return None 24 | 25 | 26 | PartFactory.part_class_selector = part_class_selector 27 | PartFactory.part_type_for[CT.OPC_CORE_PROPERTIES] = CorePropertiesPart 28 | PartFactory.part_type_for[CT.WML_DOCUMENT_MAIN] = DocumentPart 29 | PartFactory.part_type_for[CT.WML_NUMBERING] = NumberingPart 30 | PartFactory.part_type_for[CT.WML_STYLES] = StylesPart 31 | 32 | del ( 33 | CT, CorePropertiesPart, DocumentPart, NumberingPart, PartFactory, 34 | StylesPart, part_class_selector 35 | ) 36 | -------------------------------------------------------------------------------- /Python/NoteTaker/docx/api.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | """ 4 | Directly exposed API functions and classes, :func:`Document` for now. 5 | Provides a syntactically more convenient API for interacting with the 6 | OpcPackage graph. 7 | """ 8 | 9 | from __future__ import absolute_import, division, print_function 10 | 11 | import os 12 | 13 | from docx.opc.constants import CONTENT_TYPE as CT 14 | from docx.package import Package 15 | 16 | 17 | def Document(docx=None): 18 | """ 19 | Return a |Document| object loaded from *docx*, where *docx* can be 20 | either a path to a ``.docx`` file (a string) or a file-like object. If 21 | *docx* is missing or ``None``, the built-in default document "template" 22 | is loaded. 23 | """ 24 | docx = _default_docx_path() if docx is None else docx 25 | document_part = Package.open(docx).main_document_part 26 | if document_part.content_type != CT.WML_DOCUMENT_MAIN: 27 | tmpl = "file '%s' is not a Word file, content type is '%s'" 28 | raise ValueError(tmpl % (docx, document_part.content_type)) 29 | return document_part.document 30 | 31 | 32 | def _default_docx_path(): 33 | """ 34 | Return the path to the built-in default .docx package. 35 | """ 36 | _thisdir = os.path.split(__file__)[0] 37 | return os.path.join(_thisdir, 'templates', 'default.docx') 38 | -------------------------------------------------------------------------------- /Python/NoteTaker/docx/blkcntnr.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | """ 4 | Block item container, used by body, cell, header, etc. Block level items are 5 | things like paragraph and table, although there are a few other specialized 6 | ones like structured document tags. 7 | """ 8 | 9 | from __future__ import absolute_import, print_function 10 | 11 | from .oxml.table import CT_Tbl 12 | from .shared import Parented 13 | from .text.paragraph import Paragraph 14 | 15 | 16 | class BlockItemContainer(Parented): 17 | """ 18 | Base class for proxy objects that can contain block items, such as _Body, 19 | _Cell, header, footer, footnote, endnote, comment, and text box objects. 20 | Provides the shared functionality to add a block item like a paragraph or 21 | table. 22 | """ 23 | def __init__(self, element, parent): 24 | super(BlockItemContainer, self).__init__(parent) 25 | self._element = element 26 | 27 | def add_paragraph(self, text='', style=None): 28 | """ 29 | Return a paragraph newly added to the end of the content in this 30 | container, having *text* in a single run if present, and having 31 | paragraph style *style*. If *style* is |None|, no paragraph style is 32 | applied, which has the same effect as applying the 'Normal' style. 33 | """ 34 | paragraph = self._add_paragraph() 35 | if text: 36 | paragraph.add_run(text) 37 | if style is not None: 38 | paragraph.style = style 39 | return paragraph 40 | 41 | def add_table(self, rows, cols, width): 42 | """ 43 | Return a table of *width* having *rows* rows and *cols* columns, 44 | newly appended to the content in this container. *width* is evenly 45 | distributed between the table columns. 46 | """ 47 | from .table import Table 48 | tbl = CT_Tbl.new_tbl(rows, cols, width) 49 | self._element._insert_tbl(tbl) 50 | return Table(tbl, self) 51 | 52 | @property 53 | def paragraphs(self): 54 | """ 55 | A list containing the paragraphs in this container, in document 56 | order. Read-only. 57 | """ 58 | return [Paragraph(p, self) for p in self._element.p_lst] 59 | 60 | @property 61 | def tables(self): 62 | """ 63 | A list containing the tables in this container, in document order. 64 | Read-only. 65 | """ 66 | from .table import Table 67 | return [Table(tbl, self) for tbl in self._element.tbl_lst] 68 | 69 | def _add_paragraph(self): 70 | """ 71 | Return a paragraph newly added to the end of the content in this 72 | container. 73 | """ 74 | return Paragraph(self._element.add_p(), self) 75 | -------------------------------------------------------------------------------- /Python/NoteTaker/docx/compat.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | """ 4 | Provides Python 2/3 compatibility objects 5 | """ 6 | 7 | from __future__ import ( 8 | absolute_import, division, print_function, unicode_literals 9 | ) 10 | 11 | import sys 12 | 13 | # =========================================================================== 14 | # Python 3 versions 15 | # =========================================================================== 16 | 17 | if sys.version_info >= (3, 0): 18 | 19 | from io import BytesIO 20 | 21 | def is_string(obj): 22 | """ 23 | Return True if *obj* is a string, False otherwise. 24 | """ 25 | return isinstance(obj, str) 26 | 27 | Unicode = str 28 | 29 | # =========================================================================== 30 | # Python 2 versions 31 | # =========================================================================== 32 | 33 | else: 34 | 35 | from StringIO import StringIO as BytesIO # noqa 36 | 37 | def is_string(obj): 38 | """ 39 | Return True if *obj* is a string, False otherwise. 40 | """ 41 | return isinstance(obj, basestring) 42 | 43 | Unicode = unicode 44 | -------------------------------------------------------------------------------- /Python/NoteTaker/docx/dml/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsouzarc/dotfiles/f771532b0f512efcefa3dc0ede31deceaf0e9acc/Python/NoteTaker/docx/dml/__init__.py -------------------------------------------------------------------------------- /Python/NoteTaker/docx/dml/color.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | """ 4 | DrawingML objects related to color, ColorFormat being the most prominent. 5 | """ 6 | 7 | from __future__ import ( 8 | absolute_import, division, print_function, unicode_literals 9 | ) 10 | 11 | from ..enum.dml import MSO_COLOR_TYPE 12 | from ..oxml.simpletypes import ST_HexColorAuto 13 | from ..shared import ElementProxy 14 | 15 | 16 | class ColorFormat(ElementProxy): 17 | """ 18 | Provides access to color settings such as RGB color, theme color, and 19 | luminance adjustments. 20 | """ 21 | 22 | __slots__ = () 23 | 24 | def __init__(self, rPr_parent): 25 | super(ColorFormat, self).__init__(rPr_parent) 26 | 27 | @property 28 | def rgb(self): 29 | """ 30 | An |RGBColor| value or |None| if no RGB color is specified. 31 | 32 | When :attr:`type` is `MSO_COLOR_TYPE.RGB`, the value of this property 33 | will always be an |RGBColor| value. It may also be an |RGBColor| 34 | value if :attr:`type` is `MSO_COLOR_TYPE.THEME`, as Word writes the 35 | current value of a theme color when one is assigned. In that case, 36 | the RGB value should be interpreted as no more than a good guess 37 | however, as the theme color takes precedence at rendering time. Its 38 | value is |None| whenever :attr:`type` is either |None| or 39 | `MSO_COLOR_TYPE.AUTO`. 40 | 41 | Assigning an |RGBColor| value causes :attr:`type` to become 42 | `MSO_COLOR_TYPE.RGB` and any theme color is removed. Assigning |None| 43 | causes any color to be removed such that the effective color is 44 | inherited from the style hierarchy. 45 | """ 46 | color = self._color 47 | if color is None: 48 | return None 49 | if color.val == ST_HexColorAuto.AUTO: 50 | return None 51 | return color.val 52 | 53 | @rgb.setter 54 | def rgb(self, value): 55 | if value is None and self._color is None: 56 | return 57 | rPr = self._element.get_or_add_rPr() 58 | rPr._remove_color() 59 | if value is not None: 60 | rPr.get_or_add_color().val = value 61 | 62 | @property 63 | def theme_color(self): 64 | """ 65 | A member of :ref:`MsoThemeColorIndex` or |None| if no theme color is 66 | specified. When :attr:`type` is `MSO_COLOR_TYPE.THEME`, the value of 67 | this property will always be a member of :ref:`MsoThemeColorIndex`. 68 | When :attr:`type` has any other value, the value of this property is 69 | |None|. 70 | 71 | Assigning a member of :ref:`MsoThemeColorIndex` causes :attr:`type` 72 | to become `MSO_COLOR_TYPE.THEME`. Any existing RGB value is retained 73 | but ignored by Word. Assigning |None| causes any color specification 74 | to be removed such that the effective color is inherited from the 75 | style hierarchy. 76 | """ 77 | color = self._color 78 | if color is None or color.themeColor is None: 79 | return None 80 | return color.themeColor 81 | 82 | @theme_color.setter 83 | def theme_color(self, value): 84 | if value is None: 85 | if self._color is not None: 86 | self._element.rPr._remove_color() 87 | return 88 | self._element.get_or_add_rPr().get_or_add_color().themeColor = value 89 | 90 | @property 91 | def type(self): 92 | """ 93 | Read-only. A member of :ref:`MsoColorType`, one of RGB, THEME, or 94 | AUTO, corresponding to the way this color is defined. Its value is 95 | |None| if no color is applied at this level, which causes the 96 | effective color to be inherited from the style hierarchy. 97 | """ 98 | color = self._color 99 | if color is None: 100 | return None 101 | if color.themeColor is not None: 102 | return MSO_COLOR_TYPE.THEME 103 | if color.val == ST_HexColorAuto.AUTO: 104 | return MSO_COLOR_TYPE.AUTO 105 | return MSO_COLOR_TYPE.RGB 106 | 107 | @property 108 | def _color(self): 109 | """ 110 | Return `w:rPr/w:color` or |None| if not present. Helper to factor out 111 | repetitive element access. 112 | """ 113 | rPr = self._element.rPr 114 | if rPr is None: 115 | return None 116 | return rPr.color 117 | -------------------------------------------------------------------------------- /Python/NoteTaker/docx/enum/__init__.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | """ 4 | Enumerations used in python-docx 5 | """ 6 | 7 | from __future__ import absolute_import, print_function, unicode_literals 8 | 9 | 10 | class Enumeration(object): 11 | 12 | @classmethod 13 | def from_xml(cls, xml_val): 14 | return cls._xml_to_idx[xml_val] 15 | 16 | @classmethod 17 | def to_xml(cls, enum_val): 18 | return cls._idx_to_xml[enum_val] 19 | -------------------------------------------------------------------------------- /Python/NoteTaker/docx/enum/dml.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | """ 4 | Enumerations used by DrawingML objects 5 | """ 6 | 7 | from __future__ import absolute_import 8 | 9 | from .base import ( 10 | alias, Enumeration, EnumMember, XmlEnumeration, XmlMappedEnumMember 11 | ) 12 | 13 | 14 | class MSO_COLOR_TYPE(Enumeration): 15 | """ 16 | Specifies the color specification scheme 17 | 18 | Example:: 19 | 20 | from docx.enum.dml import MSO_COLOR_TYPE 21 | 22 | assert font.color.type == MSO_COLOR_TYPE.SCHEME 23 | """ 24 | 25 | __ms_name__ = 'MsoColorType' 26 | 27 | __url__ = ( 28 | 'http://msdn.microsoft.com/en-us/library/office/ff864912(v=office.15' 29 | ').aspx' 30 | ) 31 | 32 | __members__ = ( 33 | EnumMember( 34 | 'RGB', 1, 'Color is specified by an |RGBColor| value.' 35 | ), 36 | EnumMember( 37 | 'THEME', 2, 'Color is one of the preset theme colors.' 38 | ), 39 | EnumMember( 40 | 'AUTO', 101, 'Color is determined automatically by the ' 41 | 'application.' 42 | ), 43 | ) 44 | 45 | 46 | @alias('MSO_THEME_COLOR') 47 | class MSO_THEME_COLOR_INDEX(XmlEnumeration): 48 | """ 49 | Indicates the Office theme color, one of those shown in the color gallery 50 | on the formatting ribbon. 51 | 52 | Alias: ``MSO_THEME_COLOR`` 53 | 54 | Example:: 55 | 56 | from docx.enum.dml import MSO_THEME_COLOR 57 | 58 | font.color.theme_color = MSO_THEME_COLOR.ACCENT_1 59 | """ 60 | 61 | __ms_name__ = 'MsoThemeColorIndex' 62 | 63 | __url__ = ( 64 | 'http://msdn.microsoft.com/en-us/library/office/ff860782(v=office.15' 65 | ').aspx' 66 | ) 67 | 68 | __members__ = ( 69 | EnumMember( 70 | 'NOT_THEME_COLOR', 0, 'Indicates the color is not a theme color.' 71 | ), 72 | XmlMappedEnumMember( 73 | 'ACCENT_1', 5, 'accent1', 'Specifies the Accent 1 theme color.' 74 | ), 75 | XmlMappedEnumMember( 76 | 'ACCENT_2', 6, 'accent2', 'Specifies the Accent 2 theme color.' 77 | ), 78 | XmlMappedEnumMember( 79 | 'ACCENT_3', 7, 'accent3', 'Specifies the Accent 3 theme color.' 80 | ), 81 | XmlMappedEnumMember( 82 | 'ACCENT_4', 8, 'accent4', 'Specifies the Accent 4 theme color.' 83 | ), 84 | XmlMappedEnumMember( 85 | 'ACCENT_5', 9, 'accent5', 'Specifies the Accent 5 theme color.' 86 | ), 87 | XmlMappedEnumMember( 88 | 'ACCENT_6', 10, 'accent6', 'Specifies the Accent 6 theme color.' 89 | ), 90 | XmlMappedEnumMember( 91 | 'BACKGROUND_1', 14, 'background1', 'Specifies the Background 1 ' 92 | 'theme color.' 93 | ), 94 | XmlMappedEnumMember( 95 | 'BACKGROUND_2', 16, 'background2', 'Specifies the Background 2 ' 96 | 'theme color.' 97 | ), 98 | XmlMappedEnumMember( 99 | 'DARK_1', 1, 'dark1', 'Specifies the Dark 1 theme color.' 100 | ), 101 | XmlMappedEnumMember( 102 | 'DARK_2', 3, 'dark2', 'Specifies the Dark 2 theme color.' 103 | ), 104 | XmlMappedEnumMember( 105 | 'FOLLOWED_HYPERLINK', 12, 'followedHyperlink', 'Specifies the ' 106 | 'theme color for a clicked hyperlink.' 107 | ), 108 | XmlMappedEnumMember( 109 | 'HYPERLINK', 11, 'hyperlink', 'Specifies the theme color for a ' 110 | 'hyperlink.' 111 | ), 112 | XmlMappedEnumMember( 113 | 'LIGHT_1', 2, 'light1', 'Specifies the Light 1 theme color.' 114 | ), 115 | XmlMappedEnumMember( 116 | 'LIGHT_2', 4, 'light2', 'Specifies the Light 2 theme color.' 117 | ), 118 | XmlMappedEnumMember( 119 | 'TEXT_1', 13, 'text1', 'Specifies the Text 1 theme color.' 120 | ), 121 | XmlMappedEnumMember( 122 | 'TEXT_2', 15, 'text2', 'Specifies the Text 2 theme color.' 123 | ), 124 | ) 125 | -------------------------------------------------------------------------------- /Python/NoteTaker/docx/enum/section.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | """ 4 | Enumerations related to the main document in WordprocessingML files 5 | """ 6 | 7 | from __future__ import absolute_import, print_function, unicode_literals 8 | 9 | from .base import alias, XmlEnumeration, XmlMappedEnumMember 10 | 11 | 12 | @alias('WD_ORIENT') 13 | class WD_ORIENTATION(XmlEnumeration): 14 | """ 15 | alias: **WD_ORIENT** 16 | 17 | Specifies the page layout orientation. 18 | 19 | Example:: 20 | 21 | from docx.enum.section import WD_ORIENT 22 | 23 | section = document.sections[-1] 24 | section.orientation = WD_ORIENT.LANDSCAPE 25 | """ 26 | 27 | __ms_name__ = 'WdOrientation' 28 | 29 | __url__ = 'http://msdn.microsoft.com/en-us/library/office/ff837902.aspx' 30 | 31 | __members__ = ( 32 | XmlMappedEnumMember( 33 | 'PORTRAIT', 0, 'portrait', 'Portrait orientation.' 34 | ), 35 | XmlMappedEnumMember( 36 | 'LANDSCAPE', 1, 'landscape', 'Landscape orientation.' 37 | ), 38 | ) 39 | 40 | 41 | @alias('WD_SECTION') 42 | class WD_SECTION_START(XmlEnumeration): 43 | """ 44 | alias: **WD_SECTION** 45 | 46 | Specifies the start type of a section break. 47 | 48 | Example:: 49 | 50 | from docx.enum.section import WD_SECTION 51 | 52 | section = document.sections[0] 53 | section.start_type = WD_SECTION.NEW_PAGE 54 | """ 55 | 56 | __ms_name__ = 'WdSectionStart' 57 | 58 | __url__ = 'http://msdn.microsoft.com/en-us/library/office/ff840975.aspx' 59 | 60 | __members__ = ( 61 | XmlMappedEnumMember( 62 | 'CONTINUOUS', 0, 'continuous', 'Continuous section break.' 63 | ), 64 | XmlMappedEnumMember( 65 | 'NEW_COLUMN', 1, 'nextColumn', 'New column section break.' 66 | ), 67 | XmlMappedEnumMember( 68 | 'NEW_PAGE', 2, 'nextPage', 'New page section break.' 69 | ), 70 | XmlMappedEnumMember( 71 | 'EVEN_PAGE', 3, 'evenPage', 'Even pages section break.' 72 | ), 73 | XmlMappedEnumMember( 74 | 'ODD_PAGE', 4, 'oddPage', 'Section begins on next odd page.' 75 | ), 76 | ) 77 | -------------------------------------------------------------------------------- /Python/NoteTaker/docx/enum/shape.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | """ 4 | Enumerations related to DrawingML shapes in WordprocessingML files 5 | """ 6 | 7 | from __future__ import absolute_import, print_function, unicode_literals 8 | 9 | 10 | class WD_INLINE_SHAPE_TYPE(object): 11 | """ 12 | Corresponds to WdInlineShapeType enumeration 13 | http://msdn.microsoft.com/en-us/library/office/ff192587.aspx 14 | """ 15 | CHART = 12 16 | LINKED_PICTURE = 4 17 | PICTURE = 3 18 | SMART_ART = 15 19 | NOT_IMPLEMENTED = -6 20 | 21 | WD_INLINE_SHAPE = WD_INLINE_SHAPE_TYPE 22 | -------------------------------------------------------------------------------- /Python/NoteTaker/docx/enum/table.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | """ 4 | Enumerations related to tables in WordprocessingML files 5 | """ 6 | 7 | from __future__ import ( 8 | absolute_import, division, print_function, unicode_literals 9 | ) 10 | 11 | from .base import ( 12 | Enumeration, EnumMember, XmlEnumeration, XmlMappedEnumMember 13 | ) 14 | 15 | 16 | class WD_TABLE_ALIGNMENT(XmlEnumeration): 17 | """ 18 | Specifies table justification type. 19 | 20 | Example:: 21 | 22 | from docx.enum.table import WD_TABLE_ALIGNMENT 23 | 24 | table = document.add_table(3, 3) 25 | table.alignment = WD_TABLE_ALIGNMENT.CENTER 26 | """ 27 | 28 | __ms_name__ = 'WdRowAlignment' 29 | 30 | __url__ = ' http://office.microsoft.com/en-us/word-help/HV080607259.aspx' 31 | 32 | __members__ = ( 33 | XmlMappedEnumMember( 34 | 'LEFT', 0, 'left', 'Left-aligned' 35 | ), 36 | XmlMappedEnumMember( 37 | 'CENTER', 1, 'center', 'Center-aligned.' 38 | ), 39 | XmlMappedEnumMember( 40 | 'RIGHT', 2, 'right', 'Right-aligned.' 41 | ), 42 | ) 43 | 44 | 45 | class WD_TABLE_DIRECTION(Enumeration): 46 | """ 47 | Specifies the direction in which an application orders cells in the 48 | specified table or row. 49 | 50 | Example:: 51 | 52 | from docx.enum.table import WD_TABLE_DIRECTION 53 | 54 | table = document.add_table(3, 3) 55 | table.direction = WD_TABLE_DIRECTION.RTL 56 | """ 57 | 58 | __ms_name__ = 'WdTableDirection' 59 | 60 | __url__ = ' http://msdn.microsoft.com/en-us/library/ff835141.aspx' 61 | 62 | __members__ = ( 63 | EnumMember( 64 | 'LTR', 0, 'The table or row is arranged with the first column ' 65 | 'in the leftmost position.' 66 | ), 67 | EnumMember( 68 | 'RTL', 1, 'The table or row is arranged with the first column ' 69 | 'in the rightmost position.' 70 | ), 71 | ) 72 | -------------------------------------------------------------------------------- /Python/NoteTaker/docx/enum/text.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | """ 4 | Enumerations related to text in WordprocessingML files 5 | """ 6 | 7 | from __future__ import absolute_import, print_function, unicode_literals 8 | 9 | from .base import alias, EnumMember, XmlEnumeration, XmlMappedEnumMember 10 | 11 | 12 | @alias('WD_ALIGN_PARAGRAPH') 13 | class WD_PARAGRAPH_ALIGNMENT(XmlEnumeration): 14 | """ 15 | alias: **WD_ALIGN_PARAGRAPH** 16 | 17 | Specifies paragraph justification type. 18 | 19 | Example:: 20 | 21 | from docx.enum.text import WD_ALIGN_PARAGRAPH 22 | 23 | paragraph = document.add_paragraph() 24 | paragraph.alignment = WD_ALIGN_PARAGRAPH.CENTER 25 | """ 26 | 27 | __ms_name__ = 'WdParagraphAlignment' 28 | 29 | __url__ = 'http://msdn.microsoft.com/en-us/library/office/ff835817.aspx' 30 | 31 | __members__ = ( 32 | XmlMappedEnumMember( 33 | 'LEFT', 0, 'left', 'Left-aligned' 34 | ), 35 | XmlMappedEnumMember( 36 | 'CENTER', 1, 'center', 'Center-aligned.' 37 | ), 38 | XmlMappedEnumMember( 39 | 'RIGHT', 2, 'right', 'Right-aligned.' 40 | ), 41 | XmlMappedEnumMember( 42 | 'JUSTIFY', 3, 'both', 'Fully justified.' 43 | ), 44 | XmlMappedEnumMember( 45 | 'DISTRIBUTE', 4, 'distribute', 'Paragraph characters are distrib' 46 | 'uted to fill the entire width of the paragraph.' 47 | ), 48 | XmlMappedEnumMember( 49 | 'JUSTIFY_MED', 5, 'mediumKashida', 'Justified with a medium char' 50 | 'acter compression ratio.' 51 | ), 52 | XmlMappedEnumMember( 53 | 'JUSTIFY_HI', 7, 'highKashida', 'Justified with a high character' 54 | ' compression ratio.' 55 | ), 56 | XmlMappedEnumMember( 57 | 'JUSTIFY_LOW', 8, 'lowKashida', 'Justified with a low character ' 58 | 'compression ratio.' 59 | ), 60 | XmlMappedEnumMember( 61 | 'THAI_JUSTIFY', 9, 'thaiDistribute', 'Justified according to Tha' 62 | 'i formatting layout.' 63 | ), 64 | ) 65 | 66 | 67 | class WD_BREAK_TYPE(object): 68 | """ 69 | Corresponds to WdBreakType enumeration 70 | http://msdn.microsoft.com/en-us/library/office/ff195905.aspx 71 | """ 72 | COLUMN = 8 73 | LINE = 6 74 | LINE_CLEAR_LEFT = 9 75 | LINE_CLEAR_RIGHT = 10 76 | LINE_CLEAR_ALL = 11 # added for consistency, not in MS version 77 | PAGE = 7 78 | SECTION_CONTINUOUS = 3 79 | SECTION_EVEN_PAGE = 4 80 | SECTION_NEXT_PAGE = 2 81 | SECTION_ODD_PAGE = 5 82 | TEXT_WRAPPING = 11 83 | 84 | WD_BREAK = WD_BREAK_TYPE 85 | 86 | 87 | class WD_LINE_SPACING(XmlEnumeration): 88 | """ 89 | Specifies a line spacing format to be applied to a paragraph. 90 | 91 | Example:: 92 | 93 | from docx.enum.text import WD_LINE_SPACING 94 | 95 | paragraph = document.add_paragraph() 96 | paragraph.line_spacing_rule = WD_LINE_SPACING.EXACTLY 97 | """ 98 | 99 | __ms_name__ = 'WdLineSpacing' 100 | 101 | __url__ = 'http://msdn.microsoft.com/en-us/library/office/ff844910.aspx' 102 | 103 | __members__ = ( 104 | EnumMember( 105 | 'ONE_POINT_FIVE', 1, 'Space-and-a-half line spacing.' 106 | ), 107 | XmlMappedEnumMember( 108 | 'AT_LEAST', 3, 'atLeast', 'Line spacing is always at least the s' 109 | 'pecified amount. The amount is specified separately.' 110 | ), 111 | EnumMember( 112 | 'DOUBLE', 2, 'Double spaced.' 113 | ), 114 | XmlMappedEnumMember( 115 | 'EXACTLY', 4, 'exact', 'Line spacing is exactly the specified am' 116 | 'ount. The amount is specified separately.' 117 | ), 118 | XmlMappedEnumMember( 119 | 'MULTIPLE', 5, 'auto', 'Line spacing is specified as a multiple ' 120 | 'of line heights. Changing the font size will change the line sp' 121 | 'acing proportionately.' 122 | ), 123 | EnumMember( 124 | 'SINGLE', 0, 'Single spaced (default).' 125 | ), 126 | ) 127 | 128 | 129 | class WD_UNDERLINE(XmlEnumeration): 130 | """ 131 | Specifies the style of underline applied to a run of characters. 132 | """ 133 | 134 | __ms_name__ = 'WdUnderline' 135 | 136 | __url__ = 'http://msdn.microsoft.com/en-us/library/office/ff822388.aspx' 137 | 138 | __members__ = ( 139 | XmlMappedEnumMember( 140 | None, None, None, 'Inherit underline setting from containing par' 141 | 'agraph.' 142 | ), 143 | XmlMappedEnumMember( 144 | 'NONE', 0, 'none', 'No underline. This setting overrides any inh' 145 | 'erited underline value, so can be used to remove underline from' 146 | ' a run that inherits underlining from its containing paragraph.' 147 | ' Note this is not the same as assigning |None| to Run.underline' 148 | '. |None| is a valid assignment value, but causes the run to inh' 149 | 'erit its underline value. Assigning ``WD_UNDERLINE.NONE`` cause' 150 | 's underlining to be unconditionally turned off.' 151 | ), 152 | XmlMappedEnumMember( 153 | 'SINGLE', 1, 'single', 'A single line. Note that this setting is' 154 | 'write-only in the sense that |True| (rather than ``WD_UNDERLINE' 155 | '.SINGLE``) is returned for a run having this setting.' 156 | ), 157 | XmlMappedEnumMember( 158 | 'WORDS', 2, 'words', 'Underline individual words only.' 159 | ), 160 | XmlMappedEnumMember( 161 | 'DOUBLE', 3, 'double', 'A double line.' 162 | ), 163 | XmlMappedEnumMember( 164 | 'DOTTED', 4, 'dotted', 'Dots.' 165 | ), 166 | XmlMappedEnumMember( 167 | 'THICK', 6, 'thick', 'A single thick line.' 168 | ), 169 | XmlMappedEnumMember( 170 | 'DASH', 7, 'dash', 'Dashes.' 171 | ), 172 | XmlMappedEnumMember( 173 | 'DOT_DASH', 9, 'dotDash', 'Alternating dots and dashes.' 174 | ), 175 | XmlMappedEnumMember( 176 | 'DOT_DOT_DASH', 10, 'dotDotDash', 'An alternating dot-dot-dash p' 177 | 'attern.' 178 | ), 179 | XmlMappedEnumMember( 180 | 'WAVY', 11, 'wave', 'A single wavy line.' 181 | ), 182 | XmlMappedEnumMember( 183 | 'DOTTED_HEAVY', 20, 'dottedHeavy', 'Heavy dots.' 184 | ), 185 | XmlMappedEnumMember( 186 | 'DASH_HEAVY', 23, 'dashedHeavy', 'Heavy dashes.' 187 | ), 188 | XmlMappedEnumMember( 189 | 'DOT_DASH_HEAVY', 25, 'dashDotHeavy', 'Alternating heavy dots an' 190 | 'd heavy dashes.' 191 | ), 192 | XmlMappedEnumMember( 193 | 'DOT_DOT_DASH_HEAVY', 26, 'dashDotDotHeavy', 'An alternating hea' 194 | 'vy dot-dot-dash pattern.' 195 | ), 196 | XmlMappedEnumMember( 197 | 'WAVY_HEAVY', 27, 'wavyHeavy', 'A heavy wavy line.' 198 | ), 199 | XmlMappedEnumMember( 200 | 'DASH_LONG', 39, 'dashLong', 'Long dashes.' 201 | ), 202 | XmlMappedEnumMember( 203 | 'WAVY_DOUBLE', 43, 'wavyDouble', 'A double wavy line.' 204 | ), 205 | XmlMappedEnumMember( 206 | 'DASH_LONG_HEAVY', 55, 'dashLongHeavy', 'Long heavy dashes.' 207 | ), 208 | ) 209 | -------------------------------------------------------------------------------- /Python/NoteTaker/docx/exceptions.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | """ 4 | Exceptions used with python-docx. 5 | 6 | The base exception class is PythonDocxError. 7 | """ 8 | 9 | 10 | class PythonDocxError(Exception): 11 | """ 12 | Generic error class. 13 | """ 14 | 15 | 16 | class InvalidSpanError(PythonDocxError): 17 | """ 18 | Raised when an invalid merge region is specified in a request to merge 19 | table cells. 20 | """ 21 | 22 | 23 | class InvalidXmlError(PythonDocxError): 24 | """ 25 | Raised when invalid XML is encountered, such as on attempt to access a 26 | missing required child element 27 | """ 28 | -------------------------------------------------------------------------------- /Python/NoteTaker/docx/image/__init__.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | """ 4 | Provides objects that can characterize image streams as to content type and 5 | size, as a required step in including them in a document. 6 | """ 7 | 8 | from __future__ import ( 9 | absolute_import, division, print_function, unicode_literals 10 | ) 11 | 12 | from docx.image.bmp import Bmp 13 | from docx.image.gif import Gif 14 | from docx.image.jpeg import Exif, Jfif 15 | from docx.image.png import Png 16 | from docx.image.tiff import Tiff 17 | 18 | 19 | SIGNATURES = ( 20 | # class, offset, signature_bytes 21 | (Png, 0, b'\x89PNG\x0D\x0A\x1A\x0A'), 22 | (Jfif, 6, b'JFIF'), 23 | (Exif, 6, b'Exif'), 24 | (Gif, 0, b'GIF87a'), 25 | (Gif, 0, b'GIF89a'), 26 | (Tiff, 0, b'MM\x00*'), # big-endian (Motorola) TIFF 27 | (Tiff, 0, b'II*\x00'), # little-endian (Intel) TIFF 28 | (Bmp, 0, b'BM'), 29 | ) 30 | -------------------------------------------------------------------------------- /Python/NoteTaker/docx/image/bmp.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | from __future__ import absolute_import, division, print_function 4 | 5 | from .constants import MIME_TYPE 6 | from .helpers import LITTLE_ENDIAN, StreamReader 7 | from .image import BaseImageHeader 8 | 9 | 10 | class Bmp(BaseImageHeader): 11 | """ 12 | Image header parser for BMP images 13 | """ 14 | @classmethod 15 | def from_stream(cls, stream): 16 | """ 17 | Return |Bmp| instance having header properties parsed from the BMP 18 | image in *stream*. 19 | """ 20 | stream_rdr = StreamReader(stream, LITTLE_ENDIAN) 21 | 22 | px_width = stream_rdr.read_long(0x12) 23 | px_height = stream_rdr.read_long(0x16) 24 | 25 | horz_px_per_meter = stream_rdr.read_long(0x26) 26 | vert_px_per_meter = stream_rdr.read_long(0x2A) 27 | 28 | horz_dpi = cls._dpi(horz_px_per_meter) 29 | vert_dpi = cls._dpi(vert_px_per_meter) 30 | 31 | return cls(px_width, px_height, horz_dpi, vert_dpi) 32 | 33 | @property 34 | def content_type(self): 35 | """ 36 | MIME content type for this image, unconditionally `image/bmp` for 37 | BMP images. 38 | """ 39 | return MIME_TYPE.BMP 40 | 41 | @property 42 | def default_ext(self): 43 | """ 44 | Default filename extension, always 'bmp' for BMP images. 45 | """ 46 | return 'bmp' 47 | 48 | @staticmethod 49 | def _dpi(px_per_meter): 50 | """ 51 | Return the integer pixels per inch from *px_per_meter*, defaulting to 52 | 96 if *px_per_meter* is zero. 53 | """ 54 | if px_per_meter == 0: 55 | return 96 56 | return int(round(px_per_meter * 0.0254)) 57 | -------------------------------------------------------------------------------- /Python/NoteTaker/docx/image/constants.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | """ 4 | Constants specific the the image sub-package 5 | """ 6 | 7 | 8 | class JPEG_MARKER_CODE(object): 9 | """ 10 | JPEG marker codes 11 | """ 12 | TEM = b'\x01' 13 | DHT = b'\xC4' 14 | DAC = b'\xCC' 15 | JPG = b'\xC8' 16 | 17 | SOF0 = b'\xC0' 18 | SOF1 = b'\xC1' 19 | SOF2 = b'\xC2' 20 | SOF3 = b'\xC3' 21 | SOF5 = b'\xC5' 22 | SOF6 = b'\xC6' 23 | SOF7 = b'\xC7' 24 | SOF9 = b'\xC9' 25 | SOFA = b'\xCA' 26 | SOFB = b'\xCB' 27 | SOFD = b'\xCD' 28 | SOFE = b'\xCE' 29 | SOFF = b'\xCF' 30 | 31 | RST0 = b'\xD0' 32 | RST1 = b'\xD1' 33 | RST2 = b'\xD2' 34 | RST3 = b'\xD3' 35 | RST4 = b'\xD4' 36 | RST5 = b'\xD5' 37 | RST6 = b'\xD6' 38 | RST7 = b'\xD7' 39 | 40 | SOI = b'\xD8' 41 | EOI = b'\xD9' 42 | SOS = b'\xDA' 43 | DQT = b'\xDB' # Define Quantization Table(s) 44 | DNL = b'\xDC' 45 | DRI = b'\xDD' 46 | DHP = b'\xDE' 47 | EXP = b'\xDF' 48 | 49 | APP0 = b'\xE0' 50 | APP1 = b'\xE1' 51 | APP2 = b'\xE2' 52 | APP3 = b'\xE3' 53 | APP4 = b'\xE4' 54 | APP5 = b'\xE5' 55 | APP6 = b'\xE6' 56 | APP7 = b'\xE7' 57 | APP8 = b'\xE8' 58 | APP9 = b'\xE9' 59 | APPA = b'\xEA' 60 | APPB = b'\xEB' 61 | APPC = b'\xEC' 62 | APPD = b'\xED' 63 | APPE = b'\xEE' 64 | APPF = b'\xEF' 65 | 66 | STANDALONE_MARKERS = ( 67 | TEM, SOI, EOI, RST0, RST1, RST2, RST3, RST4, RST5, RST6, RST7 68 | ) 69 | 70 | SOF_MARKER_CODES = ( 71 | SOF0, SOF1, SOF2, SOF3, SOF5, SOF6, SOF7, SOF9, SOFA, SOFB, SOFD, 72 | SOFE, SOFF 73 | ) 74 | 75 | marker_names = { 76 | b'\x00': 'UNKNOWN', 77 | b'\xC0': 'SOF0', 78 | b'\xC2': 'SOF2', 79 | b'\xC4': 'DHT', 80 | b'\xDA': 'SOS', # start of scan 81 | b'\xD8': 'SOI', # start of image 82 | b'\xD9': 'EOI', # end of image 83 | b'\xDB': 'DQT', 84 | b'\xE0': 'APP0', 85 | b'\xE1': 'APP1', 86 | b'\xE2': 'APP2', 87 | b'\xED': 'APP13', 88 | b'\xEE': 'APP14', 89 | } 90 | 91 | @classmethod 92 | def is_standalone(cls, marker_code): 93 | return marker_code in cls.STANDALONE_MARKERS 94 | 95 | 96 | class MIME_TYPE(object): 97 | """ 98 | Image content types 99 | """ 100 | BMP = 'image/bmp' 101 | GIF = 'image/gif' 102 | JPEG = 'image/jpeg' 103 | PNG = 'image/png' 104 | TIFF = 'image/tiff' 105 | 106 | 107 | class PNG_CHUNK_TYPE(object): 108 | """ 109 | PNG chunk type names 110 | """ 111 | IHDR = 'IHDR' 112 | pHYs = 'pHYs' 113 | IEND = 'IEND' 114 | 115 | 116 | class TIFF_FLD_TYPE(object): 117 | """ 118 | Tag codes for TIFF Image File Directory (IFD) entries. 119 | """ 120 | BYTE = 1 121 | ASCII = 2 122 | SHORT = 3 123 | LONG = 4 124 | RATIONAL = 5 125 | 126 | field_type_names = { 127 | 1: 'BYTE', 2: 'ASCII char', 3: 'SHORT', 4: 'LONG', 128 | 5: 'RATIONAL' 129 | } 130 | 131 | 132 | TIFF_FLD = TIFF_FLD_TYPE 133 | 134 | 135 | class TIFF_TAG(object): 136 | """ 137 | Tag codes for TIFF Image File Directory (IFD) entries. 138 | """ 139 | IMAGE_WIDTH = 0x0100 140 | IMAGE_LENGTH = 0x0101 141 | X_RESOLUTION = 0x011A 142 | Y_RESOLUTION = 0x011B 143 | RESOLUTION_UNIT = 0x0128 144 | 145 | tag_names = { 146 | 0x00FE: 'NewSubfileType', 147 | 0x0100: 'ImageWidth', 148 | 0x0101: 'ImageLength', 149 | 0x0102: 'BitsPerSample', 150 | 0x0103: 'Compression', 151 | 0x0106: 'PhotometricInterpretation', 152 | 0x010E: 'ImageDescription', 153 | 0x010F: 'Make', 154 | 0x0110: 'Model', 155 | 0x0111: 'StripOffsets', 156 | 0x0112: 'Orientation', 157 | 0x0115: 'SamplesPerPixel', 158 | 0x0117: 'StripByteCounts', 159 | 0x011A: 'XResolution', 160 | 0x011B: 'YResolution', 161 | 0x011C: 'PlanarConfiguration', 162 | 0x0128: 'ResolutionUnit', 163 | 0x0131: 'Software', 164 | 0x0132: 'DateTime', 165 | 0x0213: 'YCbCrPositioning', 166 | 0x8769: 'ExifTag', 167 | 0x8825: 'GPS IFD', 168 | 0xC4A5: 'PrintImageMatching', 169 | } 170 | -------------------------------------------------------------------------------- /Python/NoteTaker/docx/image/exceptions.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | """ 4 | Exceptions specific the the image sub-package 5 | """ 6 | 7 | 8 | class InvalidImageStreamError(Exception): 9 | """ 10 | The recognized image stream appears to be corrupted 11 | """ 12 | 13 | 14 | class UnexpectedEndOfFileError(Exception): 15 | """ 16 | EOF was unexpectedly encountered while reading an image stream. 17 | """ 18 | 19 | 20 | class UnrecognizedImageError(Exception): 21 | """ 22 | The provided image stream could not be recognized. 23 | """ 24 | -------------------------------------------------------------------------------- /Python/NoteTaker/docx/image/gif.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | from __future__ import absolute_import, division, print_function 4 | 5 | from struct import Struct 6 | 7 | from .constants import MIME_TYPE 8 | from .image import BaseImageHeader 9 | 10 | 11 | class Gif(BaseImageHeader): 12 | """ 13 | Image header parser for GIF images. Note that the GIF format does not 14 | support resolution (DPI) information. Both horizontal and vertical DPI 15 | default to 72. 16 | """ 17 | @classmethod 18 | def from_stream(cls, stream): 19 | """ 20 | Return |Gif| instance having header properties parsed from GIF image 21 | in *stream*. 22 | """ 23 | px_width, px_height = cls._dimensions_from_stream(stream) 24 | return cls(px_width, px_height, 72, 72) 25 | 26 | @property 27 | def content_type(self): 28 | """ 29 | MIME content type for this image, unconditionally `image/gif` for 30 | GIF images. 31 | """ 32 | return MIME_TYPE.GIF 33 | 34 | @property 35 | def default_ext(self): 36 | """ 37 | Default filename extension, always 'gif' for GIF images. 38 | """ 39 | return 'gif' 40 | 41 | @classmethod 42 | def _dimensions_from_stream(cls, stream): 43 | stream.seek(6) 44 | bytes_ = stream.read(4) 45 | struct = Struct('L' 51 | return self._read_int(fmt, base, offset) 52 | 53 | def read_short(self, base, offset=0): 54 | """ 55 | Return the int value of the two bytes at the file position determined 56 | by *base* and *offset*, similarly to ``read_long()`` above. 57 | """ 58 | fmt = b'H' 59 | return self._read_int(fmt, base, offset) 60 | 61 | def read_str(self, char_count, base, offset=0): 62 | """ 63 | Return a string containing the *char_count* bytes at the file 64 | position determined by self._base_offset + *base* + *offset*. 65 | """ 66 | def str_struct(char_count): 67 | format_ = '%ds' % char_count 68 | return Struct(format_) 69 | struct = str_struct(char_count) 70 | chars = self._unpack_item(struct, base, offset) 71 | unicode_str = chars.decode('UTF-8') 72 | return unicode_str 73 | 74 | def seek(self, base, offset=0): 75 | location = self._base_offset + base + offset 76 | self._stream.seek(location) 77 | 78 | def tell(self): 79 | """ 80 | Allow pass-through tell() call 81 | """ 82 | return self._stream.tell() 83 | 84 | def _read_bytes(self, byte_count, base, offset): 85 | self.seek(base, offset) 86 | bytes_ = self._stream.read(byte_count) 87 | if len(bytes_) < byte_count: 88 | raise UnexpectedEndOfFileError 89 | return bytes_ 90 | 91 | def _read_int(self, fmt, base, offset): 92 | struct = Struct(fmt) 93 | return self._unpack_item(struct, base, offset) 94 | 95 | def _unpack_item(self, struct, base, offset): 96 | bytes_ = self._read_bytes(struct.size, base, offset) 97 | return struct.unpack(bytes_)[0] 98 | -------------------------------------------------------------------------------- /Python/NoteTaker/docx/opc/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsouzarc/dotfiles/f771532b0f512efcefa3dc0ede31deceaf0e9acc/Python/NoteTaker/docx/opc/__init__.py -------------------------------------------------------------------------------- /Python/NoteTaker/docx/opc/compat.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | """ 4 | Provides Python 2/3 compatibility objects 5 | """ 6 | 7 | from __future__ import ( 8 | absolute_import, division, print_function, unicode_literals 9 | ) 10 | 11 | import sys 12 | 13 | # =========================================================================== 14 | # Python 3 versions 15 | # =========================================================================== 16 | 17 | if sys.version_info >= (3, 0): 18 | 19 | def cls_method_fn(cls, method_name): 20 | """ 21 | Return the function object associated with the method of *cls* having 22 | *method_name*. 23 | """ 24 | return getattr(cls, method_name) 25 | 26 | def is_string(obj): 27 | """ 28 | Return True if *obj* is a string, False otherwise. 29 | """ 30 | return isinstance(obj, str) 31 | 32 | # =========================================================================== 33 | # Python 2 versions 34 | # =========================================================================== 35 | 36 | else: 37 | 38 | def cls_method_fn(cls, method_name): 39 | """ 40 | Return the function object associated with the method of *cls* having 41 | *method_name*. 42 | """ 43 | unbound_method = getattr(cls, method_name) 44 | return unbound_method.__func__ 45 | 46 | def is_string(obj): 47 | """ 48 | Return True if *obj* is a string, False otherwise. 49 | """ 50 | return isinstance(obj, basestring) 51 | -------------------------------------------------------------------------------- /Python/NoteTaker/docx/opc/coreprops.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | """ 4 | The :mod:`pptx.packaging` module coheres around the concerns of reading and 5 | writing presentations to and from a .pptx file. 6 | """ 7 | 8 | from __future__ import ( 9 | absolute_import, division, print_function, unicode_literals 10 | ) 11 | 12 | 13 | class CoreProperties(object): 14 | """ 15 | Corresponds to part named ``/docProps/core.xml``, containing the core 16 | document properties for this document package. 17 | """ 18 | def __init__(self, element): 19 | self._element = element 20 | 21 | @property 22 | def author(self): 23 | return self._element.author_text 24 | 25 | @author.setter 26 | def author(self, value): 27 | self._element.author_text = value 28 | 29 | @property 30 | def category(self): 31 | return self._element.category_text 32 | 33 | @category.setter 34 | def category(self, value): 35 | self._element.category_text = value 36 | 37 | @property 38 | def comments(self): 39 | return self._element.comments_text 40 | 41 | @comments.setter 42 | def comments(self, value): 43 | self._element.comments_text = value 44 | 45 | @property 46 | def content_status(self): 47 | return self._element.contentStatus_text 48 | 49 | @content_status.setter 50 | def content_status(self, value): 51 | self._element.contentStatus_text = value 52 | 53 | @property 54 | def created(self): 55 | return self._element.created_datetime 56 | 57 | @created.setter 58 | def created(self, value): 59 | self._element.created_datetime = value 60 | 61 | @property 62 | def identifier(self): 63 | return self._element.identifier_text 64 | 65 | @identifier.setter 66 | def identifier(self, value): 67 | self._element.identifier_text = value 68 | 69 | @property 70 | def keywords(self): 71 | return self._element.keywords_text 72 | 73 | @keywords.setter 74 | def keywords(self, value): 75 | self._element.keywords_text = value 76 | 77 | @property 78 | def language(self): 79 | return self._element.language_text 80 | 81 | @language.setter 82 | def language(self, value): 83 | self._element.language_text = value 84 | 85 | @property 86 | def last_modified_by(self): 87 | return self._element.lastModifiedBy_text 88 | 89 | @last_modified_by.setter 90 | def last_modified_by(self, value): 91 | self._element.lastModifiedBy_text = value 92 | 93 | @property 94 | def last_printed(self): 95 | return self._element.lastPrinted_datetime 96 | 97 | @last_printed.setter 98 | def last_printed(self, value): 99 | self._element.lastPrinted_datetime = value 100 | 101 | @property 102 | def modified(self): 103 | return self._element.modified_datetime 104 | 105 | @modified.setter 106 | def modified(self, value): 107 | self._element.modified_datetime = value 108 | 109 | @property 110 | def revision(self): 111 | return self._element.revision_number 112 | 113 | @revision.setter 114 | def revision(self, value): 115 | self._element.revision_number = value 116 | 117 | @property 118 | def subject(self): 119 | return self._element.subject_text 120 | 121 | @subject.setter 122 | def subject(self, value): 123 | self._element.subject_text = value 124 | 125 | @property 126 | def title(self): 127 | return self._element.title_text 128 | 129 | @title.setter 130 | def title(self, value): 131 | self._element.title_text = value 132 | 133 | @property 134 | def version(self): 135 | return self._element.version_text 136 | 137 | @version.setter 138 | def version(self, value): 139 | self._element.version_text = value 140 | -------------------------------------------------------------------------------- /Python/NoteTaker/docx/opc/exceptions.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | """ 4 | Exceptions specific to python-opc 5 | 6 | The base exception class is OpcError. 7 | """ 8 | 9 | 10 | class OpcError(Exception): 11 | """ 12 | Base error class for python-opc 13 | """ 14 | 15 | 16 | class PackageNotFoundError(OpcError): 17 | """ 18 | Raised when a package cannot be found at the specified path. 19 | """ 20 | -------------------------------------------------------------------------------- /Python/NoteTaker/docx/opc/packuri.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | """ 4 | Provides the PackURI value type along with some useful known pack URI strings 5 | such as PACKAGE_URI. 6 | """ 7 | 8 | import posixpath 9 | import re 10 | 11 | 12 | class PackURI(str): 13 | """ 14 | Provides access to pack URI components such as the baseURI and the 15 | filename slice. Behaves as |str| otherwise. 16 | """ 17 | _filename_re = re.compile('([a-zA-Z]+)([1-9][0-9]*)?') 18 | 19 | def __new__(cls, pack_uri_str): 20 | if not pack_uri_str[0] == '/': 21 | tmpl = "PackURI must begin with slash, got '%s'" 22 | raise ValueError(tmpl % pack_uri_str) 23 | return str.__new__(cls, pack_uri_str) 24 | 25 | @staticmethod 26 | def from_rel_ref(baseURI, relative_ref): 27 | """ 28 | Return a |PackURI| instance containing the absolute pack URI formed by 29 | translating *relative_ref* onto *baseURI*. 30 | """ 31 | joined_uri = posixpath.join(baseURI, relative_ref) 32 | abs_uri = posixpath.abspath(joined_uri) 33 | return PackURI(abs_uri) 34 | 35 | @property 36 | def baseURI(self): 37 | """ 38 | The base URI of this pack URI, the directory portion, roughly 39 | speaking. E.g. ``'/ppt/slides'`` for ``'/ppt/slides/slide1.xml'``. 40 | For the package pseudo-partname '/', baseURI is '/'. 41 | """ 42 | return posixpath.split(self)[0] 43 | 44 | @property 45 | def ext(self): 46 | """ 47 | The extension portion of this pack URI, e.g. ``'xml'`` for 48 | ``'/word/document.xml'``. Note the period is not included. 49 | """ 50 | # raw_ext is either empty string or starts with period, e.g. '.xml' 51 | raw_ext = posixpath.splitext(self)[1] 52 | return raw_ext[1:] if raw_ext.startswith('.') else raw_ext 53 | 54 | @property 55 | def filename(self): 56 | """ 57 | The "filename" portion of this pack URI, e.g. ``'slide1.xml'`` for 58 | ``'/ppt/slides/slide1.xml'``. For the package pseudo-partname '/', 59 | filename is ''. 60 | """ 61 | return posixpath.split(self)[1] 62 | 63 | @property 64 | def idx(self): 65 | """ 66 | Return partname index as integer for tuple partname or None for 67 | singleton partname, e.g. ``21`` for ``'/ppt/slides/slide21.xml'`` and 68 | |None| for ``'/ppt/presentation.xml'``. 69 | """ 70 | filename = self.filename 71 | if not filename: 72 | return None 73 | name_part = posixpath.splitext(filename)[0] # filename w/ext removed 74 | match = self._filename_re.match(name_part) 75 | if match is None: 76 | return None 77 | if match.group(2): 78 | return int(match.group(2)) 79 | return None 80 | 81 | @property 82 | def membername(self): 83 | """ 84 | The pack URI with the leading slash stripped off, the form used as 85 | the Zip file membername for the package item. Returns '' for the 86 | package pseudo-partname '/'. 87 | """ 88 | return self[1:] 89 | 90 | def relative_ref(self, baseURI): 91 | """ 92 | Return string containing relative reference to package item from 93 | *baseURI*. E.g. PackURI('/ppt/slideLayouts/slideLayout1.xml') would 94 | return '../slideLayouts/slideLayout1.xml' for baseURI '/ppt/slides'. 95 | """ 96 | # workaround for posixpath bug in 2.6, doesn't generate correct 97 | # relative path when *start* (second) parameter is root ('/') 98 | if baseURI == '/': 99 | relpath = self[1:] 100 | else: 101 | relpath = posixpath.relpath(self, baseURI) 102 | return relpath 103 | 104 | @property 105 | def rels_uri(self): 106 | """ 107 | The pack URI of the .rels part corresponding to the current pack URI. 108 | Only produces sensible output if the pack URI is a partname or the 109 | package pseudo-partname '/'. 110 | """ 111 | rels_filename = '%s.rels' % self.filename 112 | rels_uri_str = posixpath.join(self.baseURI, '_rels', rels_filename) 113 | return PackURI(rels_uri_str) 114 | 115 | 116 | PACKAGE_URI = PackURI('/') 117 | CONTENT_TYPES_URI = PackURI('/[Content_Types].xml') 118 | -------------------------------------------------------------------------------- /Python/NoteTaker/docx/opc/parts/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsouzarc/dotfiles/f771532b0f512efcefa3dc0ede31deceaf0e9acc/Python/NoteTaker/docx/opc/parts/__init__.py -------------------------------------------------------------------------------- /Python/NoteTaker/docx/opc/parts/coreprops.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | """ 4 | Core properties part, corresponds to ``/docProps/core.xml`` part in package. 5 | """ 6 | 7 | from __future__ import ( 8 | absolute_import, division, print_function, unicode_literals 9 | ) 10 | 11 | from datetime import datetime 12 | 13 | from ..constants import CONTENT_TYPE as CT 14 | from ..coreprops import CoreProperties 15 | from ...oxml.coreprops import CT_CoreProperties 16 | from ..packuri import PackURI 17 | from ..part import XmlPart 18 | 19 | 20 | class CorePropertiesPart(XmlPart): 21 | """ 22 | Corresponds to part named ``/docProps/core.xml``, containing the core 23 | document properties for this document package. 24 | """ 25 | @classmethod 26 | def default(cls, package): 27 | """ 28 | Return a new |CorePropertiesPart| object initialized with default 29 | values for its base properties. 30 | """ 31 | core_properties_part = cls._new(package) 32 | core_properties = core_properties_part.core_properties 33 | core_properties.title = 'Word Document' 34 | core_properties.last_modified_by = 'python-docx' 35 | core_properties.revision = 1 36 | core_properties.modified = datetime.utcnow() 37 | return core_properties_part 38 | 39 | @property 40 | def core_properties(self): 41 | """ 42 | A |CoreProperties| object providing read/write access to the core 43 | properties contained in this core properties part. 44 | """ 45 | return CoreProperties(self.element) 46 | 47 | @classmethod 48 | def _new(cls, package): 49 | partname = PackURI('/docProps/core.xml') 50 | content_type = CT.OPC_CORE_PROPERTIES 51 | coreProperties = CT_CoreProperties.new() 52 | return CorePropertiesPart( 53 | partname, content_type, coreProperties, package 54 | ) 55 | -------------------------------------------------------------------------------- /Python/NoteTaker/docx/opc/phys_pkg.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | """ 4 | Provides a general interface to a *physical* OPC package, such as a zip file. 5 | """ 6 | 7 | from __future__ import absolute_import 8 | 9 | import os 10 | 11 | from zipfile import ZipFile, is_zipfile, ZIP_DEFLATED 12 | 13 | from .compat import is_string 14 | from .exceptions import PackageNotFoundError 15 | from .packuri import CONTENT_TYPES_URI 16 | 17 | 18 | class PhysPkgReader(object): 19 | """ 20 | Factory for physical package reader objects. 21 | """ 22 | def __new__(cls, pkg_file): 23 | # if *pkg_file* is a string, treat it as a path 24 | if is_string(pkg_file): 25 | if os.path.isdir(pkg_file): 26 | reader_cls = _DirPkgReader 27 | elif is_zipfile(pkg_file): 28 | reader_cls = _ZipPkgReader 29 | else: 30 | raise PackageNotFoundError( 31 | "Package not found at '%s'" % pkg_file 32 | ) 33 | else: # assume it's a stream and pass it to Zip reader to sort out 34 | reader_cls = _ZipPkgReader 35 | 36 | return super(PhysPkgReader, cls).__new__(reader_cls) 37 | 38 | 39 | class PhysPkgWriter(object): 40 | """ 41 | Factory for physical package writer objects. 42 | """ 43 | def __new__(cls, pkg_file): 44 | return super(PhysPkgWriter, cls).__new__(_ZipPkgWriter) 45 | 46 | 47 | class _DirPkgReader(PhysPkgReader): 48 | """ 49 | Implements |PhysPkgReader| interface for an OPC package extracted into a 50 | directory. 51 | """ 52 | def __init__(self, path): 53 | """ 54 | *path* is the path to a directory containing an expanded package. 55 | """ 56 | super(_DirPkgReader, self).__init__() 57 | self._path = os.path.abspath(path) 58 | 59 | def blob_for(self, pack_uri): 60 | """ 61 | Return contents of file corresponding to *pack_uri* in package 62 | directory. 63 | """ 64 | path = os.path.join(self._path, pack_uri.membername) 65 | with open(path, 'rb') as f: 66 | blob = f.read() 67 | return blob 68 | 69 | def close(self): 70 | """ 71 | Provides interface consistency with |ZipFileSystem|, but does 72 | nothing, a directory file system doesn't need closing. 73 | """ 74 | pass 75 | 76 | @property 77 | def content_types_xml(self): 78 | """ 79 | Return the `[Content_Types].xml` blob from the package. 80 | """ 81 | return self.blob_for(CONTENT_TYPES_URI) 82 | 83 | def rels_xml_for(self, source_uri): 84 | """ 85 | Return rels item XML for source with *source_uri*, or None if the 86 | item has no rels item. 87 | """ 88 | try: 89 | rels_xml = self.blob_for(source_uri.rels_uri) 90 | except IOError: 91 | rels_xml = None 92 | return rels_xml 93 | 94 | 95 | class _ZipPkgReader(PhysPkgReader): 96 | """ 97 | Implements |PhysPkgReader| interface for a zip file OPC package. 98 | """ 99 | def __init__(self, pkg_file): 100 | super(_ZipPkgReader, self).__init__() 101 | self._zipf = ZipFile(pkg_file, 'r') 102 | 103 | def blob_for(self, pack_uri): 104 | """ 105 | Return blob corresponding to *pack_uri*. Raises |ValueError| if no 106 | matching member is present in zip archive. 107 | """ 108 | return self._zipf.read(pack_uri.membername) 109 | 110 | def close(self): 111 | """ 112 | Close the zip archive, releasing any resources it is using. 113 | """ 114 | self._zipf.close() 115 | 116 | @property 117 | def content_types_xml(self): 118 | """ 119 | Return the `[Content_Types].xml` blob from the zip package. 120 | """ 121 | return self.blob_for(CONTENT_TYPES_URI) 122 | 123 | def rels_xml_for(self, source_uri): 124 | """ 125 | Return rels item XML for source with *source_uri* or None if no rels 126 | item is present. 127 | """ 128 | try: 129 | rels_xml = self.blob_for(source_uri.rels_uri) 130 | except KeyError: 131 | rels_xml = None 132 | return rels_xml 133 | 134 | 135 | class _ZipPkgWriter(PhysPkgWriter): 136 | """ 137 | Implements |PhysPkgWriter| interface for a zip file OPC package. 138 | """ 139 | def __init__(self, pkg_file): 140 | super(_ZipPkgWriter, self).__init__() 141 | self._zipf = ZipFile(pkg_file, 'w', compression=ZIP_DEFLATED) 142 | 143 | def close(self): 144 | """ 145 | Close the zip archive, flushing any pending physical writes and 146 | releasing any resources it's using. 147 | """ 148 | self._zipf.close() 149 | 150 | def write(self, pack_uri, blob): 151 | """ 152 | Write *blob* to this zip package with the membername corresponding to 153 | *pack_uri*. 154 | """ 155 | self._zipf.writestr(pack_uri.membername, blob) 156 | -------------------------------------------------------------------------------- /Python/NoteTaker/docx/opc/pkgwriter.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | """ 4 | Provides a low-level, write-only API to a serialized Open Packaging 5 | Convention (OPC) package, essentially an implementation of OpcPackage.save() 6 | """ 7 | 8 | from __future__ import absolute_import 9 | 10 | from .constants import CONTENT_TYPE as CT 11 | from .oxml import CT_Types, serialize_part_xml 12 | from .packuri import CONTENT_TYPES_URI, PACKAGE_URI 13 | from .phys_pkg import PhysPkgWriter 14 | from .shared import CaseInsensitiveDict 15 | from .spec import default_content_types 16 | 17 | 18 | class PackageWriter(object): 19 | """ 20 | Writes a zip-format OPC package to *pkg_file*, where *pkg_file* can be 21 | either a path to a zip file (a string) or a file-like object. Its single 22 | API method, :meth:`write`, is static, so this class is not intended to 23 | be instantiated. 24 | """ 25 | @staticmethod 26 | def write(pkg_file, pkg_rels, parts): 27 | """ 28 | Write a physical package (.pptx file) to *pkg_file* containing 29 | *pkg_rels* and *parts* and a content types stream based on the 30 | content types of the parts. 31 | """ 32 | phys_writer = PhysPkgWriter(pkg_file) 33 | PackageWriter._write_content_types_stream(phys_writer, parts) 34 | PackageWriter._write_pkg_rels(phys_writer, pkg_rels) 35 | PackageWriter._write_parts(phys_writer, parts) 36 | phys_writer.close() 37 | 38 | @staticmethod 39 | def _write_content_types_stream(phys_writer, parts): 40 | """ 41 | Write ``[Content_Types].xml`` part to the physical package with an 42 | appropriate content type lookup target for each part in *parts*. 43 | """ 44 | cti = _ContentTypesItem.from_parts(parts) 45 | phys_writer.write(CONTENT_TYPES_URI, cti.blob) 46 | 47 | @staticmethod 48 | def _write_parts(phys_writer, parts): 49 | """ 50 | Write the blob of each part in *parts* to the package, along with a 51 | rels item for its relationships if and only if it has any. 52 | """ 53 | for part in parts: 54 | phys_writer.write(part.partname, part.blob) 55 | if len(part._rels): 56 | phys_writer.write(part.partname.rels_uri, part._rels.xml) 57 | 58 | @staticmethod 59 | def _write_pkg_rels(phys_writer, pkg_rels): 60 | """ 61 | Write the XML rels item for *pkg_rels* ('/_rels/.rels') to the 62 | package. 63 | """ 64 | phys_writer.write(PACKAGE_URI.rels_uri, pkg_rels.xml) 65 | 66 | 67 | class _ContentTypesItem(object): 68 | """ 69 | Service class that composes a content types item ([Content_Types].xml) 70 | based on a list of parts. Not meant to be instantiated directly, its 71 | single interface method is xml_for(), e.g. 72 | ``_ContentTypesItem.xml_for(parts)``. 73 | """ 74 | def __init__(self): 75 | self._defaults = CaseInsensitiveDict() 76 | self._overrides = dict() 77 | 78 | @property 79 | def blob(self): 80 | """ 81 | Return XML form of this content types item, suitable for storage as 82 | ``[Content_Types].xml`` in an OPC package. 83 | """ 84 | return serialize_part_xml(self._element) 85 | 86 | @classmethod 87 | def from_parts(cls, parts): 88 | """ 89 | Return content types XML mapping each part in *parts* to the 90 | appropriate content type and suitable for storage as 91 | ``[Content_Types].xml`` in an OPC package. 92 | """ 93 | cti = cls() 94 | cti._defaults['rels'] = CT.OPC_RELATIONSHIPS 95 | cti._defaults['xml'] = CT.XML 96 | for part in parts: 97 | cti._add_content_type(part.partname, part.content_type) 98 | return cti 99 | 100 | def _add_content_type(self, partname, content_type): 101 | """ 102 | Add a content type for the part with *partname* and *content_type*, 103 | using a default or override as appropriate. 104 | """ 105 | ext = partname.ext 106 | if (ext.lower(), content_type) in default_content_types: 107 | self._defaults[ext] = content_type 108 | else: 109 | self._overrides[partname] = content_type 110 | 111 | @property 112 | def _element(self): 113 | """ 114 | Return XML form of this content types item, suitable for storage as 115 | ``[Content_Types].xml`` in an OPC package. Although the sequence of 116 | elements is not strictly significant, as an aid to testing and 117 | readability Default elements are sorted by extension and Override 118 | elements are sorted by partname. 119 | """ 120 | _types_elm = CT_Types.new() 121 | for ext in sorted(self._defaults.keys()): 122 | _types_elm.add_default(ext, self._defaults[ext]) 123 | for partname in sorted(self._overrides.keys()): 124 | _types_elm.add_override(partname, self._overrides[partname]) 125 | return _types_elm 126 | -------------------------------------------------------------------------------- /Python/NoteTaker/docx/opc/rel.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | """ 4 | Relationship-related objects. 5 | """ 6 | 7 | from __future__ import ( 8 | absolute_import, division, print_function, unicode_literals 9 | ) 10 | 11 | from .oxml import CT_Relationships 12 | 13 | 14 | class Relationships(dict): 15 | """ 16 | Collection object for |_Relationship| instances, having list semantics. 17 | """ 18 | def __init__(self, baseURI): 19 | super(Relationships, self).__init__() 20 | self._baseURI = baseURI 21 | self._target_parts_by_rId = {} 22 | 23 | def add_relationship(self, reltype, target, rId, is_external=False): 24 | """ 25 | Return a newly added |_Relationship| instance. 26 | """ 27 | rel = _Relationship(rId, reltype, target, self._baseURI, is_external) 28 | self[rId] = rel 29 | if not is_external: 30 | self._target_parts_by_rId[rId] = target 31 | return rel 32 | 33 | def get_or_add(self, reltype, target_part): 34 | """ 35 | Return relationship of *reltype* to *target_part*, newly added if not 36 | already present in collection. 37 | """ 38 | rel = self._get_matching(reltype, target_part) 39 | if rel is None: 40 | rId = self._next_rId 41 | rel = self.add_relationship(reltype, target_part, rId) 42 | return rel 43 | 44 | def get_or_add_ext_rel(self, reltype, target_ref): 45 | """ 46 | Return rId of external relationship of *reltype* to *target_ref*, 47 | newly added if not already present in collection. 48 | """ 49 | rel = self._get_matching(reltype, target_ref, is_external=True) 50 | if rel is None: 51 | rId = self._next_rId 52 | rel = self.add_relationship( 53 | reltype, target_ref, rId, is_external=True 54 | ) 55 | return rel.rId 56 | 57 | def part_with_reltype(self, reltype): 58 | """ 59 | Return target part of rel with matching *reltype*, raising |KeyError| 60 | if not found and |ValueError| if more than one matching relationship 61 | is found. 62 | """ 63 | rel = self._get_rel_of_type(reltype) 64 | return rel.target_part 65 | 66 | @property 67 | def related_parts(self): 68 | """ 69 | dict mapping rIds to target parts for all the internal relationships 70 | in the collection. 71 | """ 72 | return self._target_parts_by_rId 73 | 74 | @property 75 | def xml(self): 76 | """ 77 | Serialize this relationship collection into XML suitable for storage 78 | as a .rels file in an OPC package. 79 | """ 80 | rels_elm = CT_Relationships.new() 81 | for rel in self.values(): 82 | rels_elm.add_rel( 83 | rel.rId, rel.reltype, rel.target_ref, rel.is_external 84 | ) 85 | return rels_elm.xml 86 | 87 | def _get_matching(self, reltype, target, is_external=False): 88 | """ 89 | Return relationship of matching *reltype*, *target*, and 90 | *is_external* from collection, or None if not found. 91 | """ 92 | def matches(rel, reltype, target, is_external): 93 | if rel.reltype != reltype: 94 | return False 95 | if rel.is_external != is_external: 96 | return False 97 | rel_target = rel.target_ref if rel.is_external else rel.target_part 98 | if rel_target != target: 99 | return False 100 | return True 101 | 102 | for rel in self.values(): 103 | if matches(rel, reltype, target, is_external): 104 | return rel 105 | return None 106 | 107 | def _get_rel_of_type(self, reltype): 108 | """ 109 | Return single relationship of type *reltype* from the collection. 110 | Raises |KeyError| if no matching relationship is found. Raises 111 | |ValueError| if more than one matching relationship is found. 112 | """ 113 | matching = [rel for rel in self.values() if rel.reltype == reltype] 114 | if len(matching) == 0: 115 | tmpl = "no relationship of type '%s' in collection" 116 | raise KeyError(tmpl % reltype) 117 | if len(matching) > 1: 118 | tmpl = "multiple relationships of type '%s' in collection" 119 | raise ValueError(tmpl % reltype) 120 | return matching[0] 121 | 122 | @property 123 | def _next_rId(self): 124 | """ 125 | Next available rId in collection, starting from 'rId1' and making use 126 | of any gaps in numbering, e.g. 'rId2' for rIds ['rId1', 'rId3']. 127 | """ 128 | for n in range(1, len(self)+2): 129 | rId_candidate = 'rId%d' % n # like 'rId19' 130 | if rId_candidate not in self: 131 | return rId_candidate 132 | 133 | 134 | class _Relationship(object): 135 | """ 136 | Value object for relationship to part. 137 | """ 138 | def __init__(self, rId, reltype, target, baseURI, external=False): 139 | super(_Relationship, self).__init__() 140 | self._rId = rId 141 | self._reltype = reltype 142 | self._target = target 143 | self._baseURI = baseURI 144 | self._is_external = bool(external) 145 | 146 | @property 147 | def is_external(self): 148 | return self._is_external 149 | 150 | @property 151 | def reltype(self): 152 | return self._reltype 153 | 154 | @property 155 | def rId(self): 156 | return self._rId 157 | 158 | @property 159 | def target_part(self): 160 | if self._is_external: 161 | raise ValueError("target_part property on _Relationship is undef" 162 | "ined when target mode is External") 163 | return self._target 164 | 165 | @property 166 | def target_ref(self): 167 | if self._is_external: 168 | return self._target 169 | else: 170 | return self._target.partname.relative_ref(self._baseURI) 171 | -------------------------------------------------------------------------------- /Python/NoteTaker/docx/opc/shared.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | """ 4 | Objects shared by opc modules. 5 | """ 6 | 7 | from __future__ import absolute_import, print_function, unicode_literals 8 | 9 | 10 | class CaseInsensitiveDict(dict): 11 | """ 12 | Mapping type that behaves like dict except that it matches without respect 13 | to the case of the key. E.g. cid['A'] == cid['a']. Note this is not 14 | general-purpose, just complete enough to satisfy opc package needs. It 15 | assumes str keys, and that it is created empty; keys passed in constructor 16 | are not accounted for 17 | """ 18 | def __contains__(self, key): 19 | return super(CaseInsensitiveDict, self).__contains__(key.lower()) 20 | 21 | def __getitem__(self, key): 22 | return super(CaseInsensitiveDict, self).__getitem__(key.lower()) 23 | 24 | def __setitem__(self, key, value): 25 | return super(CaseInsensitiveDict, self).__setitem__( 26 | key.lower(), value 27 | ) 28 | 29 | 30 | def lazyproperty(f): 31 | """ 32 | @lazyprop decorator. Decorated method will be called only on first access 33 | to calculate a cached property value. After that, the cached value is 34 | returned. 35 | """ 36 | cache_attr_name = '_%s' % f.__name__ # like '_foobar' for prop 'foobar' 37 | docstring = f.__doc__ 38 | 39 | def get_prop_value(obj): 40 | try: 41 | return getattr(obj, cache_attr_name) 42 | except AttributeError: 43 | value = f(obj) 44 | setattr(obj, cache_attr_name, value) 45 | return value 46 | 47 | return property(get_prop_value, doc=docstring) 48 | -------------------------------------------------------------------------------- /Python/NoteTaker/docx/opc/spec.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | """ 4 | Provides mappings that embody aspects of the Open XML spec ISO/IEC 29500. 5 | """ 6 | 7 | from .constants import CONTENT_TYPE as CT 8 | 9 | 10 | default_content_types = ( 11 | ('bin', CT.PML_PRINTER_SETTINGS), 12 | ('bin', CT.SML_PRINTER_SETTINGS), 13 | ('bin', CT.WML_PRINTER_SETTINGS), 14 | ('bmp', CT.BMP), 15 | ('emf', CT.X_EMF), 16 | ('fntdata', CT.X_FONTDATA), 17 | ('gif', CT.GIF), 18 | ('jpe', CT.JPEG), 19 | ('jpeg', CT.JPEG), 20 | ('jpg', CT.JPEG), 21 | ('png', CT.PNG), 22 | ('rels', CT.OPC_RELATIONSHIPS), 23 | ('tif', CT.TIFF), 24 | ('tiff', CT.TIFF), 25 | ('wdp', CT.MS_PHOTO), 26 | ('wmf', CT.X_WMF), 27 | ('xlsx', CT.SML_SHEET), 28 | ('xml', CT.XML), 29 | ) 30 | -------------------------------------------------------------------------------- /Python/NoteTaker/docx/oxml/document.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | """ 4 | Custom element classes that correspond to the document part, e.g. 5 | . 6 | """ 7 | 8 | from .xmlchemy import BaseOxmlElement, ZeroOrOne, ZeroOrMore 9 | 10 | 11 | class CT_Document(BaseOxmlElement): 12 | """ 13 | ```` element, the root element of a document.xml file. 14 | """ 15 | body = ZeroOrOne('w:body') 16 | 17 | @property 18 | def sectPr_lst(self): 19 | """ 20 | Return a list containing a reference to each ```` element 21 | in the document, in the order encountered. 22 | """ 23 | return self.xpath('.//w:sectPr') 24 | 25 | 26 | class CT_Body(BaseOxmlElement): 27 | """ 28 | ````, the container element for the main document story in 29 | ``document.xml``. 30 | """ 31 | p = ZeroOrMore('w:p', successors=('w:sectPr',)) 32 | tbl = ZeroOrMore('w:tbl', successors=('w:sectPr',)) 33 | sectPr = ZeroOrOne('w:sectPr', successors=()) 34 | 35 | def add_section_break(self): 36 | """ 37 | Return the current ```` element after adding a clone of it 38 | in a new ```` element appended to the block content elements. 39 | Note that the "current" ```` will always be the sentinel 40 | sectPr in this case since we're always working at the end of the 41 | block content. 42 | """ 43 | sentinel_sectPr = self.get_or_add_sectPr() 44 | cloned_sectPr = sentinel_sectPr.clone() 45 | p = self.add_p() 46 | p.set_sectPr(cloned_sectPr) 47 | return sentinel_sectPr 48 | 49 | def clear_content(self): 50 | """ 51 | Remove all content child elements from this element. Leave 52 | the element if it is present. 53 | """ 54 | if self.sectPr is not None: 55 | content_elms = self[:-1] 56 | else: 57 | content_elms = self[:] 58 | for content_elm in content_elms: 59 | self.remove(content_elm) 60 | -------------------------------------------------------------------------------- /Python/NoteTaker/docx/oxml/exceptions.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | """ 4 | Exceptions for oxml sub-package 5 | """ 6 | 7 | 8 | class XmlchemyError(Exception): 9 | """Generic error class.""" 10 | 11 | 12 | class InvalidXmlError(XmlchemyError): 13 | """ 14 | Raised when invalid XML is encountered, such as on attempt to access a 15 | missing required child element 16 | """ 17 | -------------------------------------------------------------------------------- /Python/NoteTaker/docx/oxml/ns.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | """ 4 | Namespace-related objects. 5 | """ 6 | 7 | from __future__ import absolute_import, print_function, unicode_literals 8 | 9 | 10 | nsmap = { 11 | 'a': ('http://schemas.openxmlformats.org/drawingml/2006/main'), 12 | 'c': ('http://schemas.openxmlformats.org/drawingml/2006/chart'), 13 | 'cp': ('http://schemas.openxmlformats.org/package/2006/metadata/core-pr' 14 | 'operties'), 15 | 'dc': ('http://purl.org/dc/elements/1.1/'), 16 | 'dcmitype': ('http://purl.org/dc/dcmitype/'), 17 | 'dcterms': ('http://purl.org/dc/terms/'), 18 | 'dgm': ('http://schemas.openxmlformats.org/drawingml/2006/diagram'), 19 | 'pic': ('http://schemas.openxmlformats.org/drawingml/2006/picture'), 20 | 'r': ('http://schemas.openxmlformats.org/officeDocument/2006/relations' 21 | 'hips'), 22 | 'w': ('http://schemas.openxmlformats.org/wordprocessingml/2006/main'), 23 | 'wp': ('http://schemas.openxmlformats.org/drawingml/2006/wordprocessing' 24 | 'Drawing'), 25 | 'xml': ('http://www.w3.org/XML/1998/namespace'), 26 | 'xsi': ('http://www.w3.org/2001/XMLSchema-instance'), 27 | } 28 | 29 | pfxmap = dict((value, key) for key, value in nsmap.items()) 30 | 31 | 32 | class NamespacePrefixedTag(str): 33 | """ 34 | Value object that knows the semantics of an XML tag having a namespace 35 | prefix. 36 | """ 37 | def __new__(cls, nstag, *args): 38 | return super(NamespacePrefixedTag, cls).__new__(cls, nstag) 39 | 40 | def __init__(self, nstag): 41 | self._pfx, self._local_part = nstag.split(':') 42 | self._ns_uri = nsmap[self._pfx] 43 | 44 | @property 45 | def clark_name(self): 46 | return '{%s}%s' % (self._ns_uri, self._local_part) 47 | 48 | @classmethod 49 | def from_clark_name(cls, clark_name): 50 | nsuri, local_name = clark_name[1:].split('}') 51 | nstag = '%s:%s' % (pfxmap[nsuri], local_name) 52 | return cls(nstag) 53 | 54 | @property 55 | def local_part(self): 56 | """ 57 | Return the local part of the tag as a string. E.g. 'foobar' is 58 | returned for tag 'f:foobar'. 59 | """ 60 | return self._local_part 61 | 62 | @property 63 | def nsmap(self): 64 | """ 65 | Return a dict having a single member, mapping the namespace prefix of 66 | this tag to it's namespace name (e.g. {'f': 'http://foo/bar'}). This 67 | is handy for passing to xpath calls and other uses. 68 | """ 69 | return {self._pfx: self._ns_uri} 70 | 71 | @property 72 | def nspfx(self): 73 | """ 74 | Return the string namespace prefix for the tag, e.g. 'f' is returned 75 | for tag 'f:foobar'. 76 | """ 77 | return self._pfx 78 | 79 | @property 80 | def nsuri(self): 81 | """ 82 | Return the namespace URI for the tag, e.g. 'http://foo/bar' would be 83 | returned for tag 'f:foobar' if the 'f' prefix maps to 84 | 'http://foo/bar' in nsmap. 85 | """ 86 | return self._ns_uri 87 | 88 | 89 | def nsdecls(*prefixes): 90 | """ 91 | Return a string containing a namespace declaration for each of the 92 | namespace prefix strings, e.g. 'p', 'ct', passed as *prefixes*. 93 | """ 94 | return ' '.join(['xmlns:%s="%s"' % (pfx, nsmap[pfx]) for pfx in prefixes]) 95 | 96 | 97 | def nspfxmap(*nspfxs): 98 | """ 99 | Return a dict containing the subset namespace prefix mappings specified by 100 | *nspfxs*. Any number of namespace prefixes can be supplied, e.g. 101 | namespaces('a', 'r', 'p'). 102 | """ 103 | return dict((pfx, nsmap[pfx]) for pfx in nspfxs) 104 | 105 | 106 | def qn(tag): 107 | """ 108 | Stands for "qualified name", a utility function to turn a namespace 109 | prefixed tag name into a Clark-notation qualified tag name for lxml. For 110 | example, ``qn('p:cSld')`` returns ``'{http://schemas.../main}cSld'``. 111 | """ 112 | prefix, tagroot = tag.split(':') 113 | uri = nsmap[prefix] 114 | return '{%s}%s' % (uri, tagroot) 115 | -------------------------------------------------------------------------------- /Python/NoteTaker/docx/oxml/numbering.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | """ 4 | Custom element classes related to the numbering part 5 | """ 6 | 7 | from . import OxmlElement 8 | from .shared import CT_DecimalNumber 9 | from .simpletypes import ST_DecimalNumber 10 | from .xmlchemy import ( 11 | BaseOxmlElement, OneAndOnlyOne, RequiredAttribute, ZeroOrMore, ZeroOrOne 12 | ) 13 | 14 | 15 | class CT_Num(BaseOxmlElement): 16 | """ 17 | ```` element, which represents a concrete list definition 18 | instance, having a required child that references an 19 | abstract numbering definition that defines most of the formatting details. 20 | """ 21 | abstractNumId = OneAndOnlyOne('w:abstractNumId') 22 | lvlOverride = ZeroOrMore('w:lvlOverride') 23 | numId = RequiredAttribute('w:numId', ST_DecimalNumber) 24 | 25 | def add_lvlOverride(self, ilvl): 26 | """ 27 | Return a newly added CT_NumLvl () element having its 28 | ``ilvl`` attribute set to *ilvl*. 29 | """ 30 | return self._add_lvlOverride(ilvl=ilvl) 31 | 32 | @classmethod 33 | def new(cls, num_id, abstractNum_id): 34 | """ 35 | Return a new ```` element having numId of *num_id* and having 36 | a ```` child with val attribute set to 37 | *abstractNum_id*. 38 | """ 39 | num = OxmlElement('w:num') 40 | num.numId = num_id 41 | abstractNumId = CT_DecimalNumber.new( 42 | 'w:abstractNumId', abstractNum_id 43 | ) 44 | num.append(abstractNumId) 45 | return num 46 | 47 | 48 | class CT_NumLvl(BaseOxmlElement): 49 | """ 50 | ```` element, which identifies a level in a list 51 | definition to override with settings it contains. 52 | """ 53 | startOverride = ZeroOrOne('w:startOverride', successors=('w:lvl',)) 54 | ilvl = RequiredAttribute('w:ilvl', ST_DecimalNumber) 55 | 56 | def add_startOverride(self, val): 57 | """ 58 | Return a newly added CT_DecimalNumber element having tagname 59 | ``w:startOverride`` and ``val`` attribute set to *val*. 60 | """ 61 | return self._add_startOverride(val=val) 62 | 63 | 64 | class CT_NumPr(BaseOxmlElement): 65 | """ 66 | A ```` element, a container for numbering properties applied to 67 | a paragraph. 68 | """ 69 | ilvl = ZeroOrOne('w:ilvl', successors=( 70 | 'w:numId', 'w:numberingChange', 'w:ins' 71 | )) 72 | numId = ZeroOrOne('w:numId', successors=('w:numberingChange', 'w:ins')) 73 | 74 | # @ilvl.setter 75 | # def _set_ilvl(self, val): 76 | # """ 77 | # Get or add a child and set its ``w:val`` attribute to *val*. 78 | # """ 79 | # ilvl = self.get_or_add_ilvl() 80 | # ilvl.val = val 81 | 82 | # @numId.setter 83 | # def numId(self, val): 84 | # """ 85 | # Get or add a child and set its ``w:val`` attribute to 86 | # *val*. 87 | # """ 88 | # numId = self.get_or_add_numId() 89 | # numId.val = val 90 | 91 | 92 | class CT_Numbering(BaseOxmlElement): 93 | """ 94 | ```` element, the root element of a numbering part, i.e. 95 | numbering.xml 96 | """ 97 | num = ZeroOrMore('w:num', successors=('w:numIdMacAtCleanup',)) 98 | 99 | def add_num(self, abstractNum_id): 100 | """ 101 | Return a newly added CT_Num () element referencing the 102 | abstract numbering definition identified by *abstractNum_id*. 103 | """ 104 | next_num_id = self._next_numId 105 | num = CT_Num.new(next_num_id, abstractNum_id) 106 | return self._insert_num(num) 107 | 108 | def num_having_numId(self, numId): 109 | """ 110 | Return the ```` child element having ``numId`` attribute 111 | matching *numId*. 112 | """ 113 | xpath = './w:num[@w:numId="%d"]' % numId 114 | try: 115 | return self.xpath(xpath)[0] 116 | except IndexError: 117 | raise KeyError('no element with numId %d' % numId) 118 | 119 | @property 120 | def _next_numId(self): 121 | """ 122 | The first ``numId`` unused by a ```` element, starting at 123 | 1 and filling any gaps in numbering between existing ```` 124 | elements. 125 | """ 126 | numId_strs = self.xpath('./w:num/@w:numId') 127 | num_ids = [int(numId_str) for numId_str in numId_strs] 128 | for num in range(1, len(num_ids)+2): 129 | if num not in num_ids: 130 | break 131 | return num 132 | -------------------------------------------------------------------------------- /Python/NoteTaker/docx/oxml/shared.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | """ 4 | Objects shared by modules in the docx.oxml subpackage. 5 | """ 6 | 7 | from __future__ import absolute_import 8 | 9 | from . import OxmlElement 10 | from .ns import qn 11 | from .simpletypes import ST_DecimalNumber, ST_OnOff, ST_String 12 | from .xmlchemy import BaseOxmlElement, OptionalAttribute, RequiredAttribute 13 | 14 | 15 | class CT_DecimalNumber(BaseOxmlElement): 16 | """ 17 | Used for ````, ````, ```` and several 18 | others, containing a text representation of a decimal number (e.g. 42) in 19 | its ``val`` attribute. 20 | """ 21 | val = RequiredAttribute('w:val', ST_DecimalNumber) 22 | 23 | @classmethod 24 | def new(cls, nsptagname, val): 25 | """ 26 | Return a new ``CT_DecimalNumber`` element having tagname *nsptagname* 27 | and ``val`` attribute set to *val*. 28 | """ 29 | return OxmlElement(nsptagname, attrs={qn('w:val'): str(val)}) 30 | 31 | 32 | class CT_OnOff(BaseOxmlElement): 33 | """ 34 | Used for ````, ```` elements and others, containing a bool-ish 35 | string in its ``val`` attribute, xsd:boolean plus 'on' and 'off'. 36 | """ 37 | val = OptionalAttribute('w:val', ST_OnOff, default=True) 38 | 39 | 40 | class CT_String(BaseOxmlElement): 41 | """ 42 | Used for ```` and ```` elements and others, 43 | containing a style name in its ``val`` attribute. 44 | """ 45 | val = RequiredAttribute('w:val', ST_String) 46 | 47 | @classmethod 48 | def new(cls, nsptagname, val): 49 | """ 50 | Return a new ``CT_String`` element with tagname *nsptagname* and 51 | ``val`` attribute set to *val*. 52 | """ 53 | elm = OxmlElement(nsptagname) 54 | elm.val = val 55 | return elm 56 | -------------------------------------------------------------------------------- /Python/NoteTaker/docx/oxml/text/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsouzarc/dotfiles/f771532b0f512efcefa3dc0ede31deceaf0e9acc/Python/NoteTaker/docx/oxml/text/__init__.py -------------------------------------------------------------------------------- /Python/NoteTaker/docx/oxml/text/paragraph.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | """ 4 | Custom element classes related to paragraphs (CT_P). 5 | """ 6 | 7 | from ..ns import qn 8 | from ..xmlchemy import BaseOxmlElement, OxmlElement, ZeroOrMore, ZeroOrOne 9 | 10 | 11 | class CT_P(BaseOxmlElement): 12 | """ 13 | ```` element, containing the properties and text for a paragraph. 14 | """ 15 | pPr = ZeroOrOne('w:pPr') 16 | r = ZeroOrMore('w:r') 17 | 18 | def _insert_pPr(self, pPr): 19 | self.insert(0, pPr) 20 | return pPr 21 | 22 | def add_p_before(self): 23 | """ 24 | Return a new ```` element inserted directly prior to this one. 25 | """ 26 | new_p = OxmlElement('w:p') 27 | self.addprevious(new_p) 28 | return new_p 29 | 30 | @property 31 | def alignment(self): 32 | """ 33 | The value of the ```` grandchild element or |None| if not 34 | present. 35 | """ 36 | pPr = self.pPr 37 | if pPr is None: 38 | return None 39 | return pPr.jc_val 40 | 41 | @alignment.setter 42 | def alignment(self, value): 43 | pPr = self.get_or_add_pPr() 44 | pPr.jc_val = value 45 | 46 | def clear_content(self): 47 | """ 48 | Remove all child elements, except the ```` element if present. 49 | """ 50 | for child in self[:]: 51 | if child.tag == qn('w:pPr'): 52 | continue 53 | self.remove(child) 54 | 55 | def set_sectPr(self, sectPr): 56 | """ 57 | Unconditionally replace or add *sectPr* as a grandchild in the 58 | correct sequence. 59 | """ 60 | pPr = self.get_or_add_pPr() 61 | pPr._remove_sectPr() 62 | pPr._insert_sectPr(sectPr) 63 | 64 | @property 65 | def style(self): 66 | """ 67 | String contained in w:val attribute of ./w:pPr/w:pStyle grandchild, 68 | or |None| if not present. 69 | """ 70 | pPr = self.pPr 71 | if pPr is None: 72 | return None 73 | return pPr.style 74 | 75 | @style.setter 76 | def style(self, style): 77 | pPr = self.get_or_add_pPr() 78 | pPr.style = style 79 | -------------------------------------------------------------------------------- /Python/NoteTaker/docx/oxml/text/run.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | """ 4 | Custom element classes related to text runs (CT_R). 5 | """ 6 | 7 | from ..ns import qn 8 | from ..simpletypes import ST_BrClear, ST_BrType 9 | from ..xmlchemy import ( 10 | BaseOxmlElement, OptionalAttribute, ZeroOrMore, ZeroOrOne 11 | ) 12 | 13 | 14 | class CT_Br(BaseOxmlElement): 15 | """ 16 | ```` element, indicating a line, page, or column break in a run. 17 | """ 18 | type = OptionalAttribute('w:type', ST_BrType) 19 | clear = OptionalAttribute('w:clear', ST_BrClear) 20 | 21 | 22 | class CT_R(BaseOxmlElement): 23 | """ 24 | ```` element, containing the properties and text for a run. 25 | """ 26 | rPr = ZeroOrOne('w:rPr') 27 | t = ZeroOrMore('w:t') 28 | br = ZeroOrMore('w:br') 29 | cr = ZeroOrMore('w:cr') 30 | tab = ZeroOrMore('w:tab') 31 | drawing = ZeroOrMore('w:drawing') 32 | 33 | def _insert_rPr(self, rPr): 34 | self.insert(0, rPr) 35 | return rPr 36 | 37 | def add_t(self, text): 38 | """ 39 | Return a newly added ```` element containing *text*. 40 | """ 41 | t = self._add_t(text=text) 42 | if len(text.strip()) < len(text): 43 | t.set(qn('xml:space'), 'preserve') 44 | return t 45 | 46 | def add_drawing(self, inline_or_anchor): 47 | """ 48 | Return a newly appended ``CT_Drawing`` (````) child 49 | element having *inline_or_anchor* as its child. 50 | """ 51 | drawing = self._add_drawing() 52 | drawing.append(inline_or_anchor) 53 | return drawing 54 | 55 | def clear_content(self): 56 | """ 57 | Remove all child elements except the ```` element if present. 58 | """ 59 | content_child_elms = self[1:] if self.rPr is not None else self[:] 60 | for child in content_child_elms: 61 | self.remove(child) 62 | 63 | @property 64 | def style(self): 65 | """ 66 | String contained in w:val attribute of grandchild, or 67 | |None| if that element is not present. 68 | """ 69 | rPr = self.rPr 70 | if rPr is None: 71 | return None 72 | return rPr.style 73 | 74 | @style.setter 75 | def style(self, style): 76 | """ 77 | Set the character style of this element to *style*. If *style* 78 | is None, remove the style element. 79 | """ 80 | rPr = self.get_or_add_rPr() 81 | rPr.style = style 82 | 83 | @property 84 | def text(self): 85 | """ 86 | A string representing the textual content of this run, with content 87 | child elements like ```` translated to their Python 88 | equivalent. 89 | """ 90 | text = '' 91 | for child in self: 92 | if child.tag == qn('w:t'): 93 | t_text = child.text 94 | text += t_text if t_text is not None else '' 95 | elif child.tag == qn('w:tab'): 96 | text += '\t' 97 | elif child.tag in (qn('w:br'), qn('w:cr')): 98 | text += '\n' 99 | return text 100 | 101 | @text.setter 102 | def text(self, text): 103 | self.clear_content() 104 | _RunContentAppender.append_to_run_from_text(self, text) 105 | 106 | 107 | class CT_Text(BaseOxmlElement): 108 | """ 109 | ```` element, containing a sequence of characters within a run. 110 | """ 111 | 112 | 113 | class _RunContentAppender(object): 114 | """ 115 | Service object that knows how to translate a Python string into run 116 | content elements appended to a specified ```` element. Contiguous 117 | sequences of regular characters are appended in a single ```` 118 | element. Each tab character ('\t') causes a ```` element to be 119 | appended. Likewise a newline or carriage return character ('\n', '\r') 120 | causes a ```` element to be appended. 121 | """ 122 | def __init__(self, r): 123 | self._r = r 124 | self._bfr = [] 125 | 126 | @classmethod 127 | def append_to_run_from_text(cls, r, text): 128 | """ 129 | Create a "one-shot" ``_RunContentAppender`` instance and use it to 130 | append the run content elements corresponding to *text* to the 131 | ```` element *r*. 132 | """ 133 | appender = cls(r) 134 | appender.add_text(text) 135 | 136 | def add_text(self, text): 137 | """ 138 | Append the run content elements corresponding to *text* to the 139 | ```` element of this instance. 140 | """ 141 | for char in text: 142 | self.add_char(char) 143 | self.flush() 144 | 145 | def add_char(self, char): 146 | """ 147 | Process the next character of input through the translation finite 148 | state maching (FSM). There are two possible states, buffer pending 149 | and not pending, but those are hidden behind the ``.flush()`` method 150 | which must be called at the end of text to ensure any pending 151 | ```` element is written. 152 | """ 153 | if char == '\t': 154 | self.flush() 155 | self._r.add_tab() 156 | elif char in '\r\n': 157 | self.flush() 158 | self._r.add_br() 159 | else: 160 | self._bfr.append(char) 161 | 162 | def flush(self): 163 | text = ''.join(self._bfr) 164 | if text: 165 | self._r.add_t(text) 166 | del self._bfr[:] 167 | -------------------------------------------------------------------------------- /Python/NoteTaker/docx/package.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | """ 4 | WordprocessingML Package class and related objects 5 | """ 6 | 7 | from __future__ import absolute_import, print_function, unicode_literals 8 | 9 | from docx.image.image import Image 10 | from docx.opc.constants import RELATIONSHIP_TYPE as RT 11 | from docx.opc.package import OpcPackage 12 | from docx.opc.packuri import PackURI 13 | from docx.parts.image import ImagePart 14 | from docx.shared import lazyproperty 15 | 16 | 17 | class Package(OpcPackage): 18 | """ 19 | Customizations specific to a WordprocessingML package. 20 | """ 21 | def after_unmarshal(self): 22 | """ 23 | Called by loading code after all parts and relationships have been 24 | loaded, to afford the opportunity for any required post-processing. 25 | """ 26 | self._gather_image_parts() 27 | 28 | @lazyproperty 29 | def image_parts(self): 30 | """ 31 | Collection of all image parts in this package. 32 | """ 33 | return ImageParts() 34 | 35 | def _gather_image_parts(self): 36 | """ 37 | Load the image part collection with all the image parts in package. 38 | """ 39 | for rel in self.iter_rels(): 40 | if rel.is_external: 41 | continue 42 | if rel.reltype != RT.IMAGE: 43 | continue 44 | if rel.target_part in self.image_parts: 45 | continue 46 | self.image_parts.append(rel.target_part) 47 | 48 | 49 | class ImageParts(object): 50 | """ 51 | Collection of |ImagePart| instances corresponding to each image part in 52 | the package. 53 | """ 54 | def __init__(self): 55 | super(ImageParts, self).__init__() 56 | self._image_parts = [] 57 | 58 | def __contains__(self, item): 59 | return self._image_parts.__contains__(item) 60 | 61 | def __iter__(self): 62 | return self._image_parts.__iter__() 63 | 64 | def __len__(self): 65 | return self._image_parts.__len__() 66 | 67 | def append(self, item): 68 | self._image_parts.append(item) 69 | 70 | def get_or_add_image_part(self, image_descriptor): 71 | """ 72 | Return an |ImagePart| instance containing the image identified by 73 | *image_descriptor*, newly created if a matching one is not present in 74 | the collection. 75 | """ 76 | image = Image.from_file(image_descriptor) 77 | matching_image_part = self._get_by_sha1(image.sha1) 78 | if matching_image_part is not None: 79 | return matching_image_part 80 | return self._add_image_part(image) 81 | 82 | def _add_image_part(self, image): 83 | """ 84 | Return an |ImagePart| instance newly created from image and appended 85 | to the collection. 86 | """ 87 | partname = self._next_image_partname(image.ext) 88 | image_part = ImagePart.from_image(image, partname) 89 | self.append(image_part) 90 | return image_part 91 | 92 | def _get_by_sha1(self, sha1): 93 | """ 94 | Return the image part in this collection having a SHA1 hash matching 95 | *sha1*, or |None| if not found. 96 | """ 97 | for image_part in self._image_parts: 98 | if image_part.sha1 == sha1: 99 | return image_part 100 | return None 101 | 102 | def _next_image_partname(self, ext): 103 | """ 104 | The next available image partname, starting from 105 | ``/word/media/image1.{ext}`` where unused numbers are reused. The 106 | partname is unique by number, without regard to the extension. *ext* 107 | does not include the leading period. 108 | """ 109 | def image_partname(n): 110 | return PackURI('/word/media/image%d.%s' % (n, ext)) 111 | used_numbers = [image_part.partname.idx for image_part in self] 112 | for n in range(1, len(self)+1): 113 | if n not in used_numbers: 114 | return image_partname(n) 115 | return image_partname(len(self)+1) 116 | -------------------------------------------------------------------------------- /Python/NoteTaker/docx/parts/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsouzarc/dotfiles/f771532b0f512efcefa3dc0ede31deceaf0e9acc/Python/NoteTaker/docx/parts/__init__.py -------------------------------------------------------------------------------- /Python/NoteTaker/docx/parts/document.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | """ 4 | |DocumentPart| and closely related objects 5 | """ 6 | 7 | from __future__ import ( 8 | absolute_import, division, print_function, unicode_literals 9 | ) 10 | 11 | from ..document import Document 12 | from .numbering import NumberingPart 13 | from ..opc.constants import RELATIONSHIP_TYPE as RT 14 | from ..opc.part import XmlPart 15 | from ..oxml.shape import CT_Inline 16 | from ..shape import InlineShapes 17 | from ..shared import lazyproperty 18 | from .styles import StylesPart 19 | 20 | 21 | class DocumentPart(XmlPart): 22 | """ 23 | Main document part of a WordprocessingML (WML) package, aka a .docx file. 24 | Acts as broker to other parts such as image, core properties, and style 25 | parts. It also acts as a convenient delegate when a mid-document object 26 | needs a service involving a remote ancestor. The `Parented.part` property 27 | inherited by many content objects provides access to this part object for 28 | that purpose. 29 | """ 30 | @property 31 | def core_properties(self): 32 | """ 33 | A |CoreProperties| object providing read/write access to the core 34 | properties of this document. 35 | """ 36 | return self.package.core_properties 37 | 38 | @property 39 | def document(self): 40 | """ 41 | A |Document| object providing access to the content of this document. 42 | """ 43 | return Document(self._element, self) 44 | 45 | def get_or_add_image(self, image_descriptor): 46 | """ 47 | Return an (rId, image) 2-tuple for the image identified by 48 | *image_descriptor*. *image* is an |Image| instance providing access 49 | to the properties of the image, such as dimensions and image type. 50 | *rId* is the key for the relationship between this document part and 51 | the image part, reused if already present, newly created if not. 52 | """ 53 | image_part = self._package.image_parts.get_or_add_image_part( 54 | image_descriptor 55 | ) 56 | rId = self.relate_to(image_part, RT.IMAGE) 57 | return rId, image_part.image 58 | 59 | def get_style(self, style_id, style_type): 60 | """ 61 | Return the style in this document matching *style_id*. Returns the 62 | default style for *style_type* if *style_id* is |None| or does not 63 | match a defined style of *style_type*. 64 | """ 65 | return self.styles.get_by_id(style_id, style_type) 66 | 67 | def get_style_id(self, style_or_name, style_type): 68 | """ 69 | Return the style_id (|str|) of the style of *style_type* matching 70 | *style_or_name*. Returns |None| if the style resolves to the default 71 | style for *style_type* or if *style_or_name* is itself |None|. Raises 72 | if *style_or_name* is a style of the wrong type or names a style not 73 | present in the document. 74 | """ 75 | return self.styles.get_style_id(style_or_name, style_type) 76 | 77 | @lazyproperty 78 | def inline_shapes(self): 79 | """ 80 | The |InlineShapes| instance containing the inline shapes in the 81 | document. 82 | """ 83 | return InlineShapes(self._element.body, self) 84 | 85 | def new_pic_inline(self, image_descriptor, width, height): 86 | """ 87 | Return a newly-created `w:inline` element containing the image 88 | specified by *image_descriptor* and scaled based on the values of 89 | *width* and *height*. 90 | """ 91 | rId, image = self.get_or_add_image(image_descriptor) 92 | cx, cy = image.scaled_dimensions(width, height) 93 | shape_id, filename = self.next_id, image.filename 94 | return CT_Inline.new_pic_inline(shape_id, rId, filename, cx, cy) 95 | 96 | @property 97 | def next_id(self): 98 | """ 99 | The next available positive integer id value in this document. Gaps 100 | in id sequence are filled. The id attribute value is unique in the 101 | document, without regard to the element type it appears on. 102 | """ 103 | id_str_lst = self._element.xpath('//@id') 104 | used_ids = [int(id_str) for id_str in id_str_lst if id_str.isdigit()] 105 | for n in range(1, len(used_ids)+2): 106 | if n not in used_ids: 107 | return n 108 | 109 | @lazyproperty 110 | def numbering_part(self): 111 | """ 112 | A |NumberingPart| object providing access to the numbering 113 | definitions for this document. Creates an empty numbering part if one 114 | is not present. 115 | """ 116 | try: 117 | return self.part_related_by(RT.NUMBERING) 118 | except KeyError: 119 | numbering_part = NumberingPart.new() 120 | self.relate_to(numbering_part, RT.NUMBERING) 121 | return numbering_part 122 | 123 | def save(self, path_or_stream): 124 | """ 125 | Save this document to *path_or_stream*, which can be either a path to 126 | a filesystem location (a string) or a file-like object. 127 | """ 128 | self.package.save(path_or_stream) 129 | 130 | @property 131 | def styles(self): 132 | """ 133 | A |Styles| object providing access to the styles in the styles part 134 | of this document. 135 | """ 136 | return self._styles_part.styles 137 | 138 | @property 139 | def _styles_part(self): 140 | """ 141 | Instance of |StylesPart| for this document. Creates an empty styles 142 | part if one is not present. 143 | """ 144 | try: 145 | return self.part_related_by(RT.STYLES) 146 | except KeyError: 147 | styles_part = StylesPart.default(self.package) 148 | self.relate_to(styles_part, RT.STYLES) 149 | return styles_part 150 | -------------------------------------------------------------------------------- /Python/NoteTaker/docx/parts/image.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | """ 4 | The proxy class for an image part, and related objects. 5 | """ 6 | 7 | from __future__ import ( 8 | absolute_import, division, print_function, unicode_literals 9 | ) 10 | 11 | import hashlib 12 | 13 | from docx.image.image import Image 14 | from docx.opc.part import Part 15 | from docx.shared import Emu, Inches 16 | 17 | 18 | class ImagePart(Part): 19 | """ 20 | An image part. Corresponds to the target part of a relationship with type 21 | RELATIONSHIP_TYPE.IMAGE. 22 | """ 23 | def __init__(self, partname, content_type, blob, image=None): 24 | super(ImagePart, self).__init__(partname, content_type, blob) 25 | self._image = image 26 | 27 | @property 28 | def default_cx(self): 29 | """ 30 | Native width of this image, calculated from its width in pixels and 31 | horizontal dots per inch (dpi). 32 | """ 33 | px_width = self.image.px_width 34 | horz_dpi = self.image.horz_dpi 35 | width_in_inches = px_width / horz_dpi 36 | return Inches(width_in_inches) 37 | 38 | @property 39 | def default_cy(self): 40 | """ 41 | Native height of this image, calculated from its height in pixels and 42 | vertical dots per inch (dpi). 43 | """ 44 | px_height = self.image.px_height 45 | horz_dpi = self.image.horz_dpi 46 | height_in_emu = 914400 * px_height / horz_dpi 47 | return Emu(height_in_emu) 48 | 49 | @property 50 | def filename(self): 51 | """ 52 | Filename from which this image part was originally created. A generic 53 | name, e.g. 'image.png', is substituted if no name is available, for 54 | example when the image was loaded from an unnamed stream. In that 55 | case a default extension is applied based on the detected MIME type 56 | of the image. 57 | """ 58 | if self._image is not None: 59 | return self._image.filename 60 | return 'image.%s' % self.partname.ext 61 | 62 | @classmethod 63 | def from_image(cls, image, partname): 64 | """ 65 | Return an |ImagePart| instance newly created from *image* and 66 | assigned *partname*. 67 | """ 68 | return ImagePart(partname, image.content_type, image.blob, image) 69 | 70 | @property 71 | def image(self): 72 | if self._image is None: 73 | self._image = Image.from_blob(self.blob) 74 | return self._image 75 | 76 | @classmethod 77 | def load(cls, partname, content_type, blob, package): 78 | """ 79 | Called by ``docx.opc.package.PartFactory`` to load an image part from 80 | a package being opened by ``Document(...)`` call. 81 | """ 82 | return cls(partname, content_type, blob) 83 | 84 | @property 85 | def sha1(self): 86 | """ 87 | SHA1 hash digest of the blob of this image part. 88 | """ 89 | return hashlib.sha1(self._blob).hexdigest() 90 | -------------------------------------------------------------------------------- /Python/NoteTaker/docx/parts/numbering.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | """ 4 | |NumberingPart| and closely related objects 5 | """ 6 | 7 | from __future__ import ( 8 | absolute_import, division, print_function, unicode_literals 9 | ) 10 | 11 | from ..opc.part import XmlPart 12 | from ..shared import lazyproperty 13 | 14 | 15 | class NumberingPart(XmlPart): 16 | """ 17 | Proxy for the numbering.xml part containing numbering definitions for 18 | a document or glossary. 19 | """ 20 | @classmethod 21 | def new(cls): 22 | """ 23 | Return newly created empty numbering part, containing only the root 24 | ```` element. 25 | """ 26 | raise NotImplementedError 27 | 28 | @lazyproperty 29 | def numbering_definitions(self): 30 | """ 31 | The |_NumberingDefinitions| instance containing the numbering 32 | definitions ( element proxies) for this numbering part. 33 | """ 34 | return _NumberingDefinitions(self._element) 35 | 36 | 37 | class _NumberingDefinitions(object): 38 | """ 39 | Collection of |_NumberingDefinition| instances corresponding to the 40 | ```` elements in a numbering part. 41 | """ 42 | def __init__(self, numbering_elm): 43 | super(_NumberingDefinitions, self).__init__() 44 | self._numbering = numbering_elm 45 | 46 | def __len__(self): 47 | return len(self._numbering.num_lst) 48 | -------------------------------------------------------------------------------- /Python/NoteTaker/docx/parts/styles.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | """ 4 | Provides StylesPart and related objects 5 | """ 6 | 7 | from __future__ import ( 8 | absolute_import, division, print_function, unicode_literals 9 | ) 10 | 11 | import os 12 | 13 | from ..opc.constants import CONTENT_TYPE as CT 14 | from ..opc.packuri import PackURI 15 | from ..opc.part import XmlPart 16 | from ..oxml import parse_xml 17 | from ..styles.styles import Styles 18 | 19 | 20 | class StylesPart(XmlPart): 21 | """ 22 | Proxy for the styles.xml part containing style definitions for a document 23 | or glossary. 24 | """ 25 | @classmethod 26 | def default(cls, package): 27 | """ 28 | Return a newly created styles part, containing a default set of 29 | elements. 30 | """ 31 | partname = PackURI('/word/styles.xml') 32 | content_type = CT.WML_STYLES 33 | element = parse_xml(cls._default_styles_xml()) 34 | return cls(partname, content_type, element, package) 35 | 36 | @property 37 | def styles(self): 38 | """ 39 | The |_Styles| instance containing the styles ( element 40 | proxies) for this styles part. 41 | """ 42 | return Styles(self.element) 43 | 44 | @classmethod 45 | def _default_styles_xml(cls): 46 | """ 47 | Return a bytestream containing XML for a default styles part. 48 | """ 49 | path = os.path.join( 50 | os.path.split(__file__)[0], '..', 'templates', 51 | 'default-styles.xml' 52 | ) 53 | with open(path, 'rb') as f: 54 | xml_bytes = f.read() 55 | return xml_bytes 56 | -------------------------------------------------------------------------------- /Python/NoteTaker/docx/section.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | """ 4 | The |Section| object and related proxy classes. 5 | """ 6 | 7 | from __future__ import absolute_import, print_function, unicode_literals 8 | 9 | from collections import Sequence 10 | 11 | 12 | class Sections(Sequence): 13 | """ 14 | Sequence of |Section| objects corresponding to the sections in the 15 | document. Supports ``len()``, iteration, and indexed access. 16 | """ 17 | def __init__(self, document_elm): 18 | super(Sections, self).__init__() 19 | self._document_elm = document_elm 20 | 21 | def __getitem__(self, key): 22 | if isinstance(key, slice): 23 | sectPr_lst = self._document_elm.sectPr_lst[key] 24 | return [Section(sectPr) for sectPr in sectPr_lst] 25 | sectPr = self._document_elm.sectPr_lst[key] 26 | return Section(sectPr) 27 | 28 | def __iter__(self): 29 | for sectPr in self._document_elm.sectPr_lst: 30 | yield Section(sectPr) 31 | 32 | def __len__(self): 33 | return len(self._document_elm.sectPr_lst) 34 | 35 | 36 | class Section(object): 37 | """ 38 | Document section, providing access to section and page setup settings. 39 | """ 40 | def __init__(self, sectPr): 41 | super(Section, self).__init__() 42 | self._sectPr = sectPr 43 | 44 | @property 45 | def bottom_margin(self): 46 | """ 47 | |Length| object representing the bottom margin for all pages in this 48 | section in English Metric Units. 49 | """ 50 | return self._sectPr.bottom_margin 51 | 52 | @bottom_margin.setter 53 | def bottom_margin(self, value): 54 | self._sectPr.bottom_margin = value 55 | 56 | @property 57 | def footer_distance(self): 58 | """ 59 | |Length| object representing the distance from the bottom edge of the 60 | page to the bottom edge of the footer. |None| if no setting is present 61 | in the XML. 62 | """ 63 | return self._sectPr.footer 64 | 65 | @footer_distance.setter 66 | def footer_distance(self, value): 67 | self._sectPr.footer = value 68 | 69 | @property 70 | def gutter(self): 71 | """ 72 | |Length| object representing the page gutter size in English Metric 73 | Units for all pages in this section. The page gutter is extra spacing 74 | added to the *inner* margin to ensure even margins after page 75 | binding. 76 | """ 77 | return self._sectPr.gutter 78 | 79 | @gutter.setter 80 | def gutter(self, value): 81 | self._sectPr.gutter = value 82 | 83 | @property 84 | def header_distance(self): 85 | """ 86 | |Length| object representing the distance from the top edge of the 87 | page to the top edge of the header. |None| if no setting is present 88 | in the XML. 89 | """ 90 | return self._sectPr.header 91 | 92 | @header_distance.setter 93 | def header_distance(self, value): 94 | self._sectPr.header = value 95 | 96 | @property 97 | def left_margin(self): 98 | """ 99 | |Length| object representing the left margin for all pages in this 100 | section in English Metric Units. 101 | """ 102 | return self._sectPr.left_margin 103 | 104 | @left_margin.setter 105 | def left_margin(self, value): 106 | self._sectPr.left_margin = value 107 | 108 | @property 109 | def orientation(self): 110 | """ 111 | Member of the :ref:`WdOrientation` enumeration specifying the page 112 | orientation for this section, one of ``WD_ORIENT.PORTRAIT`` or 113 | ``WD_ORIENT.LANDSCAPE``. 114 | """ 115 | return self._sectPr.orientation 116 | 117 | @orientation.setter 118 | def orientation(self, value): 119 | self._sectPr.orientation = value 120 | 121 | @property 122 | def page_height(self): 123 | """ 124 | Total page height used for this section, inclusive of all edge spacing 125 | values such as margins. Page orientation is taken into account, so 126 | for example, its expected value would be ``Inches(8.5)`` for 127 | letter-sized paper when orientation is landscape. 128 | """ 129 | return self._sectPr.page_height 130 | 131 | @page_height.setter 132 | def page_height(self, value): 133 | self._sectPr.page_height = value 134 | 135 | @property 136 | def page_width(self): 137 | """ 138 | Total page width used for this section, inclusive of all edge spacing 139 | values such as margins. Page orientation is taken into account, so 140 | for example, its expected value would be ``Inches(11)`` for 141 | letter-sized paper when orientation is landscape. 142 | """ 143 | return self._sectPr.page_width 144 | 145 | @page_width.setter 146 | def page_width(self, value): 147 | self._sectPr.page_width = value 148 | 149 | @property 150 | def right_margin(self): 151 | """ 152 | |Length| object representing the right margin for all pages in this 153 | section in English Metric Units. 154 | """ 155 | return self._sectPr.right_margin 156 | 157 | @right_margin.setter 158 | def right_margin(self, value): 159 | self._sectPr.right_margin = value 160 | 161 | @property 162 | def start_type(self): 163 | """ 164 | The member of the :ref:`WdSectionStart` enumeration corresponding to 165 | the initial break behavior of this section, e.g. 166 | ``WD_SECTION.ODD_PAGE`` if the section should begin on the next odd 167 | page. 168 | """ 169 | return self._sectPr.start_type 170 | 171 | @start_type.setter 172 | def start_type(self, value): 173 | self._sectPr.start_type = value 174 | 175 | @property 176 | def top_margin(self): 177 | """ 178 | |Length| object representing the top margin for all pages in this 179 | section in English Metric Units. 180 | """ 181 | return self._sectPr.top_margin 182 | 183 | @top_margin.setter 184 | def top_margin(self, value): 185 | self._sectPr.top_margin = value 186 | -------------------------------------------------------------------------------- /Python/NoteTaker/docx/shape.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | """ 4 | Objects related to shapes, visual objects that appear on the drawing layer of 5 | a document. 6 | """ 7 | 8 | from __future__ import ( 9 | absolute_import, division, print_function, unicode_literals 10 | ) 11 | 12 | from .enum.shape import WD_INLINE_SHAPE 13 | from .oxml.ns import nsmap 14 | from .shared import Parented 15 | 16 | 17 | class InlineShapes(Parented): 18 | """ 19 | Sequence of |InlineShape| instances, supporting len(), iteration, and 20 | indexed access. 21 | """ 22 | def __init__(self, body_elm, parent): 23 | super(InlineShapes, self).__init__(parent) 24 | self._body = body_elm 25 | 26 | def __getitem__(self, idx): 27 | """ 28 | Provide indexed access, e.g. 'inline_shapes[idx]' 29 | """ 30 | try: 31 | inline = self._inline_lst[idx] 32 | except IndexError: 33 | msg = "inline shape index [%d] out of range" % idx 34 | raise IndexError(msg) 35 | return InlineShape(inline) 36 | 37 | def __iter__(self): 38 | return (InlineShape(inline) for inline in self._inline_lst) 39 | 40 | def __len__(self): 41 | return len(self._inline_lst) 42 | 43 | @property 44 | def _inline_lst(self): 45 | body = self._body 46 | xpath = '//w:p/w:r/w:drawing/wp:inline' 47 | return body.xpath(xpath) 48 | 49 | 50 | class InlineShape(object): 51 | """ 52 | Proxy for an ```` element, representing the container for an 53 | inline graphical object. 54 | """ 55 | def __init__(self, inline): 56 | super(InlineShape, self).__init__() 57 | self._inline = inline 58 | 59 | @property 60 | def height(self): 61 | """ 62 | Read/write. The display height of this inline shape as an |Emu| 63 | instance. 64 | """ 65 | return self._inline.extent.cy 66 | 67 | @height.setter 68 | def height(self, cy): 69 | self._inline.extent.cy = cy 70 | self._inline.graphic.graphicData.pic.spPr.cy = cy 71 | 72 | @property 73 | def type(self): 74 | """ 75 | The type of this inline shape as a member of 76 | ``docx.enum.shape.WD_INLINE_SHAPE``, e.g. ``LINKED_PICTURE``. 77 | Read-only. 78 | """ 79 | graphicData = self._inline.graphic.graphicData 80 | uri = graphicData.uri 81 | if uri == nsmap['pic']: 82 | blip = graphicData.pic.blipFill.blip 83 | if blip.link is not None: 84 | return WD_INLINE_SHAPE.LINKED_PICTURE 85 | return WD_INLINE_SHAPE.PICTURE 86 | if uri == nsmap['c']: 87 | return WD_INLINE_SHAPE.CHART 88 | if uri == nsmap['dgm']: 89 | return WD_INLINE_SHAPE.SMART_ART 90 | return WD_INLINE_SHAPE.NOT_IMPLEMENTED 91 | 92 | @property 93 | def width(self): 94 | """ 95 | Read/write. The display width of this inline shape as an |Emu| 96 | instance. 97 | """ 98 | return self._inline.extent.cx 99 | 100 | @width.setter 101 | def width(self, cx): 102 | self._inline.extent.cx = cx 103 | self._inline.graphic.graphicData.pic.spPr.cx = cx 104 | -------------------------------------------------------------------------------- /Python/NoteTaker/docx/styles/__init__.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | """ 4 | Sub-package module for docx.styles sub-package. 5 | """ 6 | 7 | from __future__ import ( 8 | absolute_import, division, print_function, unicode_literals 9 | ) 10 | 11 | 12 | class BabelFish(object): 13 | """ 14 | Translates special-case style names from UI name (e.g. Heading 1) to 15 | internal/styles.xml name (e.g. heading 1) and back. 16 | """ 17 | 18 | style_aliases = ( 19 | ('Caption', 'caption'), 20 | ('Heading 1', 'heading 1'), 21 | ('Heading 2', 'heading 2'), 22 | ('Heading 3', 'heading 3'), 23 | ('Heading 4', 'heading 4'), 24 | ('Heading 5', 'heading 5'), 25 | ('Heading 6', 'heading 6'), 26 | ('Heading 7', 'heading 7'), 27 | ('Heading 8', 'heading 8'), 28 | ('Heading 9', 'heading 9'), 29 | ) 30 | 31 | internal_style_names = dict(style_aliases) 32 | ui_style_names = dict((item[1], item[0]) for item in style_aliases) 33 | 34 | @classmethod 35 | def ui2internal(cls, ui_style_name): 36 | """ 37 | Return the internal style name corresponding to *ui_style_name*, such 38 | as 'heading 1' for 'Heading 1'. 39 | """ 40 | return cls.internal_style_names.get(ui_style_name, ui_style_name) 41 | 42 | @classmethod 43 | def internal2ui(cls, internal_style_name): 44 | """ 45 | Return the user interface style name corresponding to 46 | *internal_style_name*, such as 'Heading 1' for 'heading 1'. 47 | """ 48 | return cls.ui_style_names.get( 49 | internal_style_name, internal_style_name 50 | ) 51 | -------------------------------------------------------------------------------- /Python/NoteTaker/docx/styles/styles.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | """ 4 | Styles object, container for all objects in the styles part. 5 | """ 6 | 7 | from __future__ import ( 8 | absolute_import, division, print_function, unicode_literals 9 | ) 10 | 11 | from warnings import warn 12 | 13 | from . import BabelFish 14 | from .latent import LatentStyles 15 | from ..shared import ElementProxy 16 | from .style import BaseStyle, StyleFactory 17 | 18 | 19 | class Styles(ElementProxy): 20 | """ 21 | A collection providing access to the styles defined in a document. 22 | Accessed using the :attr:`.Document.styles` property. Supports ``len()``, 23 | iteration, and dictionary-style access by style name. 24 | """ 25 | 26 | __slots__ = () 27 | 28 | def __contains__(self, name): 29 | """ 30 | Enables `in` operator on style name. 31 | """ 32 | internal_name = BabelFish.ui2internal(name) 33 | for style in self._element.style_lst: 34 | if style.name_val == internal_name: 35 | return True 36 | return False 37 | 38 | def __getitem__(self, key): 39 | """ 40 | Enables dictionary-style access by UI name. Lookup by style id is 41 | deprecated, triggers a warning, and will be removed in a near-future 42 | release. 43 | """ 44 | style_elm = self._element.get_by_name(BabelFish.ui2internal(key)) 45 | if style_elm is not None: 46 | return StyleFactory(style_elm) 47 | 48 | style_elm = self._element.get_by_id(key) 49 | if style_elm is not None: 50 | msg = ( 51 | 'style lookup by style_id is deprecated. Use style name as ' 52 | 'key instead.' 53 | ) 54 | warn(msg, UserWarning) 55 | return StyleFactory(style_elm) 56 | 57 | raise KeyError("no style with name '%s'" % key) 58 | 59 | def __iter__(self): 60 | return (StyleFactory(style) for style in self._element.style_lst) 61 | 62 | def __len__(self): 63 | return len(self._element.style_lst) 64 | 65 | def add_style(self, name, style_type, builtin=False): 66 | """ 67 | Return a newly added style object of *style_type* and identified 68 | by *name*. A builtin style can be defined by passing True for the 69 | optional *builtin* argument. 70 | """ 71 | style_name = BabelFish.ui2internal(name) 72 | if style_name in self: 73 | raise ValueError("document already contains style '%s'" % name) 74 | style = self._element.add_style_of_type( 75 | style_name, style_type, builtin 76 | ) 77 | return StyleFactory(style) 78 | 79 | def default(self, style_type): 80 | """ 81 | Return the default style for *style_type* or |None| if no default is 82 | defined for that type (not common). 83 | """ 84 | style = self._element.default_for(style_type) 85 | if style is None: 86 | return None 87 | return StyleFactory(style) 88 | 89 | def get_by_id(self, style_id, style_type): 90 | """ 91 | Return the style of *style_type* matching *style_id*. Returns the 92 | default for *style_type* if *style_id* is not found or is |None|, or 93 | if the style having *style_id* is not of *style_type*. 94 | """ 95 | if style_id is None: 96 | return self.default(style_type) 97 | return self._get_by_id(style_id, style_type) 98 | 99 | def get_style_id(self, style_or_name, style_type): 100 | """ 101 | Return the id of the style corresponding to *style_or_name*, or 102 | |None| if *style_or_name* is |None|. If *style_or_name* is not 103 | a style object, the style is looked up using *style_or_name* as 104 | a style name, raising |ValueError| if no style with that name is 105 | defined. Raises |ValueError| if the target style is not of 106 | *style_type*. 107 | """ 108 | if style_or_name is None: 109 | return None 110 | elif isinstance(style_or_name, BaseStyle): 111 | return self._get_style_id_from_style(style_or_name, style_type) 112 | else: 113 | return self._get_style_id_from_name(style_or_name, style_type) 114 | 115 | @property 116 | def latent_styles(self): 117 | """ 118 | A |LatentStyles| object providing access to the default behaviors for 119 | latent styles and the collection of |_LatentStyle| objects that 120 | define overrides of those defaults for a particular named latent 121 | style. 122 | """ 123 | return LatentStyles(self._element.get_or_add_latentStyles()) 124 | 125 | def _get_by_id(self, style_id, style_type): 126 | """ 127 | Return the style of *style_type* matching *style_id*. Returns the 128 | default for *style_type* if *style_id* is not found or if the style 129 | having *style_id* is not of *style_type*. 130 | """ 131 | style = self._element.get_by_id(style_id) 132 | if style is None or style.type != style_type: 133 | return self.default(style_type) 134 | return StyleFactory(style) 135 | 136 | def _get_style_id_from_name(self, style_name, style_type): 137 | """ 138 | Return the id of the style of *style_type* corresponding to 139 | *style_name*. Returns |None| if that style is the default style for 140 | *style_type*. Raises |ValueError| if the named style is not found in 141 | the document or does not match *style_type*. 142 | """ 143 | return self._get_style_id_from_style(self[style_name], style_type) 144 | 145 | def _get_style_id_from_style(self, style, style_type): 146 | """ 147 | Return the id of *style*, or |None| if it is the default style of 148 | *style_type*. Raises |ValueError| if style is not of *style_type*. 149 | """ 150 | if style.type != style_type: 151 | raise ValueError( 152 | "assigned style is type %s, need type %s" % 153 | (style.type, style_type) 154 | ) 155 | if style == self.default(style_type): 156 | return None 157 | return style.style_id 158 | -------------------------------------------------------------------------------- /Python/NoteTaker/docx/templates/default-src.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsouzarc/dotfiles/f771532b0f512efcefa3dc0ede31deceaf0e9acc/Python/NoteTaker/docx/templates/default-src.docx -------------------------------------------------------------------------------- /Python/NoteTaker/docx/templates/default.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsouzarc/dotfiles/f771532b0f512efcefa3dc0ede31deceaf0e9acc/Python/NoteTaker/docx/templates/default.docx -------------------------------------------------------------------------------- /Python/NoteTaker/docx/text/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsouzarc/dotfiles/f771532b0f512efcefa3dc0ede31deceaf0e9acc/Python/NoteTaker/docx/text/__init__.py -------------------------------------------------------------------------------- /Python/NoteTaker/docx/text/paragraph.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | """ 4 | Paragraph-related proxy types. 5 | """ 6 | 7 | from __future__ import ( 8 | absolute_import, division, print_function, unicode_literals 9 | ) 10 | 11 | from ..enum.style import WD_STYLE_TYPE 12 | from .parfmt import ParagraphFormat 13 | from .run import Run 14 | from ..shared import Parented 15 | 16 | 17 | class Paragraph(Parented): 18 | """ 19 | Proxy object wrapping ```` element. 20 | """ 21 | def __init__(self, p, parent): 22 | super(Paragraph, self).__init__(parent) 23 | self._p = self._element = p 24 | 25 | def add_run(self, text=None, style=None): 26 | """ 27 | Append a run to this paragraph containing *text* and having character 28 | style identified by style ID *style*. *text* can contain tab 29 | (``\\t``) characters, which are converted to the appropriate XML form 30 | for a tab. *text* can also include newline (``\\n``) or carriage 31 | return (``\\r``) characters, each of which is converted to a line 32 | break. 33 | """ 34 | r = self._p.add_r() 35 | run = Run(r, self) 36 | if text: 37 | run.text = text 38 | if style: 39 | run.style = style 40 | return run 41 | 42 | @property 43 | def alignment(self): 44 | """ 45 | A member of the :ref:`WdParagraphAlignment` enumeration specifying 46 | the justification setting for this paragraph. A value of |None| 47 | indicates the paragraph has no directly-applied alignment value and 48 | will inherit its alignment value from its style hierarchy. Assigning 49 | |None| to this property removes any directly-applied alignment value. 50 | """ 51 | return self._p.alignment 52 | 53 | @alignment.setter 54 | def alignment(self, value): 55 | self._p.alignment = value 56 | 57 | def clear(self): 58 | """ 59 | Return this same paragraph after removing all its content. 60 | Paragraph-level formatting, such as style, is preserved. 61 | """ 62 | self._p.clear_content() 63 | return self 64 | 65 | def insert_paragraph_before(self, text=None, style=None): 66 | """ 67 | Return a newly created paragraph, inserted directly before this 68 | paragraph. If *text* is supplied, the new paragraph contains that 69 | text in a single run. If *style* is provided, that style is assigned 70 | to the new paragraph. 71 | """ 72 | paragraph = self._insert_paragraph_before() 73 | if text: 74 | paragraph.add_run(text) 75 | if style is not None: 76 | paragraph.style = style 77 | return paragraph 78 | 79 | @property 80 | def paragraph_format(self): 81 | """ 82 | The |ParagraphFormat| object providing access to the formatting 83 | properties for this paragraph, such as line spacing and indentation. 84 | """ 85 | return ParagraphFormat(self._element) 86 | 87 | @property 88 | def runs(self): 89 | """ 90 | Sequence of |Run| instances corresponding to the elements in 91 | this paragraph. 92 | """ 93 | return [Run(r, self) for r in self._p.r_lst] 94 | 95 | @property 96 | def style(self): 97 | """ 98 | Read/Write. |_ParagraphStyle| object representing the style assigned 99 | to this paragraph. If no explicit style is assigned to this 100 | paragraph, its value is the default paragraph style for the document. 101 | A paragraph style name can be assigned in lieu of a paragraph style 102 | object. Assigning |None| removes any applied style, making its 103 | effective value the default paragraph style for the document. 104 | """ 105 | style_id = self._p.style 106 | return self.part.get_style(style_id, WD_STYLE_TYPE.PARAGRAPH) 107 | 108 | @style.setter 109 | def style(self, style_or_name): 110 | style_id = self.part.get_style_id( 111 | style_or_name, WD_STYLE_TYPE.PARAGRAPH 112 | ) 113 | self._p.style = style_id 114 | 115 | @property 116 | def text(self): 117 | """ 118 | String formed by concatenating the text of each run in the paragraph. 119 | Tabs and line breaks in the XML are mapped to ``\\t`` and ``\\n`` 120 | characters respectively. 121 | 122 | Assigning text to this property causes all existing paragraph content 123 | to be replaced with a single run containing the assigned text. 124 | A ``\\t`` character in the text is mapped to a ```` element 125 | and each ``\\n`` or ``\\r`` character is mapped to a line break. 126 | Paragraph-level formatting, such as style, is preserved. All 127 | run-level formatting, such as bold or italic, is removed. 128 | """ 129 | text = '' 130 | for run in self.runs: 131 | text += run.text 132 | return text 133 | 134 | @text.setter 135 | def text(self, text): 136 | self.clear() 137 | self.add_run(text) 138 | 139 | def _insert_paragraph_before(self): 140 | """ 141 | Return a newly created paragraph, inserted directly before this 142 | paragraph. 143 | """ 144 | p = self._p.add_p_before() 145 | return Paragraph(p, self._parent) 146 | -------------------------------------------------------------------------------- /Python/NoteTaker/docx/text/run.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | """ 4 | Run-related proxy objects for python-docx, Run in particular. 5 | """ 6 | 7 | from __future__ import absolute_import, print_function, unicode_literals 8 | 9 | from ..enum.style import WD_STYLE_TYPE 10 | from ..enum.text import WD_BREAK 11 | from .font import Font 12 | from ..shape import InlineShape 13 | from ..shared import Parented 14 | 15 | 16 | class Run(Parented): 17 | """ 18 | Proxy object wrapping ```` element. Several of the properties on Run 19 | take a tri-state value, |True|, |False|, or |None|. |True| and |False| 20 | correspond to on and off respectively. |None| indicates the property is 21 | not specified directly on the run and its effective value is taken from 22 | the style hierarchy. 23 | """ 24 | def __init__(self, r, parent): 25 | super(Run, self).__init__(parent) 26 | self._r = self._element = self.element = r 27 | 28 | def add_break(self, break_type=WD_BREAK.LINE): 29 | """ 30 | Add a break element of *break_type* to this run. *break_type* can 31 | take the values `WD_BREAK.LINE`, `WD_BREAK.PAGE`, and 32 | `WD_BREAK.COLUMN` where `WD_BREAK` is imported from `docx.enum.text`. 33 | *break_type* defaults to `WD_BREAK.LINE`. 34 | """ 35 | type_, clear = { 36 | WD_BREAK.LINE: (None, None), 37 | WD_BREAK.PAGE: ('page', None), 38 | WD_BREAK.COLUMN: ('column', None), 39 | WD_BREAK.LINE_CLEAR_LEFT: ('textWrapping', 'left'), 40 | WD_BREAK.LINE_CLEAR_RIGHT: ('textWrapping', 'right'), 41 | WD_BREAK.LINE_CLEAR_ALL: ('textWrapping', 'all'), 42 | }[break_type] 43 | br = self._r.add_br() 44 | if type_ is not None: 45 | br.type = type_ 46 | if clear is not None: 47 | br.clear = clear 48 | 49 | def add_picture(self, image_path_or_stream, width=None, height=None): 50 | """ 51 | Return an |InlineShape| instance containing the image identified by 52 | *image_path_or_stream*, added to the end of this run. 53 | *image_path_or_stream* can be a path (a string) or a file-like object 54 | containing a binary image. If neither width nor height is specified, 55 | the picture appears at its native size. If only one is specified, it 56 | is used to compute a scaling factor that is then applied to the 57 | unspecified dimension, preserving the aspect ratio of the image. The 58 | native size of the picture is calculated using the dots-per-inch 59 | (dpi) value specified in the image file, defaulting to 72 dpi if no 60 | value is specified, as is often the case. 61 | """ 62 | inline = self.part.new_pic_inline(image_path_or_stream, width, height) 63 | self._r.add_drawing(inline) 64 | return InlineShape(inline) 65 | 66 | def add_tab(self): 67 | """ 68 | Add a ```` element at the end of the run, which Word 69 | interprets as a tab character. 70 | """ 71 | self._r._add_tab() 72 | 73 | def add_text(self, text): 74 | """ 75 | Returns a newly appended |_Text| object (corresponding to a new 76 | ```` child element) to the run, containing *text*. Compare with 77 | the possibly more friendly approach of assigning text to the 78 | :attr:`Run.text` property. 79 | """ 80 | t = self._r.add_t(text) 81 | return _Text(t) 82 | 83 | @property 84 | def bold(self): 85 | """ 86 | Read/write. Causes the text of the run to appear in bold. 87 | """ 88 | return self.font.bold 89 | 90 | @bold.setter 91 | def bold(self, value): 92 | self.font.bold = value 93 | 94 | def clear(self): 95 | """ 96 | Return reference to this run after removing all its content. All run 97 | formatting is preserved. 98 | """ 99 | self._r.clear_content() 100 | return self 101 | 102 | @property 103 | def font(self): 104 | """ 105 | The |Font| object providing access to the character formatting 106 | properties for this run, such as font name and size. 107 | """ 108 | return Font(self._element) 109 | 110 | @property 111 | def italic(self): 112 | """ 113 | Read/write tri-state value. When |True|, causes the text of the run 114 | to appear in italics. 115 | """ 116 | return self.font.italic 117 | 118 | @italic.setter 119 | def italic(self, value): 120 | self.font.italic = value 121 | 122 | @property 123 | def style(self): 124 | """ 125 | Read/write. A |_CharacterStyle| object representing the character 126 | style applied to this run. The default character style for the 127 | document (often `Default Character Font`) is returned if the run has 128 | no directly-applied character style. Setting this property to |None| 129 | removes any directly-applied character style. 130 | """ 131 | style_id = self._r.style 132 | return self.part.get_style(style_id, WD_STYLE_TYPE.CHARACTER) 133 | 134 | @style.setter 135 | def style(self, style_or_name): 136 | style_id = self.part.get_style_id( 137 | style_or_name, WD_STYLE_TYPE.CHARACTER 138 | ) 139 | self._r.style = style_id 140 | 141 | @property 142 | def text(self): 143 | """ 144 | String formed by concatenating the text equivalent of each run 145 | content child element into a Python string. Each ```` element 146 | adds the text characters it contains. A ```` element adds 147 | a ``\\t`` character. A ```` or ```` element each add 148 | a ``\\n`` character. Note that a ```` element can indicate 149 | a page break or column break as well as a line break. All ```` 150 | elements translate to a single ``\\n`` character regardless of their 151 | type. All other content child elements, such as ````, are 152 | ignored. 153 | 154 | Assigning text to this property has the reverse effect, translating 155 | each ``\\t`` character to a ```` element and each ``\\n`` or 156 | ``\\r`` character to a ```` element. Any existing run content 157 | is replaced. Run formatting is preserved. 158 | """ 159 | return self._r.text 160 | 161 | @text.setter 162 | def text(self, text): 163 | self._r.text = text 164 | 165 | @property 166 | def underline(self): 167 | """ 168 | The underline style for this |Run|, one of |None|, |True|, |False|, 169 | or a value from :ref:`WdUnderline`. A value of |None| indicates the 170 | run has no directly-applied underline value and so will inherit the 171 | underline value of its containing paragraph. Assigning |None| to this 172 | property removes any directly-applied underline value. A value of 173 | |False| indicates a directly-applied setting of no underline, 174 | overriding any inherited value. A value of |True| indicates single 175 | underline. The values from :ref:`WdUnderline` are used to specify 176 | other outline styles such as double, wavy, and dotted. 177 | """ 178 | return self.font.underline 179 | 180 | @underline.setter 181 | def underline(self, value): 182 | self.font.underline = value 183 | 184 | 185 | class _Text(object): 186 | """ 187 | Proxy object wrapping ```` element. 188 | """ 189 | def __init__(self, t_elm): 190 | super(_Text, self).__init__() 191 | self._t = t_elm 192 | -------------------------------------------------------------------------------- /Python/NoteTaker/pyPdf/__init__.py: -------------------------------------------------------------------------------- 1 | from pdf import PdfFileReader, PdfFileWriter 2 | __all__ = ["pdf"] 3 | -------------------------------------------------------------------------------- /Python/NoteTaker/pyPdf/utils.py: -------------------------------------------------------------------------------- 1 | # vim: sw=4:expandtab:foldmethod=marker 2 | # 3 | # Copyright (c) 2006, Mathieu Fenniak 4 | # All rights reserved. 5 | # 6 | # Redistribution and use in source and binary forms, with or without 7 | # modification, are permitted provided that the following conditions are 8 | # met: 9 | # 10 | # * Redistributions of source code must retain the above copyright notice, 11 | # this list of conditions and the following disclaimer. 12 | # * Redistributions in binary form must reproduce the above copyright notice, 13 | # this list of conditions and the following disclaimer in the documentation 14 | # and/or other materials provided with the distribution. 15 | # * The name of the author may not be used to endorse or promote products 16 | # derived from this software without specific prior written permission. 17 | # 18 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 | # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 22 | # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 | # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 | # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 | # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 | # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 | # POSSIBILITY OF SUCH DAMAGE. 29 | 30 | 31 | """ 32 | Utility functions for PDF library. 33 | """ 34 | __author__ = "Mathieu Fenniak" 35 | __author_email__ = "biziqe@mathieu.fenniak.net" 36 | 37 | #ENABLE_PSYCO = False 38 | #if ENABLE_PSYCO: 39 | # try: 40 | # import psyco 41 | # except ImportError: 42 | # ENABLE_PSYCO = False 43 | # 44 | #if not ENABLE_PSYCO: 45 | # class psyco: 46 | # def proxy(func): 47 | # return func 48 | # proxy = staticmethod(proxy) 49 | 50 | def readUntilWhitespace(stream, maxchars=None): 51 | txt = "" 52 | while True: 53 | tok = stream.read(1) 54 | if tok.isspace() or not tok: 55 | break 56 | txt += tok 57 | if len(txt) == maxchars: 58 | break 59 | return txt 60 | 61 | def readNonWhitespace(stream): 62 | tok = ' ' 63 | while tok == '\n' or tok == '\r' or tok == ' ' or tok == '\t': 64 | tok = stream.read(1) 65 | return tok 66 | 67 | class ConvertFunctionsToVirtualList(object): 68 | def __init__(self, lengthFunction, getFunction): 69 | self.lengthFunction = lengthFunction 70 | self.getFunction = getFunction 71 | 72 | def __len__(self): 73 | return self.lengthFunction() 74 | 75 | def __getitem__(self, index): 76 | if not isinstance(index, int): 77 | raise TypeError, "sequence indices must be integers" 78 | len_self = len(self) 79 | if index < 0: 80 | # support negative indexes 81 | index = len_self + index 82 | if index < 0 or index >= len_self: 83 | raise IndexError, "sequence index out of range" 84 | return self.getFunction(index) 85 | 86 | def RC4_encrypt(key, plaintext): 87 | S = [i for i in range(256)] 88 | j = 0 89 | for i in range(256): 90 | j = (j + S[i] + ord(key[i % len(key)])) % 256 91 | S[i], S[j] = S[j], S[i] 92 | i, j = 0, 0 93 | retval = "" 94 | for x in range(len(plaintext)): 95 | i = (i + 1) % 256 96 | j = (j + S[i]) % 256 97 | S[i], S[j] = S[j], S[i] 98 | t = S[(S[i] + S[j]) % 256] 99 | retval += chr(ord(plaintext[x]) ^ t) 100 | return retval 101 | 102 | def matrixMultiply(a, b): 103 | return [[sum([float(i)*float(j) 104 | for i, j in zip(row, col)] 105 | ) for col in zip(*b)] 106 | for row in a] 107 | 108 | class PyPdfError(Exception): 109 | pass 110 | 111 | class PdfReadError(PyPdfError): 112 | pass 113 | 114 | class PageSizeNotDefinedError(PyPdfError): 115 | pass 116 | 117 | if __name__ == "__main__": 118 | # test RC4 119 | out = RC4_encrypt("Key", "Plaintext") 120 | print repr(out) 121 | pt = RC4_encrypt("Key", out) 122 | print repr(pt) 123 | -------------------------------------------------------------------------------- /Python/PasswordGenerator.py: -------------------------------------------------------------------------------- 1 | import itertools; 2 | 3 | ############################################################# 4 | # Written by Ryan D'souza 5 | # Generates password combinations and saves them to a file 6 | ############################################################# 7 | 8 | 9 | #Returns a string with every ASCII key 10 | #Essentially returns ' !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~' 11 | def getAllAsciiValues(): 12 | string = ""; 13 | asciiValue = 32; 14 | while asciiValue <= 126: 15 | string = string + chr(asciiValue); 16 | asciiValue += 1; 17 | return string; 18 | 19 | 20 | #Writes the password combinations to a file 21 | def writePasswordCombinations(fileName = None, fromString = None, maxCharacters = None, minCharacters = None): 22 | 23 | #All combinations of what string 24 | if fromString is None: 25 | fromString = getAllAsciiValues(); 26 | 27 | #Max number of characters for password 28 | if maxCharacters is None: 29 | maxCharacters = 10; 30 | 31 | #Min number of characters for password 32 | if minCharacters is None: 33 | minCharacters = 3; 34 | 35 | #File name to save the password combinations to 36 | if fileName is None: 37 | fileName = str(minCharacters) + "-" + str(maxCharacters) + "_passwords.txt"; 38 | 39 | numPasswords = 0; 40 | numFiles = 1; 41 | 42 | #Create a new file with the format 1-passwordFileName.txt 43 | passwordFile = open(str(numFiles) + "-" + fileName, 'w'); 44 | 45 | #Get all combinations from minCharacter length to maxCharacterlength 46 | while minCharacters <= maxCharacters: 47 | res = itertools.product(fromString, repeat=minCharacters); 48 | for i in res: 49 | passwordFile.write(''.join(i) + "\n"); 50 | numPasswords += 1; 51 | 52 | #Every 1,000,000,000, store the combinations in a new file with format 2-passwordFileName.txt 53 | if numPasswords % 1000000000 == 0: 54 | passwordFile.close(); 55 | numFiles += 1; 56 | passwordFile = open(str(numFiles) + "-" + fileName, 'w'); 57 | 58 | #Print a status update every now and then 59 | if numPasswords % 1000000 == 0: 60 | print("# of passwords: " + str(numPasswords)); 61 | 62 | #For incrementing password length 63 | minCharacters += 1; 64 | 65 | passwordFile.close(); 66 | 67 | #For my testing purpose, just testing letters and numbers 68 | letters = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" 69 | writePasswordCombinations(fileName = "pure_letters_numbers.txt", fromString = letters, maxCharacters = 14, minCharacters = 8); 70 | -------------------------------------------------------------------------------- /Python/README.md: -------------------------------------------------------------------------------- 1 | # Written by Ryan D'souza 2 | 3 | ## Various Python files I run from the commandline to help me with miscellaneous tasks 4 | 5 | #### [Credential Manager](https://github.com/dsouzarc/dotfiles/blob/master/Python/CredentialManager.py) 6 | 7 | Super lightweight, secure (base64encode), quick, and easy to use credential manager to save and retrieve passwords. Stores the encrypted passwords in a secret json file in a secret folder in the home directory, enabling the script to be run from anywhere on the computer. 8 | 9 | There's only one file needed (quick for copying/pasting), and all imports are from the standard python library so downloading it is as simple as 10 | 11 | curl -L tiny.cc/credentialManager.py > CredentialManager.py 12 | 13 | and using it as simple as 14 | 15 | python CredentialManager.py 16 | 17 | I mainly built this to use on my school's computer where installing commandline tools like 'pip' is not allowed. Because of that, I can't install python's 'keyring' library to securely store my usernames/passwords. So, I made this script which can be run from anywhere 18 | 19 | ##### How to use 20 | Installation & Setup 21 | 22 | #Sets up directory and json file, and also prompts for quickly saving a username and password (password entering is hidden) 23 | python CredentialManager.py 24 | 25 | Accessing stored data 26 | 27 | import CredentialManager; 28 | 29 | username = CredentialManager.get_value("sendgridUsername"); 30 | password = CredentialManager.get_value("sendgridPassword"); 31 | 32 | Quickly modifying data (Option 1) --> [Example](https://github.com/dsouzarc/dotfiles/blob/master/Python/CredentialManagerExample.py) 33 | 34 | import CredentialManager; 35 | 36 | CredentialManager.save_credentials("sendgridUsername", "someusername", sendgridPassword", "somePassword"); 37 | CredentialManager.save_key("PromMeParseAPIKey", "someapikey"); 38 | 39 | CredentialManager.delete_key("PromMeParseAPIKey"); 40 | 41 | Quickly modifying data (Option 2) --> Run from the terminal. Each term (ie. 'save_key') is a string param and causes the program to prompt for additional input 42 | 43 | python CredentialManager save_key 44 | python CredentialManager set_value 45 | python CredentialManager get_value 46 | python CredentialManager does_key_exist 47 | python CredentialManager delete_key 48 | 49 | Quickly modifying data (Option 3) --> Run from the terminal 50 | 51 | python -c 'import CredentialManager; CredentialManager.save_key("myKey", "myValue")' 52 | python -c 'import CredentialManager; CredentialManager.delete_key("gmailUsername")' 53 | 54 | 55 | #### [Note Taker](https://github.com/dsouzarc/dotfiles/tree/master/Python/NoteTaker) 56 | Takes random notes on a book. 57 | For more details, see [README.md](https://github.com/dsouzarc/dotfiles/tree/master/Python/NoteTaker) 58 | 59 | #### [Dictionary](https://github.com/dsouzarc/dotfiles/blob/master/Python/Dictionary.py) 60 | I wrote this script because using a web browser to look up the definition of a word takes way too long on my computer (mid-2009 Macbook Pro) 61 | 62 | This script prints out the definition of a word and usage of the word in a sentence 63 | 64 | Dependencies: None 65 | 66 | Usage: 67 | 68 | python Dictionary.py perfunctory 69 | 70 | Or, to prompt: 71 | 72 | python Dictionary.py 73 | 74 | 75 | #### [iOS App Icon Resizer](https://github.com/dsouzarc/dotfiles/blob/master/Python/iOSAppIconResizer.py) 76 | Quickly resizes an image of any extension to 5 png images according to Apple's iOS icon requirements. 77 | Creates a directory in the directory it is run from called 'AppIcon' and saves each file there with the appropriate title ie. iPhone6@3x.png will be 180 x 180 78 | 79 | #Can be run from any directory 80 | python iOSAppIconResizer.py imageName.jpg 81 | 82 | 83 | #### [Text Phone](https://github.com/dsouzarc/dotfiles/blob/master/Python/TextPhone.py) 84 | Quickly sends a text to myself from the command line 85 | 86 | Dependencies: 87 | [CredentialManager.py](https://github.com/dsouzarc/dotfiles/tree/master/Python#credential-manager) 88 | 89 | Run Instructions: 90 | 91 | python TextPhone.py message 92 | 93 | Or, as a prompt: 94 | 95 | python TextPhone.py 96 | 97 | 98 | #### [Text Phone Plain](https://github.com/dsouzarc/dotfiles/blob/master/Python/TextPhoneP.py) 99 | Also quickly sends a text to myself from the command line. The main difference between this and 'TextPhone.py' is that it has no dependencies (it prompts for password via a secure input formatter) 100 | 101 | Run Instructions (prompts for info): 102 | 103 | python TextPhoneP.py 104 | 105 | 106 | #### [Text Link](https://github.com/dsouzarc/dotfiles/blob/master/Python/TextLink.py) 107 | Quickly sends a link to myself from the commandline 108 | If the link is too long (over 150 characters), shortens the link by using [po.st](https://www.po.st) 109 | 110 | Dependencies: 111 | [CredentialManager.py](https://github.com/dsouzarc/dotfiles/tree/master/Python#credential-manager) 112 | 113 | Run Instructions: 114 | 115 | python TextLink.py linkhere 116 | 117 | Or, as a prompt: 118 | 119 | python TextLink.py 120 | 121 | #### [Text People](https://github.com/dsouzarc/dotfiles/blob/master/Python/TextPeople.py) 122 | Quickly sends a text to anyone from anyone from the commandline 123 | 124 | Dependencies: 125 | [CredentialManager.py](https://github.com/dsouzarc/dotfiles/tree/master/Python#credential-manager) 126 | 127 | Run Instructions (prompts for info): 128 | 129 | python TextPeople.py 130 | 131 | #### [Email Attachment](https://github.com/dsouzarc/dotfiles/blob/master/Python/EmailAttachment.py) 132 | I wrote this Python script to quickly email files to myself because it takes way too long to do something that simple on my mid-2009 Macbook Pro. Gmail, when accessed via a web browser, uses way too much CPU processing power and lags for the first 20 seconds because of all the JavaScript it has to load. The Mail app uses way too much RAM to always be open, and when I do need to open it to quickly send myself something, the app opening/loading takes about 20 seconds. Those timings only include opening the app; going to 'Create new message', setting the 'To' to myself, clicking 'Attach File' and navigating to the file, uploading and then sending the file brings the total time to email myself a small attachment to about two minutes. 133 | 134 | This Python script sends an attachment to myself in about 2 seconds and uses almost no additional RAM or CPU processing power. The script can be run from any directory and gets the file name (optional command line parameter) from the current working directory 135 | 136 | Dependencies: 137 | [CredentialManager.py](https://github.com/dsouzarc/dotfiles/tree/master/Python#credential-manager) 138 | 139 | Run Instructions: 140 | 141 | python EmailAttachment.py fileName 142 | 143 | Or, as a prompt: 144 | 145 | python EmailAttachment.py 146 | -------------------------------------------------------------------------------- /Python/TextAttachment.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | import CredentialManager; 3 | import os; 4 | import sys; 5 | import urllib2; 6 | import urllib; 7 | 8 | ###################################################### 9 | # Written by Ryan D'souza 10 | # Sends an attachment to myself using SendGrid's API 11 | # Can be run from any directory 12 | # 13 | # Dependencies: CredentialManager 14 | # tiny.cc/credentialManager 15 | # 16 | # Run Instructions: 17 | # python EmailAttachment.py fileName 18 | ###################################################### 19 | 20 | 21 | #If filename is commandline argument 22 | if len(sys.argv) == 2: 23 | fileName = sys.argv[1]; 24 | else: 25 | fileName = raw_input("Enter file name: "); 26 | 27 | #Url for POST request 28 | url = "https://api.sendgrid.com/api/mail.send.json"; 29 | 30 | #My Information 31 | username = CredentialManager.get_value("SendGridUsername"); 32 | password = CredentialManager.get_value("SendGridPassword"); 33 | from_ = "MBProCL"; 34 | to = "6099154930@vzwpix.com" 35 | 36 | #Parameters, same as usual 37 | params = { 38 | "api_user": username, 39 | "api_key": password, 40 | "from": from_, 41 | "to": to, 42 | "subject": " ", 43 | "text": fileName, 44 | }; 45 | 46 | #Current working directory + file name 47 | filePath = str(os.getcwd()) + "/" + fileName; 48 | 49 | #Add the file to the params 50 | with open(filePath, 'rb') as f: 51 | params['files[' + fileName + ']'] = f.read(); 52 | 53 | #Encode them 54 | params = urllib.urlencode(params); 55 | 56 | #Request/response 57 | request = urllib.urlopen(url, params); 58 | response = request.read(); 59 | 60 | if response.find("success") == -1: 61 | print(response); 62 | else: 63 | print("Successfully sent"); 64 | -------------------------------------------------------------------------------- /Python/TextLink.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | import sys 4 | import urllib2 5 | import urllib 6 | import json 7 | 8 | from pprint import pprint 9 | from CredentialManager import CredentialManager 10 | 11 | ####################################################################### 12 | # Written by Ryan D'souza 13 | # 14 | # Sends a text to myself of a link 15 | # If the link is too long, uses po.st to shorten the link 16 | # 17 | # Dependency: CredentialManager.py 18 | # See: tiny.cc/credentialManager.py 19 | # 20 | # Run: 21 | # python TextLink.py 22 | ####################################################################### 23 | 24 | 25 | def compress_url(url): 26 | JSON = json.loads(urllib.urlopen("http://po.st/api/shorten?longUrl=" + url + "&apiKey=3E5C05F5-DDED-4485-A193-F486E947F547",'r').read()) 27 | return JSON['short_url'] 28 | 29 | 30 | url = "https://api.sendgrid.com/api/mail.send.json" 31 | 32 | credential_manager = CredentialManager() 33 | username, password = credential_manager.get_account('SendGrid') 34 | 35 | to = credential_manager.get_value("PHONE") + "@vtext.com" 36 | from_ = "MBProCL" 37 | 38 | 39 | #If a link has been included as a parameter 40 | if len(sys.argv) == 2: 41 | 42 | #If the link URL is less than 150 chars 43 | if len(sys.argv[1]) <= 150: 44 | bodyText = sys.argv[1] 45 | 46 | #Else, compress it 47 | else: 48 | bodyText = compress_url(sys.argv[1]) 49 | 50 | #Otherwise, just prompt for link 51 | else: 52 | bodyText = raw_input("Enter text content: ") 53 | 54 | if len(bodyText) >= 150: 55 | bodyText = compress_url(bodyText) 56 | 57 | 58 | params = { 59 | "api_user": username, 60 | "api_key": password, 61 | "from": from_, 62 | "to": to, 63 | "subject": " ", 64 | "text": bodyText 65 | } 66 | 67 | params = urllib.urlencode(params) 68 | 69 | request = urllib.urlopen(url, params) 70 | response = request.read() 71 | 72 | if response.find("success") == -1: 73 | print(response) 74 | else: 75 | print("Successfully sent") 76 | -------------------------------------------------------------------------------- /Python/TextPeople.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | import CredentialManager; 3 | import sys; 4 | import urllib2; 5 | import urllib; 6 | 7 | ###################################################### 8 | # Written by Ryan D'souza 9 | # Sends a text to a person using SendGrid's API 10 | # 11 | # Dependencies: CredentialManager 12 | # tiny.cc/credentialManager 13 | # 14 | # Run Instructions: 15 | # python TextPeople.py 16 | ###################################################### 17 | 18 | to = raw_input("To: "); 19 | from_ = raw_input("From: "); 20 | message = raw_input("Message: "); 21 | 22 | #Url for POST request 23 | url = "https://api.sendgrid.com/api/mail.send.json"; 24 | 25 | #My Information 26 | username = CredentialManager.get_value("SendGridUsername"); 27 | password = CredentialManager.get_value("SendGridPassword"); 28 | 29 | params = { 30 | "api_user": username, 31 | "api_key": password, 32 | "from": from_, 33 | "to": to, 34 | "subject": " ", 35 | "text": message 36 | }; 37 | 38 | params = urllib.urlencode(params); 39 | 40 | request = urllib.urlopen(url, params); 41 | response = request.read(); 42 | 43 | if response.find("success") == -1: 44 | print(response); 45 | else: 46 | print("Successfully sent"); 47 | -------------------------------------------------------------------------------- /Python/TextPhone.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | import sys 4 | import urllib2 5 | import urllib 6 | 7 | from CredentialManager import CredentialManager 8 | 9 | ###################################################### 10 | # Written by Ryan D'souza 11 | # Sends a text to myself using SendGrid's API 12 | # 13 | # Dependencies: CredentialManager 14 | # tiny.cc/credentialManager 15 | # 16 | # Run Instructions: 17 | # python TextPhone.py 18 | ###################################################### 19 | 20 | 21 | #If message is commandline argument 22 | if len(sys.argv) == 2: 23 | message = sys.argv[1] 24 | else: 25 | message = raw_input("Enter message: ") 26 | 27 | #Url for POST request 28 | url = "https://api.sendgrid.com/api/mail.send.json" 29 | 30 | #My Information 31 | username, password = CredentialManager().get_account('SendGrid') 32 | from_ = "6099154930" 33 | to = from_ + "@vtext.com" 34 | 35 | params = { 36 | "api_user": username, 37 | "api_key": password, 38 | "from": from_, 39 | "to": to, 40 | "subject": " ", 41 | "text": message 42 | } 43 | 44 | params = urllib.urlencode(params) 45 | 46 | request = urllib.urlopen(url, params) 47 | response = request.read() 48 | 49 | if response.find("success") == -1: 50 | print(response) 51 | else: 52 | print("Successfully sent") 53 | -------------------------------------------------------------------------------- /Python/TextPhoneP.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | import getpass; 3 | import sys; 4 | import urllib2; 5 | import urllib; 6 | 7 | ###################################################### 8 | # Written by Ryan D'souza 9 | # Sends a text to myself using SendGrid's API 10 | # 11 | # Does not use CredentialManager for information 12 | # 13 | # Run Instructions: 14 | # 15 | # python TextPhone 16 | ###################################################### 17 | 18 | 19 | #If message is commandline argument 20 | if len(sys.argv) == 2: 21 | message = sys.argv[1]; 22 | else: 23 | message = raw_input("Enter message: "); 24 | 25 | #Url for POST request 26 | url = "https://api.sendgrid.com/api/mail.send.json"; 27 | 28 | #My Information 29 | username = "dsouzarc"; 30 | password = getpass.getpass("Password: "); 31 | from_ = "6099154930"; 32 | to = from_ + "@vtext.com"; 33 | 34 | params = { 35 | "api_user": username, 36 | "api_key": password, 37 | "from": from_, 38 | "to": to, 39 | "subject": " ", 40 | "text": message 41 | }; 42 | 43 | params = urllib.urlencode(params); 44 | 45 | request = urllib.urlopen(url, params); 46 | response = request.read(); 47 | 48 | if response.find("success") == -1: 49 | print(response); 50 | else: 51 | print("Successfully sent"); 52 | -------------------------------------------------------------------------------- /Python/User-Agent/50useragents.txt: -------------------------------------------------------------------------------- 1 | Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.22 (KHTML, like Gecko) Chrome/25.0.1364.152 Safari/537.22 2 | Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; SIMBAR={A6CB265C-C812-11DF-9AED-90FBA648FE4F}; FunWebProducts; GTB6.6; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; InfoPath.2; AskTB5.6) 3 | Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; YPC 3.2.0; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30; IEMB3; .NET CLR 3.0.04506.648; IEMB3) 4 | Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; GTB7.3; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; OfficeLiveConnector.1.4; OfficeLivePatch.1.3; .NET4.0C; .NET4.0E; BRI/2) 5 | Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1.19) Gecko/20081204 Iceape/1.1.14 (Debian-1.1.14-1) 6 | Mozilla/5.0 (iPod; U; CPU iPhone OS 4_2_1 like Mac OS X; de-de) AppleWebKit/533.17.9 (KHTML, like Gecko) Mobile/8C148 7 | Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0; GTB6.6; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; InfoPath.2) 8 | Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET CLR 1.1.4322; InfoPath.2; .NET4.0C; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; OfficeLiveConnector.1.3; OfficeLivePatch.0.0; Creative AutoUpdate v1.40.01) 9 | Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1) ; InfoPath.1; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022) 10 | Mozilla/5.0 (Windows; U; Windows NT 6.1; de; rv:1.9.1.5) Gecko/20091102 Firefox/3.5.5 GTB6 (.NET CLR 3.5.30729) 11 | Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30; .NET CLR 3.0.04506.648; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; OfficeLiveConnector.1.3; OfficeLivePatch.0.0) 12 | Mozilla/5.0 (X11; Linux i686) AppleWebKit/534.30 (KHTML, like Gecko) Ubuntu/10.10 Chromium/12.0.742.91 Chrome/12.0.742.91 Safari/534.30 13 | Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Embedded Web Browser from: http://bsalsa.com/; .NET CLR 2.0.50727; Creative ZENcast v2.00.13) 14 | Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.24 Safari/536.5 15 | Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.19) Gecko/2010040118 Linux Mint/6 (Felicia) Firefox/3.0.17 16 | Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; GTB6; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; InfoPath.2) 17 | Mozilla/5.0 (Windows; U; Windows NT 5.1; cs; rv:1.9.2.4) Gecko/20100611 AskTbPTV2/3.9.1.14019 Firefox/3.6.4 ( .NET CLR 3.5.30729) 18 | Mozilla/5.0 (Windows; U; Windows NT 5.0; de-DE; rv:1.8.1.14) Gecko/20080406 K-Meleon/1.1.5 19 | Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; InfoPath.2; .NET4.0C; MS-RTC LM 8; MS-RTC EA 2) 20 | Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; Trident/4.0; YTB730; GTB6.4; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; .NET CLR 3.5.30729; .NET CLR 3.0.30729) 21 | Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.65 Safari/537.36 OPR/26.0.1656.32 22 | Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; HPNTDF; .NET4.0C; AskTbMP3R7/5.8.0.12304) 23 | Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; SV1; SLCC1; .NET CLR 2.0.50727; .NET CLR 1.1.4322; InfoPath.2; .NET CLR 3.5.30729; OfficeLiveConnector.1.3; OfficeLivePatch.0.0; .NET CLR 3.0.30618) 24 | Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0; Maxthon; .NET CLR 1.1.4322) 25 | Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0; FunWebProducts; GTB6; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; .NET CLR 1.1.4322; .NET CLR 3.5.30729; .NET CLR 3.0.30729) 26 | Opera/9.80 (Windows NT 5.1; U; be) Presto/2.10.229 Version/11.61 27 | Mozilla/5.0 (Windows NT 5.1) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.152 Safari/535.19 CoolNovo/2.0.3.55 28 | Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0; GTB0.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; AskTB5.6) 29 | Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; SD36; .NET CLR 3.0.04506.30; InfoPath.1; .NET CLR 1.0.3705; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.04506.648) 30 | Mozilla/5.0 (X11; U; Linux i686; sv-SE; rv:1.8.1.16) Gecko/20080715 Firefox/2.0.0.16 pango-text 31 | Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0; GTB6.5; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; .NET CLR 3.5.21022; .NET CLR 3.5.30729; .NET CLR 3.0.30618; .NET4.0C) 32 | Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; Trident/4.0; SIMBAR={72B99746-9C7C-45F6-B63F-184A40180248}; GTB6.5; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; .NET CLR 3.5.30729; .NET CLR 3.0.30729; OfficeLiveConnector.1.5; OfficeLivePatch.1.3; MSN Optimized;SE) 33 | Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; QQDownload 672; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; HPNTDF; .NET4.0C) 34 | Mozilla/5.0 (Macintosh; U; PPC Mac OS X 10.4; de; rv:1.9.1.9) Gecko/20100315 Firefox/3.5.9 35 | Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0; OfficeLiveConnector.1.5; OfficeLivePatch.1.3; .NET4.0C; .NET CLR 3.5.30729) 36 | Mozilla/4.0 (compatible; MSIE 8.0; AOL 9.6; AOLBuild 4340.130; Windows NT 5.1; Trident/4.0; GTB6.6; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; InfoPath.1) 37 | Mozilla/5.0 (Windows; U; Windows NT 6.1; zh-TW; rv:1.9.2.18) Gecko/20110614 Firefox/3.6.18 38 | Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 2.0.50727; .NET CLR 1.1.4322; .NET CLR 3.0.04506.30; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022; .NET CLR 3.5.30428; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729) 39 | Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; GTB6.4; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; eSobiSubscriber 2.0.4.16; .NET4.0C; BRI/1; BRI/2) 40 | Mozilla/5.0 (Linux; U; Android 2.3.6; in-id; GT-S5360 Build/GINGERBREAD) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1 41 | Mozilla/5.0 (X11; U; Linux i686; en-GB; rv:1.9.2.15) Gecko/20110303 Firefox/3.6.15 42 | Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1) ; Embedded Web Browser from: http://bsalsa.com/; EmbeddedWB 14,52 from: http://www.bsalsa.com/ Embedded Web Browser from: http://bsalsa.com/; .NET CLR 2.0.50727; .NET CLR 1.1.4322; .NET CLR 3.0.04506.30) 43 | Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Embedded Web Browser from: http://bsalsa.com/; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30) 44 | Mozilla/5.0 (Windows; U; Windows NT 6.0; tr; rv:1.9.1.10) Gecko/20100504 Firefox/3.5.10 45 | Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30; .NET CLR 1.1.4322; .NET CLR 3.0.04506.648; FDM) 46 | Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3 GTB7.1 ( .NET CLR 3.5.30729; .NET4.0C) 47 | Mozilla/5.0 (Windows; U; Windows NT 5.1; de-DE; rv:1.9.1.2) Gecko/20090729 Firefox/3.5.2 (.NET CLR 3.5.30729) 48 | Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; InfoPath.2; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30; .NET CLR 3.0.04506.648; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729) 49 | Mozilla/5.0 (X11; U; Linux i686 (x86_64); en-US; rv:1.8.0.12) Gecko/20080418 CentOS/1.5.0.12-15.el5.centos Firefox/1.5.0.12 50 | Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; WOW64; Trident/4.0; GTB6.3; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; Media Center PC 5.1; .NET CLR 3.5.30729; .NET CLR 3.0.30618) 51 | -------------------------------------------------------------------------------- /Python/User-Agent/useragenttuner.py: -------------------------------------------------------------------------------- 1 | import random; 2 | 3 | ############################################################################### 4 | #Creates a textfile with X number of useragents chosen at random from fileName 5 | ############################################################################### 6 | 7 | fileName = "useragents.txt"; 8 | 9 | numberOfAgents = int(raw_input("Number of random User-Agents: ")); 10 | 11 | allAgents = []; 12 | 13 | #Add all User-Agents from file to array 14 | with open(fileName, 'r') as file: 15 | for line in file: 16 | allAgents.append(line); 17 | file.close(); 18 | 19 | print("All User-Agents read from file"); 20 | 21 | #Randomly choose X useragents and save them to a file named Xuseragents.txt 22 | file = open(str(numberOfAgents) + fileName, "wb"); 23 | counter = 0; 24 | 25 | while counter < numberOfAgents: 26 | file.write(random.choice(allAgents)); 27 | counter += 1; 28 | 29 | file.close(); 30 | print("Done"); 31 | -------------------------------------------------------------------------------- /Python/iOSAppIconResizer.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | from PIL import Image; 4 | import os; 5 | import sys; 6 | import shutil; 7 | 8 | #Original image 9 | global originalImage; 10 | 11 | #Path to save to: path program run from + directory 'AppIcon' 12 | global saveToPath; 13 | 14 | #Resizes the image and saves it 15 | #width/height are ints, imageDescription is string describing new image 16 | def resizeImage(newWidth, newHeight, imageDescription): 17 | newImage = originalImage.resize((newWidth, newHeight), Image.ANTIALIAS); 18 | 19 | newFileName = saveToPath + "/Icon-" + imageDescription + ".png"; 20 | newImage.save(newFileName, quality=100); 21 | 22 | #If the image name/directory is not inputted, prompt user for it 23 | if len(sys.argv) == 1: 24 | fileName = raw_input("Enter file name and directory:\n"); 25 | 26 | #If image name/directory is inputted as command parameter 27 | else: 28 | fileName = sys.argv[1]; 29 | 30 | #Open the original image 31 | originalImage = Image.open(fileName); 32 | 33 | #Path to save files to (see 'saveToPath' declaration 34 | pathWhenExecuting = os.getcwd(); 35 | saveToPath = pathWhenExecuting + "/AppIcon"; 36 | 37 | #If the 'AppIcon' directory exists, delete it 38 | if os.path.exists(saveToPath): 39 | shutil.rmtree(saveToPath); 40 | 41 | #And remake it 42 | os.makedirs(saveToPath); 43 | 44 | #Creates a copy of the original image, resizes to those dimensions, saves it to disk 45 | resizeImage(180, 180, "iPhone6@3x"); 46 | resizeImage(120, 120, "iOS7-8@2x"); 47 | resizeImage(120, 120, "iPhone4S@2x"); 48 | resizeImage(152, 152, "iPad(mini)@2x"); 49 | resizeImage(76, 76, "iPad2(mini)@1x"); 50 | 51 | #iOS Sizes link: https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/MobileHIG/IconMatrix.html 52 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Written by Ryan D'souza 2 | 3 | A collection of all of my dot files (.vimrc, .bashrc, etc.) and scripts 4 | 5 | Also has some pretty nifty Python files 6 | --------------------------------------------------------------------------------