├── .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 | [](https://travis-ci.org/pyista/pythonista)
8 | [](http://makeapullrequest.com)
9 | [](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
--------------------------------------------------------------------------------