├── .github └── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md ├── .gitignore ├── .travis.yml ├── CONTRIBUTING.md ├── README.md ├── TODO.md ├── logo ├── pythonista-512.png ├── pythonista.ai └── pythonista.png ├── scripts ├── README.md ├── pdf_merger │ ├── README.md │ └── main.py └── tictactoe │ ├── README.md │ └── main.py └── test └── readme-check ├── README.md ├── main.py └── tests ├── test1 ├── README.md ├── script1 │ └── file.txt └── script2 │ └── file.txt └── test2 ├── README.md ├── script1 └── file.txt └── script2 └── file.txt /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | 5 | --- 6 | 7 | **Describe the bug** 8 | A clear and concise description of what the bug is. 9 | 10 | **To Reproduce** 11 | Steps to reproduce the behavior: 12 | 1. Go to '...' 13 | 2. Click on '....' 14 | 3. Scroll down to '....' 15 | 4. See error 16 | 17 | **Expected behavior** 18 | A clear and concise description of what you expected to happen. 19 | 20 | **Screenshots** 21 | If applicable, add screenshots to help explain your problem. 22 | 23 | **Desktop (please complete the following information):** 24 | - OS: [e.g. iOS] 25 | - Browser [e.g. chrome, safari] 26 | - Version [e.g. 22] 27 | 28 | **Smartphone (please complete the following information):** 29 | - Device: [e.g. iPhone6] 30 | - OS: [e.g. iOS8.1] 31 | - Browser [e.g. stock browser, safari] 32 | - Version [e.g. 22] 33 | 34 | **Additional context** 35 | Add any other context about the problem here. 36 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | 5 | --- 6 | 7 | **Is your feature request related to a problem? Please describe.** 8 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 9 | 10 | **Describe the solution you'd like** 11 | A clear and concise description of what you want to happen. 12 | 13 | **Describe alternatives you've considered** 14 | A clear and concise description of any alternative solutions or features you've considered. 15 | 16 | **Additional context** 17 | Add any other context or screenshots about the feature request here. 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # OS Generated files 2 | .DS_Store -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | git: 2 | depth: 3 3 | 4 | language: python 5 | 6 | python: 7 | - "3.6" 8 | 9 | script: 10 | - python ./test/readme-check/main.py ./scripts ./scripts -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing Guidelines 2 | 3 | We're glad that you want to contribute to Pythonista! You can contribute in many ways, but before you do, ensure that the work you submit is your own or that you have legal authority to submit it as your own. 4 | 5 | - [Contributing Code](#contributing-code) 6 | - [Contributing Documentation](#contributing-documentation) 7 | - [Contriuting In Other Ways](#contributing-in-other-ways) 8 | 9 | ## Contributing Code 10 | 11 | Pythonista is a repository of Python scripts that range from the silly, fun ones to the complicated ones that actually make life a lot easier. In order to contribute a script, you must create a directory within the `scripts` directory with the name of your script, and update the `scripts/README.md` file in accordance with the instructions given there. 12 | 13 | Detailed guidelines for contributing code can be found in `scripts/README.md`. 14 | 15 | **Working on your first Pull Request?** You can learn how from this *free* series [How to Contribute to an Open Source Project on GitHub](https://egghead.io/series/how-to-contribute-to-an-open-source-project-on-github) 16 | 17 | **Contributions that do not pass all status checks will not be accepted unless there's a very good reason to accept them** 18 | 19 | ## Contributing Documentation 20 | 21 | Being a collection of code from a bunch of people, it is very important that everything about Pythonista is well documented. Currently, the `README.md` file needs completion. You can check out the `TODO.md` file to see if there are any missing pieces of documentation that need work. 22 | 23 | ## Contributing In Other Ways 24 | 25 | Your contributions don't have to be limited to code or documentation. You can be a part of the Pythonista community and help us grow in many other ways including: 26 | - Opening issues with helpful suggestions or bug reports 27 | - Helping us close issues by contributing appropriately 28 | - Letting us know about deprecated code or out-of-date dependencies 29 | 30 | All of these ways involve using the GitHub Issue Tracker to communicate with us, so please take care to avoid saying things that may be offensive or unrelated, and make sure that every discussion is carried out in good spirit. 31 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 |

4 | 5 | # pythonista 6 | 7 | [![Build Status](https://travis-ci.org/pyista/pythonista.svg?branch=master)](https://travis-ci.org/pyista/pythonista) 8 | [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](http://makeapullrequest.com) 9 | [![first-timers-only Friendly](https://img.shields.io/badge/first--timers--only-friendly-blue.svg)](http://www.firsttimersonly.com/) 10 |
11 | Pythonista is a collection of Python scripts of all kinds - from simple hacks for automation to more complex tooling. -------------------------------------------------------------------------------- /TODO.md: -------------------------------------------------------------------------------- 1 | The following tasks are currently waiting to be completed. PRs are welcome! 2 | 3 | ## Documentation 4 | - [ ] Complete CONTRIBUTING.md 5 | - [ ] Complete README.md -------------------------------------------------------------------------------- /logo/pythonista-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyista/pythonista/5e4c2fe08195d293013ad6317580f4e983caf9e1/logo/pythonista-512.png -------------------------------------------------------------------------------- /logo/pythonista.ai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyista/pythonista/5e4c2fe08195d293013ad6317580f4e983caf9e1/logo/pythonista.ai -------------------------------------------------------------------------------- /logo/pythonista.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyista/pythonista/5e4c2fe08195d293013ad6317580f4e983caf9e1/logo/pythonista.png -------------------------------------------------------------------------------- /scripts/README.md: -------------------------------------------------------------------------------- 1 | This directory contains all the scripts in the repo. 2 | 3 | ## Contents 4 | 1. [Guidelines](#guidelines) 5 | 2. [Template](#template) 6 | 3. [Scripts](#script) 7 | 8 | ## Guidelines 9 | - Each script should be in it's own seperate directory. 10 | - The script name must be same as the directory name of the script. 11 | - All scripts should be invokable as `python main.py`. That is, the file that is to be called by the python interpreter should be named `main.py`. 12 | - If your script has dependencies, it should contain a `requirements.txt`. 13 | - All the scripts must follow [PEP 8 Style Guidelines](https://www.python.org/dev/peps/pep-0008/). 14 | - Each script directory should contain a `README.md` file with installation and usage instructions, description, and any other information needed. 15 | - You should also edit this README and add your script to it in accordance with the [template](#template). 16 | - If the script you are contributing is under version control, make sure you add it as a [git submodule](https://git-scm.com/book/en/v2/Git-Tools-Submodules). 17 | - Any contributions that fail the status checks will not be accepted unless there is a very good reason to accept them. 18 | - When adding scripts to the `scripts/README.md` file, keep the following points in mind to prevent the CI status check from failing: 19 | * The template is followed perfectly. 20 | * The name of the directory containing the script is the same as the name of the script in `scripts/README.md`. 21 | * The comments that delimit the scripts section are not altered. 22 | * You add your script **between** the `scriptsstart` and `scriptsstop` comments. 23 | 24 | ## Template 25 | Your contribution should update this README with the following information, and in accordance with this template: 26 | 27 | - script-name
28 | Description
29 | [Author's Name](#) 30 | 31 | ## Scripts 32 | 33 | - tictactoe
34 | A cli-based tictactoe game to play with the computer.
35 | [Rounak Vyas](http://www.github.com/itsron717) 36 | - pdf_merger
37 | A pdf merger to combine multiple PDFs into a single PDF.
38 | [Anshul Hajare](https://github.com/AnshulH) 39 | 40 | -------------------------------------------------------------------------------- /scripts/pdf_merger/README.md: -------------------------------------------------------------------------------- 1 | # PDF Merger 2 | A python script to merge multiple pdfs into a single pdf.
3 | Supports only Python 3.x and Unix Based OS. 4 | 5 | ## Usage 6 | ``` 7 | $ pip3 install PyPDF2 8 | ``` 9 | 10 | ``` 11 | $ python main.py pdf1.pdf pdf2.pdf pdf3.pdf ... 12 | ``` 13 | > the PDFs are merged into a single PDF called merged_pdf.pdf 14 | -------------------------------------------------------------------------------- /scripts/pdf_merger/main.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | import os 3 | import PyPDF2 4 | 5 | parser = argparse.ArgumentParser() 6 | parser.add_argument('--paths', nargs='*', help='PDF paths') 7 | args = parser.parse_args() 8 | # print(args.paths) 9 | 10 | 11 | def PDFmerge(pdfs, output): 12 | 13 | pdfMerger = [] 14 | pdfWriter = PyPDF2.PdfFileWriter() 15 | 16 | for pdf in pdfs: 17 | pdfMerger.append(pdf) 18 | for file in pdfMerger: 19 | pdfFileobj = open(file, 'rb') 20 | pdfReader = PyPDF2.PdfFileReader(pdfFileobj) 21 | for page in range(pdfReader.numPages): 22 | pageObj = pdfReader.getPage(page) 23 | pdfWriter.addPage(pageObj) 24 | pdfOutput = open(output, 'wb') 25 | pdfWriter.write(pdfOutput) 26 | print('Merged Successfully') 27 | 28 | 29 | if __name__ == "__main__": 30 | output = 'merged_pdf.pdf' 31 | PDFmerge(args.paths, output) 32 | -------------------------------------------------------------------------------- /scripts/tictactoe/README.md: -------------------------------------------------------------------------------- 1 | # TicTacToe 2 | Playing Tic-Tac-Toe with the computer right in the terminal. The game can be played using the number keypad. It follows the same structure as the tic tac toe board -
3 | 7 | 8 | 9
4 | 4 | 5 | 6
5 | 1 | 2 | 3
6 | 7 | ## Usage 8 | `python main.py` 9 | 10 | -------------------------------------------------------------------------------- /scripts/tictactoe/main.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | from sys import stdout 3 | import random 4 | import time 5 | global board 6 | board = ['z', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '] 7 | global unit 8 | global comp_unit 9 | unit = str(input("Choose Your Symbol( 1 or 0 ) : ")) 10 | if unit == '1': 11 | comp_unit = '0' 12 | else: 13 | comp_unit = '1' 14 | 15 | print("Places are corresponding to your KeyPad") 16 | """unit= random.choice('X 0'.split()) 17 | if unit =='X': 18 | comp_unit='0' 19 | else: 20 | comp_unit= 'X'""" 21 | 22 | 23 | def board_print(): 24 | 25 | bo = ''' 26 | %s | %s | %s 27 | --------- 28 | %s | %s | %s 29 | --------- 30 | %s | %s | %s 31 | ---------''' % (board[7], board[8], board[9], board[4], board[5], board[6], board[1], board[2], board[3]) 32 | 33 | print(bo) 34 | 35 | 36 | def victory(var): 37 | bo = board 38 | end = False 39 | if (bo[1] == var and bo[2] == var and bo[3] == var): 40 | end = True 41 | elif (bo[4] == var and bo[5] == var and bo[6] == var): 42 | end = True 43 | elif (bo[7] == var and bo[8] == var and bo[9] == var): 44 | end = True 45 | elif (bo[1] == var and bo[4] == var and bo[7] == var): 46 | end = True 47 | elif (bo[2] == var and bo[5] == var and bo[8] == var): 48 | end = True 49 | elif (bo[3] == var and bo[6] == var and bo[9] == var): 50 | end = True 51 | elif (bo[1] == var and bo[5] == var and bo[9] == var): 52 | end = True 53 | elif (bo[3] == var and bo[5] == var and bo[7] == var): 54 | end = True 55 | return end 56 | 57 | 58 | def enter(a, pos): 59 | board[pos] = a 60 | board_print() 61 | 62 | 63 | def comp_enter(): 64 | cvic = 0 65 | for i in range(1, 10): 66 | if board[i] == ' ': 67 | board[i] = comp_unit 68 | if victory(comp_unit): 69 | cvic = 1 70 | break 71 | else: 72 | board[i] = ' ' 73 | board[i] = unit 74 | if victory(unit): 75 | board[i] = comp_unit 76 | cvic = 1 77 | break 78 | else: 79 | board[i] = ' ' 80 | 81 | if cvic != 1: 82 | if board[5] == ' ': 83 | board[5] = comp_unit 84 | else: 85 | if (board[1] == ' ' or board[3] == ' ' or board[7] == ' ' or board[9] == ' ') and ((board[1] != unit and board[9] != unit)and(board[3] != unit and board[7] != unit)): 86 | ran1 = int(random.sample([1, 3, 7, 9], 1)[0]) 87 | while board[ran1] != ' ': 88 | ran1 = int(random.sample([1, 3, 7, 9], 1)[0]) 89 | board[ran1] = comp_unit 90 | else: 91 | ran1 = int(random.sample([2, 4, 5, 6, 8], 1)[0]) 92 | while board[ran1] != ' ': 93 | ran1 = int(random.sample([2, 4, 5, 8], 1)[0]) 94 | board[ran1] = comp_unit 95 | 96 | 97 | while ' ' in board: 98 | pos = int(input('Enter where to place your %s : ' % (unit))) 99 | while board[pos] != ' ': 100 | print('This place already has a value') 101 | pos = int(input('Enter where to place your %s : ' % (unit))) 102 | enter(unit, pos) 103 | end = victory(unit) 104 | if end == True: 105 | print("Player wins") 106 | break 107 | if ' ' in board: 108 | comp_enter() 109 | print("Computer's move.....") 110 | t = 3 111 | while t > 0: 112 | stdout.write("\r%d" % t) 113 | stdout.flush() 114 | time.sleep(1) 115 | t -= 1 116 | print('\n') 117 | board_print() 118 | if victory(comp_unit): 119 | print("Computer wins") 120 | break 121 | 122 | else: 123 | print('Game Over , Its a draw') 124 | -------------------------------------------------------------------------------- /test/readme-check/README.md: -------------------------------------------------------------------------------- 1 | # readme-check 2 | 3 | This script is a test written for the [pythonista](https://github.com/pyista/pythonista) repository. It ensures that every directory in the `scripts` folder has a corresponding entry in `scripts/README.md` and vice versa. This is to help contributors who forget to update the readme quickly realize their mistake and fix it. 4 | 5 | ## Usage 6 | 7 | 1. Make the script executable - `$ chmod +x path/to/script/main.py` 8 | 2. Execute the script - `$ path/to/script/main.py path/to/readme path/to/scripts` 9 | 10 | The script exits with a non-zero exit code if there is an inconsistency in the directories in the `scripts` folder and the scripts listed in `scripts/README.md`. 11 | 12 | In the use case of [pythonista](https://github.com/pyista/pythonista) (and in almost every use case) the `README.md` file resides in the same folder as all the scripts, so we invoke it as follows (from the project root):
13 | `$ ./test/readme-check/main.py ./scripts ./scripts`. 14 | 15 | ## Running Tests 16 | 17 | Since this is a minimal utility script, a couple of test cases have been written in the `run_tests` method in the script. These correspond to use cases that are shown in the `tests/test1` and `tests/test2` folders. You can run the tests by running:
18 | `$ ./test/readme-check/main.py test`. 19 | 20 | ## Author 21 | 22 | This script was authored by [Mohammed Ajmal Siddiqui](https://github.com/ajmalsiddiqui) for the [pythonista](https://github.com/pyista/pythonista) project. 23 | -------------------------------------------------------------------------------- /test/readme-check/main.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from pathlib import Path 4 | import os 5 | import re 6 | import sys 7 | 8 | # TODO: Add docstring specifying that path_to_readme is an instance of PosixPath 9 | 10 | 11 | def read_readme(path_to_readme): 12 | path_to_readme = path_to_readme / "README.md" 13 | readme = open(path_to_readme, "r").read() 14 | 15 | return readme 16 | 17 | # TODO: path_to_scripts is a Path object. Make docstring 18 | 19 | 20 | def get_scripts_list(path_to_scripts): 21 | # path_to_scripts = Path(path_to_scripts) 22 | dir_list = [dirname for dirname in os.listdir( 23 | path_to_scripts) if os.path.isdir(os.path.join(path_to_scripts, dirname))] 24 | 25 | return dir_list 26 | 27 | 28 | def get_titles_from_readme(readme): 29 | # Note: All of this can be done in fewer steps 30 | # This is just for readibility 31 | scripts = readme.split("")[1] 32 | scripts = scripts.split("")[0] 33 | scripts = scripts.split("-\t")[1:] 34 | scripts = [re.split(r"\n|
|", script)[0] for script in scripts] 35 | scripts = [re.sub(r'[\n|\t]*', "", script) for script in scripts] 36 | 37 | return scripts 38 | 39 | 40 | def test_scripts(path_to_readme, path_to_scripts): 41 | titles = get_titles_from_readme(read_readme(path_to_readme)) 42 | scripts = get_scripts_list(path_to_scripts) 43 | 44 | return set(titles) == set(scripts) 45 | 46 | # TODO add docstring 47 | 48 | 49 | def run_tests(): 50 | print("[readme-check] Running tests...") 51 | test1_dir = Path(os.path.dirname(__file__) + "/tests/test1") 52 | test2_dir = Path(os.path.dirname(__file__) + "/tests/test2") 53 | 54 | test1 = test_scripts(test1_dir, test1_dir) 55 | test2 = test_scripts(test2_dir, test2_dir) 56 | 57 | print("[readme-check] Test 1 complete.\nExpected output: {}\nActual output: {}\n".format(True, test1)) 58 | print("[readme-check] Test 2 complete.\nExpected output: {}\nActual output: {}\n".format(False, test2)) 59 | 60 | if test1 and not test2: 61 | print("[readme-check] All test cases passed!") 62 | return True 63 | 64 | print("[readme-check] Some test cases failed.") 65 | return False 66 | 67 | 68 | if __name__ == "__main__": 69 | try: 70 | if sys.argv[1] == "test": 71 | if not run_tests(): 72 | sys.exit(1) 73 | else: 74 | sys.exit(0) 75 | README_PATH = Path(sys.argv[1]) 76 | SCRIPTS_PATH = Path(sys.argv[2]) 77 | if test_scripts(README_PATH, SCRIPTS_PATH): 78 | print("[readme-check] README check passed. Everything looks fine!") 79 | sys.exit(0) 80 | else: 81 | print("[readme-check] README check failed. Ensure that you've updated the README.md file in the scripts folder and that the name of the script matches the name of the directory.") 82 | sys.exit(1) 83 | except Exception: 84 | print("[readme-check] Error: Something went wrong. Did you forget to give the path to README.md or the path to scripts?") 85 | sys.exit(2) 86 | -------------------------------------------------------------------------------- /test/readme-check/tests/test1/README.md: -------------------------------------------------------------------------------- 1 | # Sample Readme for Test 1 2 | 3 | This is a sample README.md file to demonstrate and test the script. The directories in this file are dummies. Currently, this test should pass. 4 | 5 | # Scripts 6 | 7 | - script1
8 | This is a dummy script 9 | [Author 1](#) 10 | 11 | - script2 12 | This is also a dummy script 13 | [Author 2](#) 14 | -------------------------------------------------------------------------------- /test/readme-check/tests/test1/script1/file.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyista/pythonista/5e4c2fe08195d293013ad6317580f4e983caf9e1/test/readme-check/tests/test1/script1/file.txt -------------------------------------------------------------------------------- /test/readme-check/tests/test1/script2/file.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyista/pythonista/5e4c2fe08195d293013ad6317580f4e983caf9e1/test/readme-check/tests/test1/script2/file.txt -------------------------------------------------------------------------------- /test/readme-check/tests/test2/README.md: -------------------------------------------------------------------------------- 1 | # Sample Readme for Test 2 2 | 3 | This is a sample README.md file to demonstrate and test the script. The directories in this file are dummies. Currently, this test should fail. 4 | 5 | # Scripts 6 | 7 | - script1 8 | This is a dummy script 9 | [Author 1](#) 10 | -------------------------------------------------------------------------------- /test/readme-check/tests/test2/script1/file.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyista/pythonista/5e4c2fe08195d293013ad6317580f4e983caf9e1/test/readme-check/tests/test2/script1/file.txt -------------------------------------------------------------------------------- /test/readme-check/tests/test2/script2/file.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pyista/pythonista/5e4c2fe08195d293013ad6317580f4e983caf9e1/test/readme-check/tests/test2/script2/file.txt --------------------------------------------------------------------------------