From 32bdc6a28705ace238f7dfd11f3e7dc0709ef424 Mon Sep 17 00:00:00 2001 From: Roland Thomas Date: Wed, 23 Aug 2023 11:11:51 -0400 Subject: [PATCH] Initial commit --- .gitignore | 160 +++++++++++++++++++++++++++++ email_example.py | 22 ++++ freq.py | 26 +++++ patch_example.py | 22 ++++ print_things.py | 3 + pyqttt.py | 59 +++++++++++ rand_char.py | 9 ++ readline/creatures.py | 59 +++++++++++ readline/mtg.py | 29 ++++++ readline/readline_auto_complete.py | 92 +++++++++++++++++ readline/readline_calc.py | 54 ++++++++++ readline/readline_cmd.py | 66 ++++++++++++ readline/readline_test.py | 39 +++++++ set_get_attr_example.py | 34 ++++++ test.py | 19 ++++ textfile | 1 + 16 files changed, 694 insertions(+) create mode 100644 .gitignore create mode 100644 email_example.py create mode 100644 freq.py create mode 100644 patch_example.py create mode 100644 print_things.py create mode 100644 pyqttt.py create mode 100644 rand_char.py create mode 100644 readline/creatures.py create mode 100644 readline/mtg.py create mode 100644 readline/readline_auto_complete.py create mode 100644 readline/readline_calc.py create mode 100644 readline/readline_cmd.py create mode 100644 readline/readline_test.py create mode 100644 set_get_attr_example.py create mode 100644 test.py create mode 100644 textfile diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..68bc17f --- /dev/null +++ b/.gitignore @@ -0,0 +1,160 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +.pybuilder/ +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +# For a library or package, you might want to ignore these files since the code is +# intended to run in multiple environments; otherwise, check them in: +# .python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# poetry +# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. +# This is especially recommended for binary packages to ensure reproducibility, and is more +# commonly ignored for libraries. +# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control +#poetry.lock + +# pdm +# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. +#pdm.lock +# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it +# in version control. +# https://pdm.fming.dev/#use-with-ide +.pdm.toml + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# pytype static type analyzer +.pytype/ + +# Cython debug symbols +cython_debug/ + +# PyCharm +# JetBrains specific template is maintained in a separate JetBrains.gitignore that can +# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore +# and can be added to the global gitignore or merged into this file. For a more nuclear +# option (not recommended) you can uncomment the following to ignore the entire idea folder. +#.idea/ diff --git a/email_example.py b/email_example.py new file mode 100644 index 0000000..9129687 --- /dev/null +++ b/email_example.py @@ -0,0 +1,22 @@ +# Import smtplib for the actual sending function +import smtplib + +# Import the email modules we'll need +from email.message import EmailMessage +textfile = 'textfile' +# Open the plain text file whose name is in textfile for reading. +with open(textfile) as fp: + # Create a text/plain message + msg = EmailMessage() + msg.set_content(fp.read()) + +# me == the sender's email address +# you == the recipient's email address +msg['Subject'] = f'The contents of {textfile}' +msg['From'] = 'roland@rtj.dev' +msg['To'] = 'roland@rtj.dev' + +# Send the message via our own SMTP server. +s = smtplib.SMTP('localhost') +s.send_message(msg) +s.quit() diff --git a/freq.py b/freq.py new file mode 100644 index 0000000..fa2f3df --- /dev/null +++ b/freq.py @@ -0,0 +1,26 @@ +# Most frequently used words in a text + +from collections import Counter +from string import ascii_letters + +def top_3_words(text): + letters = set([x for x in ascii_letters]) + letters.add('\'') + letters.add(' ') + cleaned_text = ''.join([x.lower() for x in text if x in letters]) + text_counter = Counter([word for word in cleaned_text.split()]) + del text_counter["\'"] + keys_to_delete = [] + for key in text_counter: + new = Counter(key) + if new['\''] > 1: + keys_to_delete.append(key) + for key in keys_to_delete: + del text_counter[key] + return sorted(text_counter, key=text_counter.get, reverse=True)[:3] + +print(top_3_words("a a a b c c d d d d e e e e e")) +print(top_3_words(" //wont won't won't ")) +print(top_3_words("e e e e DDD ddd DdD: ddd ddd aa aA Aa, bb cc cC e e e")) +print(top_3_words(" ' ")) +print(top_3_words(" ''' ")) \ No newline at end of file diff --git a/patch_example.py b/patch_example.py new file mode 100644 index 0000000..e186122 --- /dev/null +++ b/patch_example.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python3 + +import unittest +from io import StringIO +from unittest.mock import patch +import print_things # import the module containing the function with print statements + +class TestPrintFunction(unittest.TestCase): + + def test_print_example(self): + # The expected output of the print statement + expected_output = "the world\n" + + # Using a context manager to temporarily replace sys.stdout with a StringIO object + with patch('sys.stdout', new=StringIO()) as captured_output: + print_things.print_the_world() # Call the function that has the print statement + + # Assert the captured output is equal to the expected output + self.assertEqual(captured_output.getvalue(), expected_output) + +if __name__ == '__main__': + unittest.main() diff --git a/print_things.py b/print_things.py new file mode 100644 index 0000000..f07bd39 --- /dev/null +++ b/print_things.py @@ -0,0 +1,3 @@ + +def print_the_world(): + print("the world") diff --git a/pyqttt.py b/pyqttt.py new file mode 100644 index 0000000..9779490 --- /dev/null +++ b/pyqttt.py @@ -0,0 +1,59 @@ +import sys +from PyQt5.QtWidgets import QApplication, QMainWindow, QTabWidget, QWidget, QGridLayout, QLabel + +class TabbedWindow(QMainWindow): + def __init__(self): + super().__init__() + + # Set the main window title and size + self.setWindowTitle("Tabbed Window") + self.resize(300, 300) + + # Create a tab widget + self.tab_widget = QTabWidget() + self.setCentralWidget(self.tab_widget) + + # Create the first tab + self.tab1 = QWidget() + self.tab_widget.addTab(self.tab1, "1-100") + + # Create a grid layout for the first tab + layout1 = QGridLayout() + layout1.setHorizontalSpacing(10) + layout1.setVerticalSpacing(10) + + # Add the numbers 1-100 to the layout + for i in range(1, 101): + column = (i - 1) % 10 + row = (i - 1) // 10 + label = QLabel(str(i)) + layout1.addWidget(label, row, column) + + # Set the layout for the first tab + self.tab1.setLayout(layout1) + + # Create the second tab + self.tab2 = QWidget() + self.tab_widget.addTab(self.tab2, "101-200") + + # Create a grid layout for the second tab + layout2 = QGridLayout() + layout2.setHorizontalSpacing(10) + layout2.setVerticalSpacing(10) + + # Add the numbers 101-200 to the layout + for i in range(101, 201): + column = (i - 101) % 10 + row = (i - 101) // 10 + label = QLabel(str(i)) + layout2.addWidget(label, row, column) + + # Set the layout for the second tab + self.tab2.setLayout(layout2) + +if __name__ == '__main__': + app = QApplication(sys.argv) + window = TabbedWindow() + window.show() + sys.exit(app.exec_()) + diff --git a/rand_char.py b/rand_char.py new file mode 100644 index 0000000..ead84c9 --- /dev/null +++ b/rand_char.py @@ -0,0 +1,9 @@ +import random + +characters = '' +try: + characters = ''.join([chr(random.choice([i for i in range(0x0, 0xD7FF + 1) if i < 0xD800 or i > 0xDFFF])) for _ in range(5000)]) +except UnicodeEncodeError as e: + print(f"Error encoding character: {e}") + +print(characters) diff --git a/readline/creatures.py b/readline/creatures.py new file mode 100644 index 0000000..eecac57 --- /dev/null +++ b/readline/creatures.py @@ -0,0 +1,59 @@ +import readline + +creatures = [] + +def add_creature(): + creature = input("Enter a creature name: ") + creatures.append(creature) + print(f"{creature} added to the list of creatures.") + +def lookup_creature(): + def completer(text, state): + options = [c for c in creatures if c.startswith(text)] + if state < len(options): + return options[state] + else: + return None + + readline.set_completer(completer) + readline.parse_and_bind("tab: complete") + + print("List of creatures:") + for creature in creatures: + print(f"- {creature}") + + while True: + creature = input("Enter the name of a creature or press enter to return to the main menu: ") + if not creature: + break + elif creature in creatures: + print(f"{creature} found!") + else: + print(f"{creature} not found.") + + readline.set_completer(None) + readline.parse_and_bind("tab: ") + +def quit(): + print("Goodbye!") + exit() + +menu = { + "1": add_creature, + "2": lookup_creature, + "3": quit +} + +while True: + print("Menu:") + print("[1] Add Creature") + print("[2] Lookup Creature") + print("[3] Quit") + + choice = input("Enter your choice: ") + action = menu.get(choice) + if action: + action() + else: + print(f"{choice} is not a valid option.") + diff --git a/readline/mtg.py b/readline/mtg.py new file mode 100644 index 0000000..0beb551 --- /dev/null +++ b/readline/mtg.py @@ -0,0 +1,29 @@ +import cmd + +completions = [ + 'Mage Slayer (Alara Reborn)', + 'Magefire Wings (Alara Reborn)', + 'Sages of the Anima (Alara Reborn)', + 'Sanctum Plowbeast (Alara Reborn)', + 'Sangrite Backlash (Alara Reborn)', + 'Sanity Gnawers (Alara Reborn)', + 'Sen Triplets (Alara Reborn)' +] + +class mycmd(cmd.Cmd): + def __init__(self): + cmd.Cmd.__init__(self) + + def do_quit(self, s): + return True + + def do_add(self, s): + pass + + def complete_add(self, text, line, begidx, endidx): + mline = line.partition(' ')[2] + offs = len(mline) - len(text) + return [s[offs:] for s in completions if s.startswith(mline)] + +if __name__ == '__main__': + mycmd().cmdloop() diff --git a/readline/readline_auto_complete.py b/readline/readline_auto_complete.py new file mode 100644 index 0000000..6e68a68 --- /dev/null +++ b/readline/readline_auto_complete.py @@ -0,0 +1,92 @@ +import cmd +import os +import readline +import sys + +# Set up history file +histfile = os.path.join(os.path.expanduser('~'), '.history') +try: + readline.read_history_file(histfile) +except FileNotFoundError: + open(histfile, 'wb').close() + +# Define add and subtract functions +def add(x, y): + return x + y + +def subtract(x, y): + return x - y + +# Define command processor +class MyCmd(cmd.Cmd): + prompt = '> ' + intro = 'Type help for commands' + + def do_exit(self, arg): + """Exit the program""" + return True + + def do_add(self, arg): + """Add two numbers: add """ + try: + num1, num2 = map(float, arg.split()) + except ValueError: + print('Invalid input') + return + print(add(num1, num2)) + + def complete_add(self, text, line, begidx, endidx): + if not text: + completions = ['', ''] + elif '' in line: + completions = [''] + else: + completions = [''] + return [c for c in completions if c.startswith(text)] + + def do_subtract(self, arg): + """Subtract two numbers: subtract """ + try: + num1, num2 = map(float, arg.split()) + except ValueError: + print('Invalid input') + return + print(subtract(num1, num2)) + + def complete_subtract(self, text, line, begidx, endidx): + if not text: + completions = ['', ''] + elif '' in line: + completions = [''] + else: + completions = [''] + return [c for c in completions if c.startswith(text)] + + def do_clear(self, arg): + """Clear the screen""" + if sys.platform.startswith('win'): + os.system('cls') + else: + os.system('clear') + + def default(self, line): + print('Invalid command') + + def emptyline(self): + pass + +# Run command processor +console = MyCmd() +readline.set_completer_delims(' \t\n;') +readline.parse_and_bind('tab: complete') +while True: + try: + line = input(console.prompt) + except EOFError: + break + console.onecmd(line) + +# Save history file +with open(histfile, 'w') as f: + readline.write_history_file(histfile) + diff --git a/readline/readline_calc.py b/readline/readline_calc.py new file mode 100644 index 0000000..13c089f --- /dev/null +++ b/readline/readline_calc.py @@ -0,0 +1,54 @@ +import readline + +# Set up history file +histfile = '.history' +try: + readline.read_history_file(histfile) +except FileNotFoundError: + open(histfile, 'wb').close() + +# Define add and subtract functions +def add(x, y): + return x + y + +def subtract(x, y): + return x - y + +# Loop for user input +while True: + # Read user input + try: + line = input('> ') + except EOFError: + break + + # Check for exit command + if line == 'exit': + break + + # Parse user input + try: + args = line.split() + if len(args) != 3: + raise ValueError + num1 = float(args[0]) + num2 = float(args[2]) + op = args[1] + if op not in ['+', '-']: + raise ValueError + except ValueError: + print('Invalid input') + continue + + # Perform operation + if op == '+': + result = add(num1, num2) + else: + result = subtract(num1, num2) + + # Print result and add command to history + print(result) + readline.add_history(line) + +# Save history file +readline.write_history_file(histfile) diff --git a/readline/readline_cmd.py b/readline/readline_cmd.py new file mode 100644 index 0000000..a65c130 --- /dev/null +++ b/readline/readline_cmd.py @@ -0,0 +1,66 @@ +import cmd +import os +import readline + +# Set up history file +histfile = os.path.join(os.path.expanduser('~'), '.history') +try: + readline.read_history_file(histfile) +except FileNotFoundError: + open(histfile, 'wb').close() + +# Define add and subtract functions +def add(x, y): + return x + y + +def subtract(x, y): + return x - y + +# Define command processor +class MyCmd(cmd.Cmd): + prompt = '> ' + intro = 'Type help for commands' + + def do_exit(self, arg): + """Exit the program""" + return True + + def do_add(self, arg): + """Add two numbers: add """ + try: + num1, num2 = map(float, arg.split()) + except ValueError: + print('Invalid input') + return + print(add(num1, num2)) + + def do_subtract(self, arg): + """Subtract two numbers: subtract """ + try: + num1, num2 = map(float, arg.split()) + except ValueError: + print('Invalid input') + return + print(subtract(num1, num2)) + + def default(self, line): + print('Invalid command') + + def emptyline(self): + pass + +# Run command processor +console = MyCmd() +readline.set_completer_delims(' \t\n;') +readline.parse_and_bind('tab: complete') +while True: + try: + line = input(console.prompt) + except EOFError: + break + console.onecmd(line) + +# Save history file +with open(histfile, 'w') as f: + readline.write_history_file(histfile) + diff --git a/readline/readline_test.py b/readline/readline_test.py new file mode 100644 index 0000000..159e6ea --- /dev/null +++ b/readline/readline_test.py @@ -0,0 +1,39 @@ +import atexit +import code +import os +import readline + +class HistoryConsole(code.InteractiveConsole): + def __init__(self, locals=None, filename="", + histfile=os.path.expanduser("~/.console-history")): + code.InteractiveConsole.__init__(self, locals, filename) + self.init_history(histfile) + + def init_history(self, histfile): + readline.parse_and_bind("tab: complete") + if hasattr(readline, "read_history_file"): + try: + readline.read_history_file(histfile) + except FileNotFoundError: + pass + atexit.register(self.save_history, histfile) + + def save_history(self, histfile): + readline.set_history_length(1000) + readline.write_history_file(histfile) + + +# Run console +console = HistoryConsole() +while True: + try: + line = input('> ') + except EOFError: + break + + # Check for exit command + if line == 'exit': + break + + # Process user input + console.push(line) diff --git a/set_get_attr_example.py b/set_get_attr_example.py new file mode 100644 index 0000000..d246eed --- /dev/null +++ b/set_get_attr_example.py @@ -0,0 +1,34 @@ + +class Number: + def __init__(self, number): + self._number = number + + def power(self): + self._number = self.number * self.number + + def another_func(self): + print("In another function") + + def __setattr__(self, name, value): + # print(name, type(name), value, type(value)) + super().__setattr__('_number', 0) + try: + if isinstance(value, int): + super().__setattr__('_number', value) + elif isinstance(value, str): + super().__setattr__('_number', int(value)) + except ValueError: + return + + def __getattribute__(self, name): + options = ['power', 'another_func', '__class__'] + if name in options: + return super().__getattribute__(name) + else: + return super().__getattribute__('_number') + + def __str__(self): + return str(self._number) + + def __getattr__(self, name): + return self._number diff --git a/test.py b/test.py new file mode 100644 index 0000000..8a0b163 --- /dev/null +++ b/test.py @@ -0,0 +1,19 @@ +import unittest + +class Yest(unittest.TestCase): + def test_int(self): + n1 = 5 + self.assertIsInstance(n1, int, "n1 should be an int"), "asldfkjalsdfjsld" + int("124124"), "Another string here", "You can do that" + a = 5 + self.assertIsInstance(a, int) + + asdf = "I know you can do this.","","","",(55,55),[124,4124],1242142 + print(type(asdf), asdf) + assert isinstance(n1, int),235235252 + +words = ['asdf', '124'] +words.sort( key=lambda an_elem: an_elem[1] ) +print(words) + +unittest.main() \ No newline at end of file diff --git a/textfile b/textfile new file mode 100644 index 0000000..4e9552a --- /dev/null +++ b/textfile @@ -0,0 +1 @@ +Test email