diff --git a/AI Game/Tic-Tac-Toe-AI/tictactoe.py b/AI Game/Tic-Tac-Toe-AI/tictactoe.py new file mode 100644 index 00000000000..6157ff6efb0 --- /dev/null +++ b/AI Game/Tic-Tac-Toe-AI/tictactoe.py @@ -0,0 +1,104 @@ +import tkinter as tk #provides a library of basic elements of GUI widgets +from tkinter import messagebox #provides a different set of dialogues that are used to display message boxes +import random + +def check_winner(board, player): + # Check rows, columns, and diagonals for a win + for i in range(3): + if all(board[i][j] == player for j in range(3)) or all(board[j][i] == player for j in range(3)): + return True + if all(board[i][i] == player for i in range(3)) or all(board[i][2 - i] == player for i in range(3)): + return True + return False + +def is_board_full(board): + return all(all(cell != ' ' for cell in row) for row in board) + +def minimax(board, depth, is_maximizing): + if check_winner(board, 'X'): + return -1 + if check_winner(board, 'O'): + return 1 + if is_board_full(board): #if game is full, terminate + return 0 + + if is_maximizing: #recursive approach that fills board with Os + max_eval = float('-inf') + for i in range(3): + for j in range(3): + if board[i][j] == ' ': + board[i][j] = 'O' + eval = minimax(board, depth + 1, False) #recursion + board[i][j] = ' ' + max_eval = max(max_eval, eval) + return max_eval + else: #recursive approach that fills board with Xs + min_eval = float('inf') + for i in range(3): + for j in range(3): + if board[i][j] == ' ': + board[i][j] = 'X' + eval = minimax(board, depth + 1, True) #recursion + board[i][j] = ' ' + min_eval = min(min_eval, eval) + return min_eval + +#determines the best move for the current player and returns a tuple representing the position +def best_move(board): + best_val = float('-inf') + best_move = None + + for i in range(3): + for j in range(3): + if board[i][j] == ' ': + board[i][j] = 'O' + move_val = minimax(board, 0, False) + board[i][j] = ' ' + if move_val > best_val: + best_val = move_val + best_move = (i, j) + + return best_move + +def make_move(row, col): + if board[row][col] == ' ': + board[row][col] = 'X' + buttons[row][col].config(text='X') + if check_winner(board, 'X'): + messagebox.showinfo("Tic-Tac-Toe", "You win!") + root.quit() + elif is_board_full(board): + messagebox.showinfo("Tic-Tac-Toe", "It's a draw!") + root.quit() + else: + ai_move() + else: + messagebox.showerror("Error", "Invalid move") + +#AI's turn to play +def ai_move(): + row, col = best_move(board) + board[row][col] = 'O' + buttons[row][col].config(text='O') + if check_winner(board, 'O'): + messagebox.showinfo("Tic-Tac-Toe", "AI wins!") + root.quit() + elif is_board_full(board): + messagebox.showinfo("Tic-Tac-Toe", "It's a draw!") + root.quit() + +root = tk.Tk() +root.title("Tic-Tac-Toe") + +board = [[' ' for _ in range(3)] for _ in range(3)] +buttons = [] + +for i in range(3): + row_buttons = [] + for j in range(3): + button = tk.Button(root, text=' ', font=('normal', 30), width=5, height=2, command=lambda row=i, col=j: make_move(row, col)) + button.grid(row=i, column=j) + row_buttons.append(button) + buttons.append(row_buttons) + +root.mainloop() diff --git a/Caesar Cipher Encoder & Decoder.py b/Caesar Cipher Encoder & Decoder.py index 7bd078e2849..63097b39e17 100644 --- a/Caesar Cipher Encoder & Decoder.py +++ b/Caesar Cipher Encoder & Decoder.py @@ -1,85 +1,67 @@ -#PROJECT1 -#CAESAR CIPHER DECODER +# PROJECT1 +# CAESAR CIPHER ENCODER/DECODER -#Author: InTruder -#Cloned from: https://github.com/InTruder-Sec/caesar-cipher +# Author: InTruder +# Cloned from: https://github.com/InTruder-Sec/caesar-cipher +# Improved by: OfficialAhmed (https://github.com/OfficialAhmed) + +def get_int() -> int: + """ + Get integer, otherwise redo + """ + + try: + key = int(input("Enter number of characters you want to shift: ")) + except: + print("Enter an integer") + key = get_int() + + return key def main(): + print("[>] CAESAR CIPHER DECODER!!! \n") print("[1] Encrypt\n[2] Decrypt") - try: - func = int(input("Choose one of the above(example for encode enter 1): ")) - except: - print("\n[>] Invalid input") - exit() - if func == 2: - decode() - else: - if func == 1: + match input("Choose one of the above(example for encode enter 1): "): + + case "1": encode() - else: - print("\n[>] Invalid input") - exit() + + case "2": + decode() + + case _: + print("\n[>] Invalid input. Choose 1 or 2") + main() + def encode(): - text = input("Enter text to encode: ") - key = input("Enter number of characters you want to shift: ") + encoded_cipher = "" - try: - key = int(key) - except: - print("Only intigers between 0 to 25 are allowed. Try again :)") - exit() - if key > 25: - print("Only intigers between 0 to 25 are allowed. Try again :)") - exit() - else: - key = key - text = text.upper() + text = input("Enter text to encode: ") + key = get_int() + for char in text: - ascii = ord(char) - if ascii > 90: - new_ascii = ascii - else: - if ascii < 65: - new_ascii = ascii - else: - new_ascii = ascii + key - if new_ascii > 90: - new_ascii = new_ascii - 26 - else: - new_ascii = new_ascii - encoded = chr(new_ascii) - encoded_cipher = encoded_cipher + encoded - print("Encoded text: " + encoded_cipher) + + ascii = ord(char) + key + encoded_cipher += chr(ascii) + print(f"Encoded text: {encoded_cipher}") def decode(): + + decoded_cipher = "" cipher = input("\n[>] Enter your cipher text: ") - print("Posiblities of cipher text are: \n") - cipher = cipher.lower() - for i in range(1, 26): - decoded = "" - decoded_cipher = "" - for char in cipher: - ascii = ord(char) - if ascii < 97: - new_ascii = ascii - else: - if ascii > 122: - new_ascii = ascii - else: - new_ascii = ascii - int(i) - if new_ascii < 97: - new_ascii = new_ascii + 26 - else: - new_ascii = new_ascii - decoded = chr(new_ascii) - decoded_cipher = decoded_cipher + decoded - print("\n" + decoded_cipher) + key = get_int() + + for character in cipher: + ascii = ord(character) - key + decoded_cipher += chr(ascii) + + print(decoded_cipher) if __name__ == '__main__': diff --git a/Calculator with simple ui.py b/Calculator with simple ui.py index eb0a5b727a2..122156a3cfd 100644 --- a/Calculator with simple ui.py +++ b/Calculator with simple ui.py @@ -1,23 +1,73 @@ # Program make a simple calculator -# This function adds two numbers -def add(x, y): - return x + y -# This function subtracts two numbers -def subtract(x, y): - return x - y +class Calculator: + def __init__(self): + pass -# This function multiplies two numbers -def multiply(x, y): - return x * y + def add(self, num1, num2): + """ + This function adds two numbers. -# This function divides two numbers -def divide(x, y): - return x / y + Examples: + >>> add(2, 3) + 5 + >>> add(5, 9) + 14 + >>> add(-1, 2) + 1 + """ + return num1 + num2 + + def subtract(self, num1, num2): + """ + This function subtracts two numbers. + + Examples: + >>> subtract(5, 3) + 2 + >>> subtract(9, 5) + 4 + >>> subtract(4, 9) + -5 + """ + return num1 - num2 + + def multiply(self, num1, num2): + """ + This function multiplies two numbers. + + Examples: + >>> multiply(4, 2) + 8 + >>> multiply(3, 3) + 9 + >>> multiply(9, 9) + 81 + """ + return num1 * num2 + + def divide(self, num1, num2): + """ + This function divides two numbers. + + Examples: + >>> divide(4, 4) + 1 + >>> divide(6, 3) + 2 + >>> divide(9, 1) + 9 + """ + if num2 == 0: + print("Cannot divide by zero") + else: + return num1 / num2 + + +calculator = Calculator() -print("Select operation.") print("1.Add") print("2.Subtract") print("3.Multiply") @@ -28,22 +78,21 @@ def divide(x, y): choice = input("Enter choice(1/2/3/4): ") # Check if choice is one of the four options - if choice in ('1', '2', '3', '4'): + if choice in ("1", "2", "3", "4"): num1 = float(input("Enter first number: ")) num2 = float(input("Enter second number: ")) - if choice == '1': - print(num1, "+", num2, "=", add(num1, num2)) + if choice == "1": + print(calculator.add(num1, num2)) - elif choice == '2': - print(num1, "-", num2, "=", subtract(num1, num2)) + elif choice == "2": + print(calculator.subtract(num1, num2)) - elif choice == '3': - print(num1, "*", num2, "=", multiply(num1, num2)) + elif choice == "3": + print(calculator.multiply(num1, num2)) - elif choice == '4': - print(num1, "/", num2, "=", divide(num1, num2)) + elif choice == "4": + print(calculator.divide(num1, num2)) break else: print("Invalid Input") - diff --git a/ExtractThumbnailFromVideo/README.md b/ExtractThumbnailFromVideo/README.md new file mode 100644 index 00000000000..2726afa84dd --- /dev/null +++ b/ExtractThumbnailFromVideo/README.md @@ -0,0 +1,49 @@ +# Thumbnail Extractor + +This Python function extracts a thumbnail frame from a video and saves it as an image file. It utilizes the OpenCV library to perform these operations. This README provides an overview of the function, its usage, and the required packages. + +## Table of Contents +- [Function Description](#function-description) +- [Usage](#usage) +- [Required Packages](#required-packages) + +## Function Description + +The `extract_thumbnail` function takes two parameters: + +- `video_path` (str): The path to the input video file. +- `frame_size` (tuple): A tuple containing the desired dimensions (width, height) for the thumbnail frame. + +The function will raise an `Exception` if it fails to extract a frame from the video. + +### Function Logic + +1. The function opens the specified video file using OpenCV. +2. It seeks to the middle frame by calculating the middle frame index. +3. The frame is resized to the specified dimensions. +4. The resized frame is saved as an image file with a filename derived from the video's base name. + +## Usage + +Here's an example of how to use the function: + +```python +from thumbnail_extractor import extract_thumbnail + +# Extract a thumbnail from 'my_video.mp4' with dimensions (320, 240) +extract_thumbnail('my_video.mp4', (320, 240)) +# Replace 'my_video.mp4' with the path to your own video file and (320, 240) with your desired thumbnail dimensions. + +## Required Packages +``` +To use this function, you need the following package: + +- **OpenCV (cv2)**: You can install it using `pip`: + + ```shell + pip install opencv-python + ``` + +This function is useful for generating thumbnail images from videos. It simplifies the process of creating video thumbnails for various applications. + + diff --git a/ExtractThumbnailFromVideo/extract_thumbnail_from_video.py b/ExtractThumbnailFromVideo/extract_thumbnail_from_video.py new file mode 100644 index 00000000000..76ca3b43eb7 --- /dev/null +++ b/ExtractThumbnailFromVideo/extract_thumbnail_from_video.py @@ -0,0 +1,39 @@ +import cv2 +import os + +def extract_thumbnail(video_path, frame_size): + """ + Extracts a thumbnail frame from a video and saves it as an image file. + + Args: + video_path (str): The path to the input video file. + frame_size (tuple): A tuple containing the desired dimensions (width, height) for the thumbnail frame. + + Raises: + Exception: If the function fails to extract a frame from the video. + + The function opens the specified video file, seeks to the middle frame, + resizes the frame to the specified dimensions, and saves it as an image + file with a filename derived from the video's base name. + + Example: + extract_thumbnail('my_video.mp4', (320, 240)) + + Required Packages: + cv2 (pip install cv2) + + This function is useful for generating thumbnail images from videos. + """ + video_capture = cv2.VideoCapture(video_path) # Open the video file for reading + total_frames = int(video_capture.get(cv2.CAP_PROP_FRAME_COUNT)) # Get the total number of frames in the video + middle_frame_index = total_frames // 2 # Calculate the index of the middle frame + video_capture.set(cv2.CAP_PROP_POS_FRAMES, middle_frame_index) # Seek to the middle frame + success, frame = video_capture.read() # Read the middle frame + video_capture.release() # Release the video capture object + + if success: + frame = cv2.resize(frame, frame_size) # Resize the frame to the specified dimensions + thumbnail_filename = f"{os.path.basename(video_path)}_thumbnail.jpg" # Create a filename for the thumbnail + cv2.imwrite(thumbnail_filename, frame) # Save the thumbnail frame as an image + else: + raise Exception("Could not extract frame") # Raise an exception if frame extraction fails diff --git a/Hand-Motion-Detection/hand_motion_recognizer.py b/Hand-Motion-Detection/hand_motion_recognizer.py index 9e9db13ce9e..59efb53c8ef 100644 --- a/Hand-Motion-Detection/hand_motion_recognizer.py +++ b/Hand-Motion-Detection/hand_motion_recognizer.py @@ -1,8 +1,5 @@ import mediapipe as mp import cv2 -import numpy as np -import uuid -import os mp_drawing = mp.solutions.drawing_utils mp_hands = mp.solutions.hands diff --git a/Hand-Motion-Detection/requirements.txt b/Hand-Motion-Detection/requirements.txt index b81f6c38f06..2d618146455 100644 --- a/Hand-Motion-Detection/requirements.txt +++ b/Hand-Motion-Detection/requirements.txt @@ -1,3 +1,3 @@ -numpy==1.25.2 +numpy==1.26.1 opencv_python==4.8.1.78 -mediapipe==0.10.5 +mediapipe==0.10.7 diff --git a/Industrial_developed_hangman/Data/local_words.txt b/Industrial_developed_hangman/Data/local_words.txt new file mode 100644 index 00000000000..ba958fe23e4 --- /dev/null +++ b/Industrial_developed_hangman/Data/local_words.txt @@ -0,0 +1,200 @@ +jam +veteran +environmental +sound +make +first-hand +disposition +handy +dance +expression +take +professor +swipe +publisher +tube +thread +paradox +bold +feeling +seal +medicine +ancestor +designer +sustain +define +stomach +minister +coffee +disorder +cow +clash +sector +discount +anger +nationalist +cater +mole +speculate +far +retirement +rub +sample +contribution +distance +palace +holiday +native +debut +steak +tired +pump +mayor +develop +cool +economics +prospect +regular +suntan +husband +praise +rule +soprano +secular +interactive +barrel +permanent +childish +ministry +rank +ball +difficult +linger +comfortable +education +grief +check +user +fish +catch +aquarium +photograph +aisle +justice +preoccupation +liberal +diagram +disturbance +separation +concentration +tidy +appointment +fling +exception +gutter +nature +relieve +illustrate +bathtub +cord +bus +divorce +country +mountain +slump +acquit +inn +achieve +bloodshed +bundle +spell +petty +closed +mud +begin +robot +chorus +prison +lend +bomb +exploration +wrist +fist +agency +example +factory +disagreement +assault +absolute +consider +sign +raw +flood +definition +implication +judge +extraterrestrial +corn +breakfast +shelter +buffet +seize +credit +hardship +growth +velvet +application +cheese +secretion +loop +smile +withdrawal +execute +daughter +quota +deny +defeat +knee +brain +packet +ignorance +core +stumble +glide +reign +huge +position +alive +we +gate +replacement +mourning +incapable +reach +rehearsal +profile +fax +sit +compete +smart +gradient +tough +house +pocket +spider +ditch +critical +ignorant +policy +experience +exhibition +forum +contribution +wrestle +cave +bet +stool +store +formal +basketball +journal diff --git a/Industrial_developed_hangman/Data/text_images.txt b/Industrial_developed_hangman/Data/text_images.txt new file mode 100644 index 00000000000..06338355b18 --- /dev/null +++ b/Industrial_developed_hangman/Data/text_images.txt @@ -0,0 +1,16 @@ +╔══╗─╔╗╔╗╔══╗╔═══╗─╔══╗╔╗╔╗╔╗╔╗╔══╗ +║╔╗║─║║║║║╔═╝║╔══╝─║╔╗║║║║║║║║║║╔╗║ +║╚╝╚╗║║║║║║──║╚══╗─║║║║║║║║║║║║║╚╝║ +║╔═╗║║║╔║║║──║╔══╝─║║║║║║╔║║║║║║╔╗║ +║╚═╝║║╚╝║║╚═╗║╚══╗╔╝║║║║╚╝║║╚╝║║║║║ +╚═══╝╚══╝╚══╝╚═══╝╚═╝╚╝╚══╝╚══╗╚╝╚╝ + ⡖⠒⢒⣶⠖⠒⠒⠒⡖⠒⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ + ⡇⣠⠟⠁⠀⠀⠀⡖⠓⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ + ⡿⠉⠀⠀⠀⠀⠀⢹⣞⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ + ⡇⠀⠀⠀⠀⠀⣠⠻⡟⢧⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ +⠀ ⡇⠀⠀⠀⠀⠐⠃⢨⡧⠀⠳⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀ ⡇⠀⠀⠀⠀⠀⠀⠠⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀ ⡇⠀⠀⠀⠀⠀⠀⢨⣧⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀ ⡇⠀⠀⠀⠀⠀⠀⠆⠘⣆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀ ⡇⠀⠀⠀⠀⠀⠈⠀⠀⠈⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ +⠀⠀ ⠧⠤⠤⠤⠤⠤⠤⠤⠤⠤⠤⠤⠤⠤ diff --git a/Industrial_developed_hangman/Makefile b/Industrial_developed_hangman/Makefile new file mode 100644 index 00000000000..e4e05f18fb2 --- /dev/null +++ b/Industrial_developed_hangman/Makefile @@ -0,0 +1,14 @@ +lint: + poetry run isort src tests + poetry run flake8 src tests + poetry run mypy src + poetry run mypy tests + +test: + poetry run pytest + +build: + python src/hangman/main.py +install: + pip install poetry + poetry install \ No newline at end of file diff --git a/Industrial_developed_hangman/README.md b/Industrial_developed_hangman/README.md new file mode 100644 index 00000000000..71fb5bd5724 --- /dev/null +++ b/Industrial_developed_hangman/README.md @@ -0,0 +1,12 @@ +This is a simple game hangman + +to install dependencies got to repository "Industrial_developed_hangman" by `cd .\Industrial_developed_hangman\` and run `make install` + +to start it use `make build` command + +example of programm run: + + +![img.png](recorces/img.png) + +also makefile have lint command to lint source code \ No newline at end of file diff --git a/Industrial_developed_hangman/poetry.lock b/Industrial_developed_hangman/poetry.lock new file mode 100644 index 00000000000..99bcf936a62 --- /dev/null +++ b/Industrial_developed_hangman/poetry.lock @@ -0,0 +1,1235 @@ +# This file is automatically @generated by Poetry 1.6.1 and should not be changed by hand. + +[[package]] +name = "astor" +version = "0.8.1" +description = "Read/rewrite/write Python ASTs" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7" +files = [ + {file = "astor-0.8.1-py2.py3-none-any.whl", hash = "sha256:070a54e890cefb5b3739d19f30f5a5ec840ffc9c50ffa7d23cc9fc1a38ebbfc5"}, + {file = "astor-0.8.1.tar.gz", hash = "sha256:6a6effda93f4e1ce9f618779b2dd1d9d84f1e32812c23a29b3fff6fd7f63fa5e"}, +] + +[[package]] +name = "attrs" +version = "23.1.0" +description = "Classes Without Boilerplate" +optional = false +python-versions = ">=3.7" +files = [ + {file = "attrs-23.1.0-py3-none-any.whl", hash = "sha256:1f28b4522cdc2fb4256ac1a020c78acf9cba2c6b461ccd2c126f3aa8e8335d04"}, + {file = "attrs-23.1.0.tar.gz", hash = "sha256:6279836d581513a26f1bf235f9acd333bc9115683f14f7e8fae46c98fc50e015"}, +] + +[package.extras] +cov = ["attrs[tests]", "coverage[toml] (>=5.3)"] +dev = ["attrs[docs,tests]", "pre-commit"] +docs = ["furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier", "zope-interface"] +tests = ["attrs[tests-no-zope]", "zope-interface"] +tests-no-zope = ["cloudpickle", "hypothesis", "mypy (>=1.1.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] + +[[package]] +name = "bandit" +version = "1.7.5" +description = "Security oriented static analyser for python code." +optional = false +python-versions = ">=3.7" +files = [ + {file = "bandit-1.7.5-py3-none-any.whl", hash = "sha256:75665181dc1e0096369112541a056c59d1c5f66f9bb74a8d686c3c362b83f549"}, + {file = "bandit-1.7.5.tar.gz", hash = "sha256:bdfc739baa03b880c2d15d0431b31c658ffc348e907fe197e54e0389dd59e11e"}, +] + +[package.dependencies] +colorama = {version = ">=0.3.9", markers = "platform_system == \"Windows\""} +GitPython = ">=1.0.1" +PyYAML = ">=5.3.1" +rich = "*" +stevedore = ">=1.20.0" + +[package.extras] +test = ["beautifulsoup4 (>=4.8.0)", "coverage (>=4.5.4)", "fixtures (>=3.0.0)", "flake8 (>=4.0.0)", "pylint (==1.9.4)", "stestr (>=2.5.0)", "testscenarios (>=0.5.0)", "testtools (>=2.3.0)", "tomli (>=1.1.0)"] +toml = ["tomli (>=1.1.0)"] +yaml = ["PyYAML"] + +[[package]] +name = "beautifulsoup4" +version = "4.12.0" +description = "Screen-scraping library" +optional = false +python-versions = ">=3.6.0" +files = [ + {file = "beautifulsoup4-4.12.0-py3-none-any.whl", hash = "sha256:2130a5ad7f513200fae61a17abb5e338ca980fa28c439c0571014bc0217e9591"}, + {file = "beautifulsoup4-4.12.0.tar.gz", hash = "sha256:c5fceeaec29d09c84970e47c65f2f0efe57872f7cff494c9691a26ec0ff13234"}, +] + +[package.dependencies] +soupsieve = ">1.2" + +[package.extras] +html5lib = ["html5lib"] +lxml = ["lxml"] + +[[package]] +name = "certifi" +version = "2023.7.22" +description = "Python package for providing Mozilla's CA Bundle." +optional = false +python-versions = ">=3.6" +files = [ + {file = "certifi-2023.7.22-py3-none-any.whl", hash = "sha256:92d6037539857d8206b8f6ae472e8b77db8058fec5937a1ef3f54304089edbb9"}, + {file = "certifi-2023.7.22.tar.gz", hash = "sha256:539cc1d13202e33ca466e88b2807e29f4c13049d6d87031a3c110744495cb082"}, +] + +[[package]] +name = "charset-normalizer" +version = "3.3.2" +description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." +optional = false +python-versions = ">=3.7.0" +files = [ + {file = "charset-normalizer-3.3.2.tar.gz", hash = "sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:25baf083bf6f6b341f4121c2f3c548875ee6f5339300e08be3f2b2ba1721cdd3"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:06435b539f889b1f6f4ac1758871aae42dc3a8c0e24ac9e60c2384973ad73027"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9063e24fdb1e498ab71cb7419e24622516c4a04476b17a2dab57e8baa30d6e03"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6897af51655e3691ff853668779c7bad41579facacf5fd7253b0133308cf000d"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1d3193f4a680c64b4b6a9115943538edb896edc190f0b222e73761716519268e"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd70574b12bb8a4d2aaa0094515df2463cb429d8536cfb6c7ce983246983e5a6"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8465322196c8b4d7ab6d1e049e4c5cb460d0394da4a27d23cc242fbf0034b6b5"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a9a8e9031d613fd2009c182b69c7b2c1ef8239a0efb1df3f7c8da66d5dd3d537"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:beb58fe5cdb101e3a055192ac291b7a21e3b7ef4f67fa1d74e331a7f2124341c"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e06ed3eb3218bc64786f7db41917d4e686cc4856944f53d5bdf83a6884432e12"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:2e81c7b9c8979ce92ed306c249d46894776a909505d8f5a4ba55b14206e3222f"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:572c3763a264ba47b3cf708a44ce965d98555f618ca42c926a9c1616d8f34269"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-win32.whl", hash = "sha256:3d47fa203a7bd9c5b6cee4736ee84ca03b8ef23193c0d1ca99b5089f72645c73"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:10955842570876604d404661fbccbc9c7e684caf432c09c715ec38fbae45ae09"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:802fe99cca7457642125a8a88a084cef28ff0cf9407060f7b93dca5aa25480db"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ceae2f17a9c33cb48e3263960dc5fc8005351ee19db217e9b1bb15d28c02574"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:65f6f63034100ead094b8744b3b97965785388f308a64cf8d7c34f2f2e5be0c4"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4a78b2b446bd7c934f5dcedc588903fb2f5eec172f3d29e52a9096a43722adfc"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e537484df0d8f426ce2afb2d0f8e1c3d0b114b83f8850e5f2fbea0e797bd82ae"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:eb6904c354526e758fda7167b33005998fb68c46fbc10e013ca97f21ca5c8887"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:deb6be0ac38ece9ba87dea880e438f25ca3eddfac8b002a2ec3d9183a454e8ae"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:4ab2fe47fae9e0f9dee8c04187ce5d09f48eabe611be8259444906793ab7cbce"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:80402cd6ee291dcb72644d6eac93785fe2c8b9cb30893c1af5b8fdd753b9d40f"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-win32.whl", hash = "sha256:7cd13a2e3ddeed6913a65e66e94b51d80a041145a026c27e6bb76c31a853c6ab"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0b2b64d2bb6d3fb9112bafa732def486049e63de9618b5843bcdd081d8144cd8"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8f4a014bc36d3c57402e2977dada34f9c12300af536839dc38c0beab8878f38a"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a10af20b82360ab00827f916a6058451b723b4e65030c5a18577c8b2de5b3389"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8d756e44e94489e49571086ef83b2bb8ce311e730092d2c34ca8f7d925cb20aa"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:90d558489962fd4918143277a773316e56c72da56ec7aa3dc3dbbe20fdfed15b"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6ac7ffc7ad6d040517be39eb591cac5ff87416c2537df6ba3cba3bae290c0fed"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:7ed9e526742851e8d5cc9e6cf41427dfc6068d4f5a3bb03659444b4cabf6bc26"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:8bdb58ff7ba23002a4c5808d608e4e6c687175724f54a5dade5fa8c67b604e4d"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:6b3251890fff30ee142c44144871185dbe13b11bab478a88887a639655be1068"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:b4a23f61ce87adf89be746c8a8974fe1c823c891d8f86eb218bb957c924bb143"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:efcb3f6676480691518c177e3b465bcddf57cea040302f9f4e6e191af91174d4"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-win32.whl", hash = "sha256:d965bba47ddeec8cd560687584e88cf699fd28f192ceb452d1d7ee807c5597b7"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:96b02a3dc4381e5494fad39be677abcb5e6634bf7b4fa83a6dd3112607547001"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:95f2a5796329323b8f0512e09dbb7a1860c46a39da62ecb2324f116fa8fdc85c"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c002b4ffc0be611f0d9da932eb0f704fe2602a9a949d1f738e4c34c75b0863d5"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a981a536974bbc7a512cf44ed14938cf01030a99e9b3a06dd59578882f06f985"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3287761bc4ee9e33561a7e058c72ac0938c4f57fe49a09eae428fd88aafe7bb6"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:42cb296636fcc8b0644486d15c12376cb9fa75443e00fb25de0b8602e64c1714"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0a55554a2fa0d408816b3b5cedf0045f4b8e1a6065aec45849de2d6f3f8e9786"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:c083af607d2515612056a31f0a8d9e0fcb5876b7bfc0abad3ecd275bc4ebc2d5"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:87d1351268731db79e0f8e745d92493ee2841c974128ef629dc518b937d9194c"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:bd8f7df7d12c2db9fab40bdd87a7c09b1530128315d047a086fa3ae3435cb3a8"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:c180f51afb394e165eafe4ac2936a14bee3eb10debc9d9e4db8958fe36afe711"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:8c622a5fe39a48f78944a87d4fb8a53ee07344641b0562c540d840748571b811"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-win32.whl", hash = "sha256:db364eca23f876da6f9e16c9da0df51aa4f104a972735574842618b8c6d999d4"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-win_amd64.whl", hash = "sha256:86216b5cee4b06df986d214f664305142d9c76df9b6512be2738aa72a2048f99"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:6463effa3186ea09411d50efc7d85360b38d5f09b870c48e4600f63af490e56a"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6c4caeef8fa63d06bd437cd4bdcf3ffefe6738fb1b25951440d80dc7df8c03ac"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:37e55c8e51c236f95b033f6fb391d7d7970ba5fe7ff453dad675e88cf303377a"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb69256e180cb6c8a894fee62b3afebae785babc1ee98b81cdf68bbca1987f33"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ae5f4161f18c61806f411a13b0310bea87f987c7d2ecdbdaad0e94eb2e404238"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b2b0a0c0517616b6869869f8c581d4eb2dd83a4d79e0ebcb7d373ef9956aeb0a"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:45485e01ff4d3630ec0d9617310448a8702f70e9c01906b0d0118bdf9d124cf2"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eb00ed941194665c332bf8e078baf037d6c35d7c4f3102ea2d4f16ca94a26dc8"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:2127566c664442652f024c837091890cb1942c30937add288223dc895793f898"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a50aebfa173e157099939b17f18600f72f84eed3049e743b68ad15bd69b6bf99"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:4d0d1650369165a14e14e1e47b372cfcb31d6ab44e6e33cb2d4e57265290044d"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:923c0c831b7cfcb071580d3f46c4baf50f174be571576556269530f4bbd79d04"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:06a81e93cd441c56a9b65d8e1d043daeb97a3d0856d177d5c90ba85acb3db087"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-win32.whl", hash = "sha256:6ef1d82a3af9d3eecdba2321dc1b3c238245d890843e040e41e470ffa64c3e25"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-win_amd64.whl", hash = "sha256:eb8821e09e916165e160797a6c17edda0679379a4be5c716c260e836e122f54b"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c235ebd9baae02f1b77bcea61bce332cb4331dc3617d254df3323aa01ab47bd4"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5b4c145409bef602a690e7cfad0a15a55c13320ff7a3ad7ca59c13bb8ba4d45d"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:68d1f8a9e9e37c1223b656399be5d6b448dea850bed7d0f87a8311f1ff3dabb0"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22afcb9f253dac0696b5a4be4a1c0f8762f8239e21b99680099abd9b2b1b2269"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e27ad930a842b4c5eb8ac0016b0a54f5aebbe679340c26101df33424142c143c"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1f79682fbe303db92bc2b1136016a38a42e835d932bab5b3b1bfcfbf0640e519"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b261ccdec7821281dade748d088bb6e9b69e6d15b30652b74cbbac25e280b796"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:122c7fa62b130ed55f8f285bfd56d5f4b4a5b503609d181f9ad85e55c89f4185"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d0eccceffcb53201b5bfebb52600a5fb483a20b61da9dbc885f8b103cbe7598c"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9f96df6923e21816da7e0ad3fd47dd8f94b2a5ce594e00677c0013018b813458"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:7f04c839ed0b6b98b1a7501a002144b76c18fb1c1850c8b98d458ac269e26ed2"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:34d1c8da1e78d2e001f363791c98a272bb734000fcef47a491c1e3b0505657a8"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-win32.whl", hash = "sha256:aed38f6e4fb3f5d6bf81bfa990a07806be9d83cf7bacef998ab1a9bd660a581f"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:b01b88d45a6fcb69667cd6d2f7a9aeb4bf53760d7fc536bf679ec94fe9f3ff3d"}, + {file = "charset_normalizer-3.3.2-py3-none-any.whl", hash = "sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc"}, +] + +[[package]] +name = "colorama" +version = "0.4.6" +description = "Cross-platform colored terminal text." +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" +files = [ + {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, + {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, +] + +[[package]] +name = "coverage" +version = "7.3.2" +description = "Code coverage measurement for Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "coverage-7.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d872145f3a3231a5f20fd48500274d7df222e291d90baa2026cc5152b7ce86bf"}, + {file = "coverage-7.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:310b3bb9c91ea66d59c53fa4989f57d2436e08f18fb2f421a1b0b6b8cc7fffda"}, + {file = "coverage-7.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f47d39359e2c3779c5331fc740cf4bce6d9d680a7b4b4ead97056a0ae07cb49a"}, + {file = "coverage-7.3.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:aa72dbaf2c2068404b9870d93436e6d23addd8bbe9295f49cbca83f6e278179c"}, + {file = "coverage-7.3.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:beaa5c1b4777f03fc63dfd2a6bd820f73f036bfb10e925fce067b00a340d0f3f"}, + {file = "coverage-7.3.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:dbc1b46b92186cc8074fee9d9fbb97a9dd06c6cbbef391c2f59d80eabdf0faa6"}, + {file = "coverage-7.3.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:315a989e861031334d7bee1f9113c8770472db2ac484e5b8c3173428360a9148"}, + {file = "coverage-7.3.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:d1bc430677773397f64a5c88cb522ea43175ff16f8bfcc89d467d974cb2274f9"}, + {file = "coverage-7.3.2-cp310-cp310-win32.whl", hash = "sha256:a889ae02f43aa45032afe364c8ae84ad3c54828c2faa44f3bfcafecb5c96b02f"}, + {file = "coverage-7.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:c0ba320de3fb8c6ec16e0be17ee1d3d69adcda99406c43c0409cb5c41788a611"}, + {file = "coverage-7.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ac8c802fa29843a72d32ec56d0ca792ad15a302b28ca6203389afe21f8fa062c"}, + {file = "coverage-7.3.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:89a937174104339e3a3ffcf9f446c00e3a806c28b1841c63edb2b369310fd074"}, + {file = "coverage-7.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e267e9e2b574a176ddb983399dec325a80dbe161f1a32715c780b5d14b5f583a"}, + {file = "coverage-7.3.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2443cbda35df0d35dcfb9bf8f3c02c57c1d6111169e3c85fc1fcc05e0c9f39a3"}, + {file = "coverage-7.3.2-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4175e10cc8dda0265653e8714b3174430b07c1dca8957f4966cbd6c2b1b8065a"}, + {file = "coverage-7.3.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0cbf38419fb1a347aaf63481c00f0bdc86889d9fbf3f25109cf96c26b403fda1"}, + {file = "coverage-7.3.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:5c913b556a116b8d5f6ef834038ba983834d887d82187c8f73dec21049abd65c"}, + {file = "coverage-7.3.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:1981f785239e4e39e6444c63a98da3a1db8e971cb9ceb50a945ba6296b43f312"}, + {file = "coverage-7.3.2-cp311-cp311-win32.whl", hash = "sha256:43668cabd5ca8258f5954f27a3aaf78757e6acf13c17604d89648ecc0cc66640"}, + {file = "coverage-7.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:e10c39c0452bf6e694511c901426d6b5ac005acc0f78ff265dbe36bf81f808a2"}, + {file = "coverage-7.3.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:4cbae1051ab791debecc4a5dcc4a1ff45fc27b91b9aee165c8a27514dd160836"}, + {file = "coverage-7.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:12d15ab5833a997716d76f2ac1e4b4d536814fc213c85ca72756c19e5a6b3d63"}, + {file = "coverage-7.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3c7bba973ebee5e56fe9251300c00f1579652587a9f4a5ed8404b15a0471f216"}, + {file = "coverage-7.3.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fe494faa90ce6381770746077243231e0b83ff3f17069d748f645617cefe19d4"}, + {file = "coverage-7.3.2-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f6e9589bd04d0461a417562649522575d8752904d35c12907d8c9dfeba588faf"}, + {file = "coverage-7.3.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d51ac2a26f71da1b57f2dc81d0e108b6ab177e7d30e774db90675467c847bbdf"}, + {file = "coverage-7.3.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:99b89d9f76070237975b315b3d5f4d6956ae354a4c92ac2388a5695516e47c84"}, + {file = "coverage-7.3.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:fa28e909776dc69efb6ed975a63691bc8172b64ff357e663a1bb06ff3c9b589a"}, + {file = "coverage-7.3.2-cp312-cp312-win32.whl", hash = "sha256:289fe43bf45a575e3ab10b26d7b6f2ddb9ee2dba447499f5401cfb5ecb8196bb"}, + {file = "coverage-7.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:7dbc3ed60e8659bc59b6b304b43ff9c3ed858da2839c78b804973f613d3e92ed"}, + {file = "coverage-7.3.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:f94b734214ea6a36fe16e96a70d941af80ff3bfd716c141300d95ebc85339738"}, + {file = "coverage-7.3.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:af3d828d2c1cbae52d34bdbb22fcd94d1ce715d95f1a012354a75e5913f1bda2"}, + {file = "coverage-7.3.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:630b13e3036e13c7adc480ca42fa7afc2a5d938081d28e20903cf7fd687872e2"}, + {file = "coverage-7.3.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c9eacf273e885b02a0273bb3a2170f30e2d53a6d53b72dbe02d6701b5296101c"}, + {file = "coverage-7.3.2-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d8f17966e861ff97305e0801134e69db33b143bbfb36436efb9cfff6ec7b2fd9"}, + {file = "coverage-7.3.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:b4275802d16882cf9c8b3d057a0839acb07ee9379fa2749eca54efbce1535b82"}, + {file = "coverage-7.3.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:72c0cfa5250f483181e677ebc97133ea1ab3eb68645e494775deb6a7f6f83901"}, + {file = "coverage-7.3.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:cb536f0dcd14149425996821a168f6e269d7dcd2c273a8bff8201e79f5104e76"}, + {file = "coverage-7.3.2-cp38-cp38-win32.whl", hash = "sha256:307adb8bd3abe389a471e649038a71b4eb13bfd6b7dd9a129fa856f5c695cf92"}, + {file = "coverage-7.3.2-cp38-cp38-win_amd64.whl", hash = "sha256:88ed2c30a49ea81ea3b7f172e0269c182a44c236eb394718f976239892c0a27a"}, + {file = "coverage-7.3.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b631c92dfe601adf8f5ebc7fc13ced6bb6e9609b19d9a8cd59fa47c4186ad1ce"}, + {file = "coverage-7.3.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:d3d9df4051c4a7d13036524b66ecf7a7537d14c18a384043f30a303b146164e9"}, + {file = "coverage-7.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5f7363d3b6a1119ef05015959ca24a9afc0ea8a02c687fe7e2d557705375c01f"}, + {file = "coverage-7.3.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2f11cc3c967a09d3695d2a6f03fb3e6236622b93be7a4b5dc09166a861be6d25"}, + {file = "coverage-7.3.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:149de1d2401ae4655c436a3dced6dd153f4c3309f599c3d4bd97ab172eaf02d9"}, + {file = "coverage-7.3.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:3a4006916aa6fee7cd38db3bfc95aa9c54ebb4ffbfc47c677c8bba949ceba0a6"}, + {file = "coverage-7.3.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9028a3871280110d6e1aa2df1afd5ef003bab5fb1ef421d6dc748ae1c8ef2ebc"}, + {file = "coverage-7.3.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:9f805d62aec8eb92bab5b61c0f07329275b6f41c97d80e847b03eb894f38d083"}, + {file = "coverage-7.3.2-cp39-cp39-win32.whl", hash = "sha256:d1c88ec1a7ff4ebca0219f5b1ef863451d828cccf889c173e1253aa84b1e07ce"}, + {file = "coverage-7.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:b4767da59464bb593c07afceaddea61b154136300881844768037fd5e859353f"}, + {file = "coverage-7.3.2-pp38.pp39.pp310-none-any.whl", hash = "sha256:ae97af89f0fbf373400970c0a21eef5aa941ffeed90aee43650b81f7d7f47637"}, + {file = "coverage-7.3.2.tar.gz", hash = "sha256:be32ad29341b0170e795ca590e1c07e81fc061cb5b10c74ce7203491484404ef"}, +] + +[package.dependencies] +tomli = {version = "*", optional = true, markers = "python_full_version <= \"3.11.0a6\" and extra == \"toml\""} + +[package.extras] +toml = ["tomli"] + +[[package]] +name = "darglint" +version = "1.8.1" +description = "A utility for ensuring Google-style docstrings stay up to date with the source code." +optional = false +python-versions = ">=3.6,<4.0" +files = [ + {file = "darglint-1.8.1-py3-none-any.whl", hash = "sha256:5ae11c259c17b0701618a20c3da343a3eb98b3bc4b5a83d31cdd94f5ebdced8d"}, + {file = "darglint-1.8.1.tar.gz", hash = "sha256:080d5106df149b199822e7ee7deb9c012b49891538f14a11be681044f0bb20da"}, +] + +[[package]] +name = "docutils" +version = "0.20.1" +description = "Docutils -- Python Documentation Utilities" +optional = false +python-versions = ">=3.7" +files = [ + {file = "docutils-0.20.1-py3-none-any.whl", hash = "sha256:96f387a2c5562db4476f09f13bbab2192e764cac08ebbf3a34a95d9b1e4a59d6"}, + {file = "docutils-0.20.1.tar.gz", hash = "sha256:f08a4e276c3a1583a86dce3e34aba3fe04d02bba2dd51ed16106244e8a923e3b"}, +] + +[[package]] +name = "eradicate" +version = "2.3.0" +description = "Removes commented-out code." +optional = false +python-versions = "*" +files = [ + {file = "eradicate-2.3.0-py3-none-any.whl", hash = "sha256:2b29b3dd27171f209e4ddd8204b70c02f0682ae95eecb353f10e8d72b149c63e"}, + {file = "eradicate-2.3.0.tar.gz", hash = "sha256:06df115be3b87d0fc1c483db22a2ebb12bcf40585722810d809cc770f5031c37"}, +] + +[[package]] +name = "exceptiongroup" +version = "1.1.3" +description = "Backport of PEP 654 (exception groups)" +optional = false +python-versions = ">=3.7" +files = [ + {file = "exceptiongroup-1.1.3-py3-none-any.whl", hash = "sha256:343280667a4585d195ca1cf9cef84a4e178c4b6cf2274caef9859782b567d5e3"}, + {file = "exceptiongroup-1.1.3.tar.gz", hash = "sha256:097acd85d473d75af5bb98e41b61ff7fe35efe6675e4f9370ec6ec5126d160e9"}, +] + +[package.extras] +test = ["pytest (>=6)"] + +[[package]] +name = "flake8" +version = "6.1.0" +description = "the modular source code checker: pep8 pyflakes and co" +optional = false +python-versions = ">=3.8.1" +files = [ + {file = "flake8-6.1.0-py2.py3-none-any.whl", hash = "sha256:ffdfce58ea94c6580c77888a86506937f9a1a227dfcd15f245d694ae20a6b6e5"}, + {file = "flake8-6.1.0.tar.gz", hash = "sha256:d5b3857f07c030bdb5bf41c7f53799571d75c4491748a3adcd47de929e34cd23"}, +] + +[package.dependencies] +mccabe = ">=0.7.0,<0.8.0" +pycodestyle = ">=2.11.0,<2.12.0" +pyflakes = ">=3.1.0,<3.2.0" + +[[package]] +name = "flake8-bandit" +version = "4.1.1" +description = "Automated security testing with bandit and flake8." +optional = false +python-versions = ">=3.6" +files = [ + {file = "flake8_bandit-4.1.1-py3-none-any.whl", hash = "sha256:4c8a53eb48f23d4ef1e59293657181a3c989d0077c9952717e98a0eace43e06d"}, + {file = "flake8_bandit-4.1.1.tar.gz", hash = "sha256:068e09287189cbfd7f986e92605adea2067630b75380c6b5733dab7d87f9a84e"}, +] + +[package.dependencies] +bandit = ">=1.7.3" +flake8 = ">=5.0.0" + +[[package]] +name = "flake8-broken-line" +version = "1.0.0" +description = "Flake8 plugin to forbid backslashes for line breaks" +optional = false +python-versions = ">=3.8,<4.0" +files = [ + {file = "flake8_broken_line-1.0.0-py3-none-any.whl", hash = "sha256:96c964336024a5030dc536a9f6fb02aa679e2d2a6b35b80a558b5136c35832a9"}, + {file = "flake8_broken_line-1.0.0.tar.gz", hash = "sha256:e2c6a17f8d9a129e99c1320fce89b33843e2963871025c4c2bb7b8b8d8732a85"}, +] + +[package.dependencies] +flake8 = ">5" + +[[package]] +name = "flake8-bugbear" +version = "23.9.16" +description = "A plugin for flake8 finding likely bugs and design problems in your program. Contains warnings that don't belong in pyflakes and pycodestyle." +optional = false +python-versions = ">=3.8.1" +files = [ + {file = "flake8-bugbear-23.9.16.tar.gz", hash = "sha256:90cf04b19ca02a682feb5aac67cae8de742af70538590509941ab10ae8351f71"}, + {file = "flake8_bugbear-23.9.16-py3-none-any.whl", hash = "sha256:b182cf96ea8f7a8595b2f87321d7d9b28728f4d9c3318012d896543d19742cb5"}, +] + +[package.dependencies] +attrs = ">=19.2.0" +flake8 = ">=6.0.0" + +[package.extras] +dev = ["coverage", "hypothesis", "hypothesmith (>=0.2)", "pre-commit", "pytest", "tox"] + +[[package]] +name = "flake8-commas" +version = "2.1.0" +description = "Flake8 lint for trailing commas." +optional = false +python-versions = "*" +files = [ + {file = "flake8-commas-2.1.0.tar.gz", hash = "sha256:940441ab8ee544df564ae3b3f49f20462d75d5c7cac2463e0b27436e2050f263"}, + {file = "flake8_commas-2.1.0-py2.py3-none-any.whl", hash = "sha256:ebb96c31e01d0ef1d0685a21f3f0e2f8153a0381430e748bf0bbbb5d5b453d54"}, +] + +[package.dependencies] +flake8 = ">=2" + +[[package]] +name = "flake8-comprehensions" +version = "3.14.0" +description = "A flake8 plugin to help you write better list/set/dict comprehensions." +optional = false +python-versions = ">=3.8" +files = [ + {file = "flake8_comprehensions-3.14.0-py3-none-any.whl", hash = "sha256:7b9d07d94aa88e62099a6d1931ddf16c344d4157deedf90fe0d8ee2846f30e97"}, + {file = "flake8_comprehensions-3.14.0.tar.gz", hash = "sha256:81768c61bfc064e1a06222df08a2580d97de10cb388694becaf987c331c6c0cf"}, +] + +[package.dependencies] +flake8 = ">=3.0,<3.2.0 || >3.2.0" + +[[package]] +name = "flake8-debugger" +version = "4.1.2" +description = "ipdb/pdb statement checker plugin for flake8" +optional = false +python-versions = ">=3.7" +files = [ + {file = "flake8-debugger-4.1.2.tar.gz", hash = "sha256:52b002560941e36d9bf806fca2523dc7fb8560a295d5f1a6e15ac2ded7a73840"}, + {file = "flake8_debugger-4.1.2-py3-none-any.whl", hash = "sha256:0a5e55aeddcc81da631ad9c8c366e7318998f83ff00985a49e6b3ecf61e571bf"}, +] + +[package.dependencies] +flake8 = ">=3.0" +pycodestyle = "*" + +[[package]] +name = "flake8-docstrings" +version = "1.7.0" +description = "Extension for flake8 which uses pydocstyle to check docstrings" +optional = false +python-versions = ">=3.7" +files = [ + {file = "flake8_docstrings-1.7.0-py2.py3-none-any.whl", hash = "sha256:51f2344026da083fc084166a9353f5082b01f72901df422f74b4d953ae88ac75"}, + {file = "flake8_docstrings-1.7.0.tar.gz", hash = "sha256:4c8cc748dc16e6869728699e5d0d685da9a10b0ea718e090b1ba088e67a941af"}, +] + +[package.dependencies] +flake8 = ">=3" +pydocstyle = ">=2.1" + +[[package]] +name = "flake8-eradicate" +version = "1.5.0" +description = "Flake8 plugin to find commented out code" +optional = false +python-versions = ">=3.8,<4.0" +files = [ + {file = "flake8_eradicate-1.5.0-py3-none-any.whl", hash = "sha256:18acc922ad7de623f5247c7d5595da068525ec5437dd53b22ec2259b96ce9d22"}, + {file = "flake8_eradicate-1.5.0.tar.gz", hash = "sha256:aee636cb9ecb5594a7cd92d67ad73eb69909e5cc7bd81710cf9d00970f3983a6"}, +] + +[package.dependencies] +attrs = "*" +eradicate = ">=2.0,<3.0" +flake8 = ">5" + +[[package]] +name = "flake8-isort" +version = "6.1.0" +description = "flake8 plugin that integrates isort ." +optional = false +python-versions = ">=3.8" +files = [ + {file = "flake8-isort-6.1.0.tar.gz", hash = "sha256:d4639343bac540194c59fb1618ac2c285b3e27609f353bef6f50904d40c1643e"}, +] + +[package.dependencies] +flake8 = "*" +isort = ">=5.0.0,<6" + +[package.extras] +test = ["pytest"] + +[[package]] +name = "flake8-quotes" +version = "3.3.2" +description = "Flake8 lint for quotes." +optional = false +python-versions = "*" +files = [ + {file = "flake8-quotes-3.3.2.tar.gz", hash = "sha256:6e26892b632dacba517bf27219c459a8396dcfac0f5e8204904c5a4ba9b480e1"}, +] + +[package.dependencies] +flake8 = "*" + +[[package]] +name = "flake8-rst-docstrings" +version = "0.3.0" +description = "Python docstring reStructuredText (RST) validator for flake8" +optional = false +python-versions = ">=3.7" +files = [ + {file = "flake8-rst-docstrings-0.3.0.tar.gz", hash = "sha256:d1ce22b4bd37b73cd86b8d980e946ef198cfcc18ed82fedb674ceaa2f8d1afa4"}, + {file = "flake8_rst_docstrings-0.3.0-py3-none-any.whl", hash = "sha256:f8c3c6892ff402292651c31983a38da082480ad3ba253743de52989bdc84ca1c"}, +] + +[package.dependencies] +flake8 = ">=3" +pygments = "*" +restructuredtext-lint = "*" + +[package.extras] +develop = ["build", "twine"] + +[[package]] +name = "flake8-string-format" +version = "0.3.0" +description = "string format checker, plugin for flake8" +optional = false +python-versions = "*" +files = [ + {file = "flake8-string-format-0.3.0.tar.gz", hash = "sha256:65f3da786a1461ef77fca3780b314edb2853c377f2e35069723348c8917deaa2"}, + {file = "flake8_string_format-0.3.0-py2.py3-none-any.whl", hash = "sha256:812ff431f10576a74c89be4e85b8e075a705be39bc40c4b4278b5b13e2afa9af"}, +] + +[package.dependencies] +flake8 = "*" + +[[package]] +name = "freezegun" +version = "1.2.2" +description = "Let your Python tests travel through time" +optional = false +python-versions = ">=3.6" +files = [ + {file = "freezegun-1.2.2-py3-none-any.whl", hash = "sha256:ea1b963b993cb9ea195adbd893a48d573fda951b0da64f60883d7e988b606c9f"}, + {file = "freezegun-1.2.2.tar.gz", hash = "sha256:cd22d1ba06941384410cd967d8a99d5ae2442f57dfafeff2fda5de8dc5c05446"}, +] + +[package.dependencies] +python-dateutil = ">=2.7" + +[[package]] +name = "gitdb" +version = "4.0.11" +description = "Git Object Database" +optional = false +python-versions = ">=3.7" +files = [ + {file = "gitdb-4.0.11-py3-none-any.whl", hash = "sha256:81a3407ddd2ee8df444cbacea00e2d038e40150acfa3001696fe0dcf1d3adfa4"}, + {file = "gitdb-4.0.11.tar.gz", hash = "sha256:bf5421126136d6d0af55bc1e7c1af1c397a34f5b7bd79e776cd3e89785c2b04b"}, +] + +[package.dependencies] +smmap = ">=3.0.1,<6" + +[[package]] +name = "gitpython" +version = "3.1.40" +description = "GitPython is a Python library used to interact with Git repositories" +optional = false +python-versions = ">=3.7" +files = [ + {file = "GitPython-3.1.40-py3-none-any.whl", hash = "sha256:cf14627d5a8049ffbf49915732e5eddbe8134c3bdb9d476e6182b676fc573f8a"}, + {file = "GitPython-3.1.40.tar.gz", hash = "sha256:22b126e9ffb671fdd0c129796343a02bf67bf2994b35449ffc9321aa755e18a4"}, +] + +[package.dependencies] +gitdb = ">=4.0.1,<5" + +[package.extras] +test = ["black", "coverage[toml]", "ddt (>=1.1.1,!=1.4.3)", "mock", "mypy", "pre-commit", "pytest", "pytest-cov", "pytest-instafail", "pytest-subtests", "pytest-sugar"] + +[[package]] +name = "idna" +version = "3.4" +description = "Internationalized Domain Names in Applications (IDNA)" +optional = false +python-versions = ">=3.5" +files = [ + {file = "idna-3.4-py3-none-any.whl", hash = "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2"}, + {file = "idna-3.4.tar.gz", hash = "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4"}, +] + +[[package]] +name = "importlib-metadata" +version = "6.8.0" +description = "Read metadata from Python packages" +optional = false +python-versions = ">=3.8" +files = [ + {file = "importlib_metadata-6.8.0-py3-none-any.whl", hash = "sha256:3ebb78df84a805d7698245025b975d9d67053cd94c79245ba4b3eb694abe68bb"}, + {file = "importlib_metadata-6.8.0.tar.gz", hash = "sha256:dbace7892d8c0c4ac1ad096662232f831d4e64f4c4545bd53016a3e9d4654743"}, +] + +[package.dependencies] +zipp = ">=0.5" + +[package.extras] +docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] +perf = ["ipython"] +testing = ["flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pyfakefs", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-perf (>=0.9.2)", "pytest-ruff"] + +[[package]] +name = "iniconfig" +version = "2.0.0" +description = "brain-dead simple config-ini parsing" +optional = false +python-versions = ">=3.7" +files = [ + {file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"}, + {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, +] + +[[package]] +name = "isort" +version = "5.12.0" +description = "A Python utility / library to sort Python imports." +optional = false +python-versions = ">=3.8.0" +files = [ + {file = "isort-5.12.0-py3-none-any.whl", hash = "sha256:f84c2818376e66cf843d497486ea8fed8700b340f308f076c6fb1229dff318b6"}, + {file = "isort-5.12.0.tar.gz", hash = "sha256:8bef7dde241278824a6d83f44a544709b065191b95b6e50894bdc722fcba0504"}, +] + +[package.extras] +colors = ["colorama (>=0.4.3)"] +pipfile-deprecated-finder = ["pip-shims (>=0.5.2)", "pipreqs", "requirementslib"] +plugins = ["setuptools"] +requirements-deprecated-finder = ["pip-api", "pipreqs"] + +[[package]] +name = "markdown-it-py" +version = "3.0.0" +description = "Python port of markdown-it. Markdown parsing, done right!" +optional = false +python-versions = ">=3.8" +files = [ + {file = "markdown-it-py-3.0.0.tar.gz", hash = "sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb"}, + {file = "markdown_it_py-3.0.0-py3-none-any.whl", hash = "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1"}, +] + +[package.dependencies] +mdurl = ">=0.1,<1.0" + +[package.extras] +benchmarking = ["psutil", "pytest", "pytest-benchmark"] +code-style = ["pre-commit (>=3.0,<4.0)"] +compare = ["commonmark (>=0.9,<1.0)", "markdown (>=3.4,<4.0)", "mistletoe (>=1.0,<2.0)", "mistune (>=2.0,<3.0)", "panflute (>=2.3,<3.0)"] +linkify = ["linkify-it-py (>=1,<3)"] +plugins = ["mdit-py-plugins"] +profiling = ["gprof2dot"] +rtd = ["jupyter_sphinx", "mdit-py-plugins", "myst-parser", "pyyaml", "sphinx", "sphinx-copybutton", "sphinx-design", "sphinx_book_theme"] +testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions"] + +[[package]] +name = "mccabe" +version = "0.7.0" +description = "McCabe checker, plugin for flake8" +optional = false +python-versions = ">=3.6" +files = [ + {file = "mccabe-0.7.0-py2.py3-none-any.whl", hash = "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e"}, + {file = "mccabe-0.7.0.tar.gz", hash = "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325"}, +] + +[[package]] +name = "mdurl" +version = "0.1.2" +description = "Markdown URL utilities" +optional = false +python-versions = ">=3.7" +files = [ + {file = "mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8"}, + {file = "mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba"}, +] + +[[package]] +name = "mypy" +version = "1.5.1" +description = "Optional static typing for Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "mypy-1.5.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f33592ddf9655a4894aef22d134de7393e95fcbdc2d15c1ab65828eee5c66c70"}, + {file = "mypy-1.5.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:258b22210a4a258ccd077426c7a181d789d1121aca6db73a83f79372f5569ae0"}, + {file = "mypy-1.5.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a9ec1f695f0c25986e6f7f8778e5ce61659063268836a38c951200c57479cc12"}, + {file = "mypy-1.5.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:abed92d9c8f08643c7d831300b739562b0a6c9fcb028d211134fc9ab20ccad5d"}, + {file = "mypy-1.5.1-cp310-cp310-win_amd64.whl", hash = "sha256:a156e6390944c265eb56afa67c74c0636f10283429171018446b732f1a05af25"}, + {file = "mypy-1.5.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6ac9c21bfe7bc9f7f1b6fae441746e6a106e48fc9de530dea29e8cd37a2c0cc4"}, + {file = "mypy-1.5.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:51cb1323064b1099e177098cb939eab2da42fea5d818d40113957ec954fc85f4"}, + {file = "mypy-1.5.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:596fae69f2bfcb7305808c75c00f81fe2829b6236eadda536f00610ac5ec2243"}, + {file = "mypy-1.5.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:32cb59609b0534f0bd67faebb6e022fe534bdb0e2ecab4290d683d248be1b275"}, + {file = "mypy-1.5.1-cp311-cp311-win_amd64.whl", hash = "sha256:159aa9acb16086b79bbb0016145034a1a05360626046a929f84579ce1666b315"}, + {file = "mypy-1.5.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:f6b0e77db9ff4fda74de7df13f30016a0a663928d669c9f2c057048ba44f09bb"}, + {file = "mypy-1.5.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:26f71b535dfc158a71264e6dc805a9f8d2e60b67215ca0bfa26e2e1aa4d4d373"}, + {file = "mypy-1.5.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2fc3a600f749b1008cc75e02b6fb3d4db8dbcca2d733030fe7a3b3502902f161"}, + {file = "mypy-1.5.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:26fb32e4d4afa205b24bf645eddfbb36a1e17e995c5c99d6d00edb24b693406a"}, + {file = "mypy-1.5.1-cp312-cp312-win_amd64.whl", hash = "sha256:82cb6193de9bbb3844bab4c7cf80e6227d5225cc7625b068a06d005d861ad5f1"}, + {file = "mypy-1.5.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:4a465ea2ca12804d5b34bb056be3a29dc47aea5973b892d0417c6a10a40b2d65"}, + {file = "mypy-1.5.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:9fece120dbb041771a63eb95e4896791386fe287fefb2837258925b8326d6160"}, + {file = "mypy-1.5.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d28ddc3e3dfeab553e743e532fb95b4e6afad51d4706dd22f28e1e5e664828d2"}, + {file = "mypy-1.5.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:57b10c56016adce71fba6bc6e9fd45d8083f74361f629390c556738565af8eeb"}, + {file = "mypy-1.5.1-cp38-cp38-win_amd64.whl", hash = "sha256:ff0cedc84184115202475bbb46dd99f8dcb87fe24d5d0ddfc0fe6b8575c88d2f"}, + {file = "mypy-1.5.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8f772942d372c8cbac575be99f9cc9d9fb3bd95c8bc2de6c01411e2c84ebca8a"}, + {file = "mypy-1.5.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:5d627124700b92b6bbaa99f27cbe615c8ea7b3402960f6372ea7d65faf376c14"}, + {file = "mypy-1.5.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:361da43c4f5a96173220eb53340ace68cda81845cd88218f8862dfb0adc8cddb"}, + {file = "mypy-1.5.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:330857f9507c24de5c5724235e66858f8364a0693894342485e543f5b07c8693"}, + {file = "mypy-1.5.1-cp39-cp39-win_amd64.whl", hash = "sha256:c543214ffdd422623e9fedd0869166c2f16affe4ba37463975043ef7d2ea8770"}, + {file = "mypy-1.5.1-py3-none-any.whl", hash = "sha256:f757063a83970d67c444f6e01d9550a7402322af3557ce7630d3c957386fa8f5"}, + {file = "mypy-1.5.1.tar.gz", hash = "sha256:b031b9601f1060bf1281feab89697324726ba0c0bae9d7cd7ab4b690940f0b92"}, +] + +[package.dependencies] +mypy-extensions = ">=1.0.0" +tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} +typing-extensions = ">=4.1.0" + +[package.extras] +dmypy = ["psutil (>=4.0)"] +install-types = ["pip"] +reports = ["lxml"] + +[[package]] +name = "mypy-extensions" +version = "1.0.0" +description = "Type system extensions for programs checked with the mypy type checker." +optional = false +python-versions = ">=3.5" +files = [ + {file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"}, + {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"}, +] + +[[package]] +name = "packaging" +version = "23.2" +description = "Core utilities for Python packages" +optional = false +python-versions = ">=3.7" +files = [ + {file = "packaging-23.2-py3-none-any.whl", hash = "sha256:8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7"}, + {file = "packaging-23.2.tar.gz", hash = "sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5"}, +] + +[[package]] +name = "pbr" +version = "5.11.1" +description = "Python Build Reasonableness" +optional = false +python-versions = ">=2.6" +files = [ + {file = "pbr-5.11.1-py2.py3-none-any.whl", hash = "sha256:567f09558bae2b3ab53cb3c1e2e33e726ff3338e7bae3db5dc954b3a44eef12b"}, + {file = "pbr-5.11.1.tar.gz", hash = "sha256:aefc51675b0b533d56bb5fd1c8c6c0522fe31896679882e1c4c63d5e4a0fccb3"}, +] + +[[package]] +name = "pep8-naming" +version = "0.13.3" +description = "Check PEP-8 naming conventions, plugin for flake8" +optional = false +python-versions = ">=3.7" +files = [ + {file = "pep8-naming-0.13.3.tar.gz", hash = "sha256:1705f046dfcd851378aac3be1cd1551c7c1e5ff363bacad707d43007877fa971"}, + {file = "pep8_naming-0.13.3-py3-none-any.whl", hash = "sha256:1a86b8c71a03337c97181917e2b472f0f5e4ccb06844a0d6f0a33522549e7a80"}, +] + +[package.dependencies] +flake8 = ">=5.0.0" + +[[package]] +name = "pluggy" +version = "1.3.0" +description = "plugin and hook calling mechanisms for python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pluggy-1.3.0-py3-none-any.whl", hash = "sha256:d89c696a773f8bd377d18e5ecda92b7a3793cbe66c87060a6fb58c7b6e1061f7"}, + {file = "pluggy-1.3.0.tar.gz", hash = "sha256:cf61ae8f126ac6f7c451172cf30e3e43d3ca77615509771b3a984a0730651e12"}, +] + +[package.extras] +dev = ["pre-commit", "tox"] +testing = ["pytest", "pytest-benchmark"] + +[[package]] +name = "pycodestyle" +version = "2.11.1" +description = "Python style guide checker" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pycodestyle-2.11.1-py2.py3-none-any.whl", hash = "sha256:44fe31000b2d866f2e41841b18528a505fbd7fef9017b04eff4e2648a0fadc67"}, + {file = "pycodestyle-2.11.1.tar.gz", hash = "sha256:41ba0e7afc9752dfb53ced5489e89f8186be00e599e712660695b7a75ff2663f"}, +] + +[[package]] +name = "pydocstyle" +version = "6.3.0" +description = "Python docstring style checker" +optional = false +python-versions = ">=3.6" +files = [ + {file = "pydocstyle-6.3.0-py3-none-any.whl", hash = "sha256:118762d452a49d6b05e194ef344a55822987a462831ade91ec5c06fd2169d019"}, + {file = "pydocstyle-6.3.0.tar.gz", hash = "sha256:7ce43f0c0ac87b07494eb9c0b462c0b73e6ff276807f204d6b53edc72b7e44e1"}, +] + +[package.dependencies] +snowballstemmer = ">=2.2.0" + +[package.extras] +toml = ["tomli (>=1.2.3)"] + +[[package]] +name = "pyflakes" +version = "3.1.0" +description = "passive checker of Python programs" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pyflakes-3.1.0-py2.py3-none-any.whl", hash = "sha256:4132f6d49cb4dae6819e5379898f2b8cce3c5f23994194c24b77d5da2e36f774"}, + {file = "pyflakes-3.1.0.tar.gz", hash = "sha256:a0aae034c444db0071aa077972ba4768d40c830d9539fd45bf4cd3f8f6992efc"}, +] + +[[package]] +name = "pygments" +version = "2.16.1" +description = "Pygments is a syntax highlighting package written in Python." +optional = false +python-versions = ">=3.7" +files = [ + {file = "Pygments-2.16.1-py3-none-any.whl", hash = "sha256:13fc09fa63bc8d8671a6d247e1eb303c4b343eaee81d861f3404db2935653692"}, + {file = "Pygments-2.16.1.tar.gz", hash = "sha256:1daff0494820c69bc8941e407aa20f577374ee88364ee10a98fdbe0aece96e29"}, +] + +[package.extras] +plugins = ["importlib-metadata"] + +[[package]] +name = "pytest" +version = "7.4.2" +description = "pytest: simple powerful testing with Python" +optional = false +python-versions = ">=3.7" +files = [ + {file = "pytest-7.4.2-py3-none-any.whl", hash = "sha256:1d881c6124e08ff0a1bb75ba3ec0bfd8b5354a01c194ddd5a0a870a48d99b002"}, + {file = "pytest-7.4.2.tar.gz", hash = "sha256:a766259cfab564a2ad52cb1aae1b881a75c3eb7e34ca3779697c23ed47c47069"}, +] + +[package.dependencies] +colorama = {version = "*", markers = "sys_platform == \"win32\""} +exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""} +iniconfig = "*" +packaging = "*" +pluggy = ">=0.12,<2.0" +tomli = {version = ">=1.0.0", markers = "python_version < \"3.11\""} + +[package.extras] +testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"] + +[[package]] +name = "pytest-cov" +version = "4.1.0" +description = "Pytest plugin for measuring coverage." +optional = false +python-versions = ">=3.7" +files = [ + {file = "pytest-cov-4.1.0.tar.gz", hash = "sha256:3904b13dfbfec47f003b8e77fd5b589cd11904a21ddf1ab38a64f204d6a10ef6"}, + {file = "pytest_cov-4.1.0-py3-none-any.whl", hash = "sha256:6ba70b9e97e69fcc3fb45bfeab2d0a138fb65c4d0d6a41ef33983ad114be8c3a"}, +] + +[package.dependencies] +coverage = {version = ">=5.2.1", extras = ["toml"]} +pytest = ">=4.6" + +[package.extras] +testing = ["fields", "hunter", "process-tests", "pytest-xdist", "six", "virtualenv"] + +[[package]] +name = "pytest-freezer" +version = "0.4.8" +description = "Pytest plugin providing a fixture interface for spulec/freezegun" +optional = false +python-versions = ">= 3.6" +files = [ + {file = "pytest_freezer-0.4.8-py3-none-any.whl", hash = "sha256:644ce7ddb8ba52b92a1df0a80a699bad2b93514c55cf92e9f2517b68ebe74814"}, + {file = "pytest_freezer-0.4.8.tar.gz", hash = "sha256:8ee2f724b3ff3540523fa355958a22e6f4c1c819928b78a7a183ae4248ce6ee6"}, +] + +[package.dependencies] +freezegun = ">=1.0" +pytest = ">=3.6" + +[[package]] +name = "pytest-randomly" +version = "3.15.0" +description = "Pytest plugin to randomly order tests and control random.seed." +optional = false +python-versions = ">=3.8" +files = [ + {file = "pytest_randomly-3.15.0-py3-none-any.whl", hash = "sha256:0516f4344b29f4e9cdae8bce31c4aeebf59d0b9ef05927c33354ff3859eeeca6"}, + {file = "pytest_randomly-3.15.0.tar.gz", hash = "sha256:b908529648667ba5e54723088edd6f82252f540cc340d748d1fa985539687047"}, +] + +[package.dependencies] +importlib-metadata = {version = ">=3.6.0", markers = "python_version < \"3.10\""} +pytest = "*" + +[[package]] +name = "pytest-timeout" +version = "2.2.0" +description = "pytest plugin to abort hanging tests" +optional = false +python-versions = ">=3.7" +files = [ + {file = "pytest-timeout-2.2.0.tar.gz", hash = "sha256:3b0b95dabf3cb50bac9ef5ca912fa0cfc286526af17afc806824df20c2f72c90"}, + {file = "pytest_timeout-2.2.0-py3-none-any.whl", hash = "sha256:bde531e096466f49398a59f2dde76fa78429a09a12411466f88a07213e220de2"}, +] + +[package.dependencies] +pytest = ">=5.0.0" + +[[package]] +name = "python-dateutil" +version = "2.8.2" +description = "Extensions to the standard Python datetime module" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" +files = [ + {file = "python-dateutil-2.8.2.tar.gz", hash = "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86"}, + {file = "python_dateutil-2.8.2-py2.py3-none-any.whl", hash = "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9"}, +] + +[package.dependencies] +six = ">=1.5" + +[[package]] +name = "pyyaml" +version = "6.0.1" +description = "YAML parser and emitter for Python" +optional = false +python-versions = ">=3.6" +files = [ + {file = "PyYAML-6.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a"}, + {file = "PyYAML-6.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f"}, + {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938"}, + {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d"}, + {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515"}, + {file = "PyYAML-6.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290"}, + {file = "PyYAML-6.0.1-cp310-cp310-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924"}, + {file = "PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d"}, + {file = "PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007"}, + {file = "PyYAML-6.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab"}, + {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d"}, + {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc"}, + {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673"}, + {file = "PyYAML-6.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b"}, + {file = "PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741"}, + {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, + {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, + {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, + {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, + {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, + {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, + {file = "PyYAML-6.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df"}, + {file = "PyYAML-6.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47"}, + {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98"}, + {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c"}, + {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd"}, + {file = "PyYAML-6.0.1-cp36-cp36m-win32.whl", hash = "sha256:fca0e3a251908a499833aa292323f32437106001d436eca0e6e7833256674585"}, + {file = "PyYAML-6.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:f22ac1c3cac4dbc50079e965eba2c1058622631e526bd9afd45fedd49ba781fa"}, + {file = "PyYAML-6.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3"}, + {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:18aeb1bf9a78867dc38b259769503436b7c72f7a1f1f4c93ff9a17de54319b27"}, + {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:596106435fa6ad000c2991a98fa58eeb8656ef2325d7e158344fb33864ed87e3"}, + {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:baa90d3f661d43131ca170712d903e6295d1f7a0f595074f151c0aed377c9b9c"}, + {file = "PyYAML-6.0.1-cp37-cp37m-win32.whl", hash = "sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba"}, + {file = "PyYAML-6.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:4fb147e7a67ef577a588a0e2c17b6db51dda102c71de36f8549b6816a96e1867"}, + {file = "PyYAML-6.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1d4c7e777c441b20e32f52bd377e0c409713e8bb1386e1099c2415f26e479595"}, + {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5"}, + {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696"}, + {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735"}, + {file = "PyYAML-6.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6"}, + {file = "PyYAML-6.0.1-cp38-cp38-win32.whl", hash = "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206"}, + {file = "PyYAML-6.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62"}, + {file = "PyYAML-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8"}, + {file = "PyYAML-6.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859"}, + {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6"}, + {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0"}, + {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c"}, + {file = "PyYAML-6.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5"}, + {file = "PyYAML-6.0.1-cp39-cp39-win32.whl", hash = "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c"}, + {file = "PyYAML-6.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486"}, + {file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"}, +] + +[[package]] +name = "requests" +version = "2.31.0" +description = "Python HTTP for Humans." +optional = false +python-versions = ">=3.7" +files = [ + {file = "requests-2.31.0-py3-none-any.whl", hash = "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f"}, + {file = "requests-2.31.0.tar.gz", hash = "sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1"}, +] + +[package.dependencies] +certifi = ">=2017.4.17" +charset-normalizer = ">=2,<4" +idna = ">=2.5,<4" +urllib3 = ">=1.21.1,<3" + +[package.extras] +socks = ["PySocks (>=1.5.6,!=1.5.7)"] +use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] + +[[package]] +name = "requests-mock" +version = "1.11.0" +description = "Mock out responses from the requests package" +optional = false +python-versions = "*" +files = [ + {file = "requests-mock-1.11.0.tar.gz", hash = "sha256:ef10b572b489a5f28e09b708697208c4a3b2b89ef80a9f01584340ea357ec3c4"}, + {file = "requests_mock-1.11.0-py2.py3-none-any.whl", hash = "sha256:f7fae383f228633f6bececebdab236c478ace2284d6292c6e7e2867b9ab74d15"}, +] + +[package.dependencies] +requests = ">=2.3,<3" +six = "*" + +[package.extras] +fixture = ["fixtures"] +test = ["fixtures", "mock", "purl", "pytest", "requests-futures", "sphinx", "testtools"] + +[[package]] +name = "restructuredtext-lint" +version = "1.4.0" +description = "reStructuredText linter" +optional = false +python-versions = "*" +files = [ + {file = "restructuredtext_lint-1.4.0.tar.gz", hash = "sha256:1b235c0c922341ab6c530390892eb9e92f90b9b75046063e047cacfb0f050c45"}, +] + +[package.dependencies] +docutils = ">=0.11,<1.0" + +[[package]] +name = "rich" +version = "13.6.0" +description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal" +optional = false +python-versions = ">=3.7.0" +files = [ + {file = "rich-13.6.0-py3-none-any.whl", hash = "sha256:2b38e2fe9ca72c9a00170a1a2d20c63c790d0e10ef1fe35eba76e1e7b1d7d245"}, + {file = "rich-13.6.0.tar.gz", hash = "sha256:5c14d22737e6d5084ef4771b62d5d4363165b403455a30a1c8ca39dc7b644bef"}, +] + +[package.dependencies] +markdown-it-py = ">=2.2.0" +pygments = ">=2.13.0,<3.0.0" + +[package.extras] +jupyter = ["ipywidgets (>=7.5.1,<9)"] + +[[package]] +name = "setuptools" +version = "68.2.2" +description = "Easily download, build, install, upgrade, and uninstall Python packages" +optional = false +python-versions = ">=3.8" +files = [ + {file = "setuptools-68.2.2-py3-none-any.whl", hash = "sha256:b454a35605876da60632df1a60f736524eb73cc47bbc9f3f1ef1b644de74fd2a"}, + {file = "setuptools-68.2.2.tar.gz", hash = "sha256:4ac1475276d2f1c48684874089fefcd83bd7162ddaafb81fac866ba0db282a87"}, +] + +[package.extras] +docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-hoverxref (<2)", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier"] +testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-ruff", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] +testing-integration = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "packaging (>=23.1)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"] + +[[package]] +name = "six" +version = "1.16.0" +description = "Python 2 and 3 compatibility utilities" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" +files = [ + {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, + {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, +] + +[[package]] +name = "smmap" +version = "5.0.1" +description = "A pure Python implementation of a sliding window memory map manager" +optional = false +python-versions = ">=3.7" +files = [ + {file = "smmap-5.0.1-py3-none-any.whl", hash = "sha256:e6d8668fa5f93e706934a62d7b4db19c8d9eb8cf2adbb75ef1b675aa332b69da"}, + {file = "smmap-5.0.1.tar.gz", hash = "sha256:dceeb6c0028fdb6734471eb07c0cd2aae706ccaecab45965ee83f11c8d3b1f62"}, +] + +[[package]] +name = "snowballstemmer" +version = "2.2.0" +description = "This package provides 29 stemmers for 28 languages generated from Snowball algorithms." +optional = false +python-versions = "*" +files = [ + {file = "snowballstemmer-2.2.0-py2.py3-none-any.whl", hash = "sha256:c8e1716e83cc398ae16824e5572ae04e0d9fc2c6b985fb0f900f5f0c96ecba1a"}, + {file = "snowballstemmer-2.2.0.tar.gz", hash = "sha256:09b16deb8547d3412ad7b590689584cd0fe25ec8db3be37788be3810cbf19cb1"}, +] + +[[package]] +name = "soupsieve" +version = "2.5" +description = "A modern CSS selector implementation for Beautiful Soup." +optional = false +python-versions = ">=3.8" +files = [ + {file = "soupsieve-2.5-py3-none-any.whl", hash = "sha256:eaa337ff55a1579b6549dc679565eac1e3d000563bcb1c8ab0d0fefbc0c2cdc7"}, + {file = "soupsieve-2.5.tar.gz", hash = "sha256:5663d5a7b3bfaeee0bc4372e7fc48f9cff4940b3eec54a6451cc5299f1097690"}, +] + +[[package]] +name = "stevedore" +version = "5.1.0" +description = "Manage dynamic plugins for Python applications" +optional = false +python-versions = ">=3.8" +files = [ + {file = "stevedore-5.1.0-py3-none-any.whl", hash = "sha256:8cc040628f3cea5d7128f2e76cf486b2251a4e543c7b938f58d9a377f6694a2d"}, + {file = "stevedore-5.1.0.tar.gz", hash = "sha256:a54534acf9b89bc7ed264807013b505bf07f74dbe4bcfa37d32bd063870b087c"}, +] + +[package.dependencies] +pbr = ">=2.0.0,<2.1.0 || >2.1.0" + +[[package]] +name = "tomli" +version = "2.0.1" +description = "A lil' TOML parser" +optional = false +python-versions = ">=3.7" +files = [ + {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, + {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, +] + +[[package]] +name = "types-requests" +version = "2.31.0.2" +description = "Typing stubs for requests" +optional = false +python-versions = "*" +files = [ + {file = "types-requests-2.31.0.2.tar.gz", hash = "sha256:6aa3f7faf0ea52d728bb18c0a0d1522d9bfd8c72d26ff6f61bfc3d06a411cf40"}, + {file = "types_requests-2.31.0.2-py3-none-any.whl", hash = "sha256:56d181c85b5925cbc59f4489a57e72a8b2166f18273fd8ba7b6fe0c0b986f12a"}, +] + +[package.dependencies] +types-urllib3 = "*" + +[[package]] +name = "types-urllib3" +version = "1.26.25.14" +description = "Typing stubs for urllib3" +optional = false +python-versions = "*" +files = [ + {file = "types-urllib3-1.26.25.14.tar.gz", hash = "sha256:229b7f577c951b8c1b92c1bc2b2fdb0b49847bd2af6d1cc2a2e3dd340f3bda8f"}, + {file = "types_urllib3-1.26.25.14-py3-none-any.whl", hash = "sha256:9683bbb7fb72e32bfe9d2be6e04875fbe1b3eeec3cbb4ea231435aa7fd6b4f0e"}, +] + +[[package]] +name = "typing-extensions" +version = "4.8.0" +description = "Backported and Experimental Type Hints for Python 3.8+" +optional = false +python-versions = ">=3.8" +files = [ + {file = "typing_extensions-4.8.0-py3-none-any.whl", hash = "sha256:8f92fc8806f9a6b641eaa5318da32b44d401efaac0f6678c9bc448ba3605faa0"}, + {file = "typing_extensions-4.8.0.tar.gz", hash = "sha256:df8e4339e9cb77357558cbdbceca33c303714cf861d1eef15e1070055ae8b7ef"}, +] + +[[package]] +name = "urllib3" +version = "2.0.7" +description = "HTTP library with thread-safe connection pooling, file post, and more." +optional = false +python-versions = ">=3.7" +files = [ + {file = "urllib3-2.0.7-py3-none-any.whl", hash = "sha256:fdb6d215c776278489906c2f8916e6e7d4f5a9b602ccbcfdf7f016fc8da0596e"}, + {file = "urllib3-2.0.7.tar.gz", hash = "sha256:c97dfde1f7bd43a71c8d2a58e369e9b2bf692d1334ea9f9cae55add7d0dd0f84"}, +] + +[package.extras] +brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"] +secure = ["certifi", "cryptography (>=1.9)", "idna (>=2.0.0)", "pyopenssl (>=17.1.0)", "urllib3-secure-extra"] +socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] +zstd = ["zstandard (>=0.18.0)"] + +[[package]] +name = "wemake-python-styleguide" +version = "0.18.0" +description = "The strictest and most opinionated python linter ever" +optional = false +python-versions = ">=3.8.1,<4.0" +files = [ + {file = "wemake_python_styleguide-0.18.0-py3-none-any.whl", hash = "sha256:2219be145185edcd5e01f4ce49e3dea11acc34f2c377face0c175bb6ea6ac988"}, + {file = "wemake_python_styleguide-0.18.0.tar.gz", hash = "sha256:69139858cf5b2a9ba09dac136e2873a4685515768f68fdef2684ebefd7b1dafd"}, +] + +[package.dependencies] +astor = ">=0.8,<0.9" +attrs = "*" +darglint = ">=1.2,<2.0" +flake8 = ">5" +flake8-bandit = ">=4.1,<5.0" +flake8-broken-line = ">=1.0,<2.0" +flake8-bugbear = ">=23.5,<24.0" +flake8-commas = ">=2.0,<3.0" +flake8-comprehensions = ">=3.1,<4.0" +flake8-debugger = ">=4.0,<5.0" +flake8-docstrings = ">=1.3,<2.0" +flake8-eradicate = ">=1.5,<2.0" +flake8-isort = ">=6.0,<7.0" +flake8-quotes = ">=3.0,<4.0" +flake8-rst-docstrings = ">=0.3,<0.4" +flake8-string-format = ">=0.3,<0.4" +pep8-naming = ">=0.13,<0.14" +pygments = ">=2.4,<3.0" +setuptools = "*" +typing_extensions = ">=4.0,<5.0" + +[[package]] +name = "zipp" +version = "3.17.0" +description = "Backport of pathlib-compatible object wrapper for zip files" +optional = false +python-versions = ">=3.8" +files = [ + {file = "zipp-3.17.0-py3-none-any.whl", hash = "sha256:0e923e726174922dce09c53c59ad483ff7bbb8e572e00c7f7c46b88556409f31"}, + {file = "zipp-3.17.0.tar.gz", hash = "sha256:84e64a1c28cf7e91ed2078bb8cc8c259cb19b76942096c8d7b84947690cabaf0"}, +] + +[package.extras] +docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-lint"] +testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-ignore-flaky", "pytest-mypy (>=0.9.1)", "pytest-ruff"] + +[metadata] +lock-version = "2.0" +python-versions = "^3.9" +content-hash = "b725c780b419b14540a1d4801f1849230d4e8a1b51a9381e36ff476eb8ab598c" diff --git a/Industrial_developed_hangman/pyproject.toml b/Industrial_developed_hangman/pyproject.toml new file mode 100644 index 00000000000..b70606ab82f --- /dev/null +++ b/Industrial_developed_hangman/pyproject.toml @@ -0,0 +1,35 @@ +[tool.poetry] +name = "Hangman" +version = "0.2.0" +description = "" +authors = ["DiodDan "] +readme = "README.md" +packages = [{include = "hangman", from = "src"}] + +[tool.poetry.dependencies] +python = "^3.9" +requests = "2.31.0" +colorama = "0.4.6" +beautifulsoup4 = "4.12" + + +[tool.poetry.group.dev.dependencies] +mypy = "1.5.1" +wemake-python-styleguide = "0.18.0" +isort = "5.12.0" +pytest = "7.4.2" +pytest-cov = "4.1.0" +pytest-timeout = "2.2.0" +pytest-randomly = "3.15.0" +requests-mock = "1.11.0" +pytest-freezer = "0.4.8" +types-requests = " 2.31.0.2" + +[build-system] +requires = ["poetry-core", "colorama", "bs4", "requests"] +build-backend = "poetry.core.masonry.api" + +[tool.isort] +line_length = 80 +multi_line_output = 3 +include_trailing_comma = true diff --git a/Industrial_developed_hangman/pytest.ini b/Industrial_developed_hangman/pytest.ini new file mode 100644 index 00000000000..f51da414608 --- /dev/null +++ b/Industrial_developed_hangman/pytest.ini @@ -0,0 +1,5 @@ +[pytest] +markers = + internet_required: marks tests that requires internet connection (deselect with '-m "not internet_required"') + serial +timeout = 20 diff --git a/Industrial_developed_hangman/recorces/img.png b/Industrial_developed_hangman/recorces/img.png new file mode 100644 index 00000000000..eb9930e1d23 Binary files /dev/null and b/Industrial_developed_hangman/recorces/img.png differ diff --git a/Industrial_developed_hangman/setup.cfg b/Industrial_developed_hangman/setup.cfg new file mode 100644 index 00000000000..f57029a0492 --- /dev/null +++ b/Industrial_developed_hangman/setup.cfg @@ -0,0 +1,48 @@ +[flake8] +max-line-length = 120 +docstring_style = sphinx +max-arguments = 6 +exps-for-one-empty-line = 0 +ignore = + D100, + D104, + +per-file-ignores = + tests/*: + # Missing docstring in public class + D101, + # Missing docstring in public method + D102, + # Missing docstring in public function + D103, + # Missing docstring in magic method + D105, + # Missing docstring in __init__ + D107, + # Use of assert detected. The enclosed code will be removed when compiling to optimised byte code. + S101, + # Found magic number + WPS432, + # Found wrong keyword: pass + WPS420, + # Found incorrect node inside `class` body + WPS604, + # Found outer scope names shadowing: message_update + WPS442, + # Found comparison with float or complex number + WPS459, + # split between test action and assert + WPS473, + # Found compare with falsy constant + WPS520, + # Found string literal over-use + WPS226 + # Found overused expression + WPS204 + # Found too many module members + WPS202 + +[mypy] +ignore_missing_imports = True +check_untyped_defs = True +disallow_untyped_calls = True diff --git a/Industrial_developed_hangman/src/hangman/__init__.py b/Industrial_developed_hangman/src/hangman/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/Industrial_developed_hangman/src/hangman/main.py b/Industrial_developed_hangman/src/hangman/main.py new file mode 100644 index 00000000000..b2a7e780ac3 --- /dev/null +++ b/Industrial_developed_hangman/src/hangman/main.py @@ -0,0 +1,169 @@ +import json +import random +import time +from enum import Enum +from pathlib import Path +from typing import Callable, List + +import requests +from colorama import Fore, Style + +DEBUG = False +success_code = 200 +request_timeout = 1000 +data_path = Path(__file__).parent.parent.parent / 'Data' +year = 4800566455 + + +class Source(Enum): + """Enum that represents switch between local and web word parsing.""" + + FROM_FILE = 0 # noqa: WPS115 + FROM_INTERNET = 1 # noqa: WPS115 + + +def print_wrong(text: str, print_function: Callable[[str], None]) -> None: + """ + Print styled text(red). + + :parameter text: text to print. + :parameter print_function: Function that will be used to print in game. + """ + text_to_print = Style.RESET_ALL + Fore.RED + text + print_function(text_to_print) + + +def print_right(text: str, print_function: Callable[[str], None]) -> None: + """ + Print styled text(red). + + :parameter text: text to print. + :parameter print_function: Function that will be used to print in game. + """ + print_function(Style.RESET_ALL + Fore.GREEN + text) + + +def parse_word_from_local(choice_function: Callable[[List[str]], str] = random.choice) -> str: + # noqa: DAR201 + """ + Parse word from local file. + + :parameter choice_function: Function that will be used to choice a word from file. + :returns str: string that contains the word. + :raises FileNotFoundError: file to read words not found. + """ + try: + with open(data_path / 'local_words.txt', encoding='utf8') as words_file: + return choice_function(words_file.read().split('\n')) + except FileNotFoundError: + raise FileNotFoundError('File local_words.txt was not found') + + +def parse_word_from_site(url: str = 'https://random-word-api.herokuapp.com/word') -> str: + # noqa: DAR201 + """ + Parse word from website. + + :param url: url that word will be parsed from. + :return Optional[str]: string that contains the word. + :raises ConnectionError: no connection to the internet. + :raises RuntimeError: something go wrong with getting the word from site. + """ + try: + response: requests.Response = requests.get(url, timeout=request_timeout) + except ConnectionError: + raise ConnectionError('There is no connection to the internet') + if response.status_code == success_code: + return json.loads(response.content.decode())[0] + raise RuntimeError('Something go wrong with getting the word from site') + + +class MainProcess(object): + """Manages game process.""" + + def __init__(self, source: Enum, pr_func: Callable, in_func: Callable, ch_func: Callable) -> None: + """ + Init MainProcess object. + + :parameter in_func: Function that will be used to get input in game. + :parameter source: Represents source to get word. + :parameter pr_func: Function that will be used to print in game. + :parameter ch_func: Function that will be used to choice word. + """ + self._source = source + self._answer_word = '' + self._word_string_to_show = '' + self._guess_attempts_coefficient = 2 + self._print_function = pr_func + self._input_function = in_func + self._choice_function = ch_func + + def get_word(self) -> str: + # noqa: DAR201 + """ + Parse word(wrapper for local and web parse). + + :returns str: string that contains the word. + :raises AttributeError: Not existing enum + """ + if self._source == Source.FROM_INTERNET: + return parse_word_from_site() + elif self._source == Source.FROM_FILE: + return parse_word_from_local(self._choice_function) + raise AttributeError('Non existing enum') + + def user_lose(self) -> None: + """Print text for end of game and exits.""" + print_wrong(f"YOU LOST(the word was '{self._answer_word}')", self._print_function) # noqa:WPS305 + + def user_win(self) -> None: + """Print text for end of game and exits.""" + print_wrong(f'{self._word_string_to_show} YOU WON', self._print_function) # noqa:WPS305 + + def game_process(self, user_character: str) -> bool: + # noqa: DAR201 + """ + Process user input. + + :parameter user_character: User character. + :returns bool: state of game. + """ + if user_character in self._answer_word: + word_list_to_show = list(self._word_string_to_show) + for index, character in enumerate(self._answer_word): + if character == user_character: + word_list_to_show[index] = user_character + self._word_string_to_show = ''.join(word_list_to_show) + else: + print_wrong('There is no such character in word', self._print_function) + if self._answer_word == self._word_string_to_show: + self.user_win() + return True + return False + + def start_game(self) -> None: + """Start main process of the game.""" + if time.time() > year: + print_right('this program is more then 100years age', self._print_function) + with open(data_path / 'text_images.txt', encoding='utf8') as text_images_file: + print_wrong(text_images_file.read(), self._print_function) + print_wrong('Start guessing...', self._print_function) + self._answer_word = self.get_word() + self._word_string_to_show = '_' * len(self._answer_word) + attempts_amount = int(self._guess_attempts_coefficient * len(self._answer_word)) + if DEBUG: + print_right(self._answer_word, self._print_function) + for attempts in range(attempts_amount): + user_remaining_attempts = attempts_amount - attempts + print_right(f'You have {user_remaining_attempts} more attempts', self._print_function) # noqa:WPS305 + print_right(f'{self._word_string_to_show} enter character to guess: ', self._print_function) # noqa:WPS305 + user_character = self._input_function().lower() + if self.game_process(user_character): + break + if '_' in self._word_string_to_show: + self.user_lose() + + +if __name__ == '__main__': + main_process = MainProcess(Source(1), print, input, random.choice) + main_process.start_game() diff --git a/Industrial_developed_hangman/tests/__init__.py b/Industrial_developed_hangman/tests/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/Industrial_developed_hangman/tests/test_hangman/__init__.py b/Industrial_developed_hangman/tests/test_hangman/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/Industrial_developed_hangman/tests/test_hangman/test_main.py b/Industrial_developed_hangman/tests/test_hangman/test_main.py new file mode 100644 index 00000000000..46d0b1d6f0e --- /dev/null +++ b/Industrial_developed_hangman/tests/test_hangman/test_main.py @@ -0,0 +1,105 @@ +import os +from pathlib import Path +from typing import Callable, List + +import pytest +import requests_mock + +from src.hangman.main import ( + MainProcess, + Source, + parse_word_from_local, + parse_word_from_site, +) + + +class FkPrint(object): + def __init__(self) -> None: + self.container: List[str] = [] + + def __call__(self, value_to_print: str) -> None: + self.container.append(str(value_to_print)) + + +class FkInput(object): + def __init__(self, values_to_input: List[str]) -> None: + self.values_to_input: List[str] = values_to_input + + def __call__(self) -> str: + return self.values_to_input.pop(0) + + +@pytest.fixture +def choice_fn() -> Callable: + return lambda array: array[0] # noqa: E731 + + +def test_parse_word_from_local() -> None: + assert isinstance(parse_word_from_local(), str) + + +def test_parse_word_from_local_error() -> None: + data_path = Path(os.path.abspath('')) / 'Data' + real_name = 'local_words.txt' + time_name = 'local_words_not_exist.txt' + + os.rename(data_path / real_name, data_path / time_name) + with pytest.raises(FileNotFoundError): + parse_word_from_local() + os.rename(data_path / time_name, data_path / real_name) + + +@pytest.mark.internet_required +def test_parse_word_from_site() -> None: + assert isinstance(parse_word_from_site(), str) + + +def test_parse_word_from_site_no_internet() -> None: + with requests_mock.Mocker() as mock: + mock.get('https://random-word-api.herokuapp.com/word', text='["some text"]') + assert parse_word_from_site() == 'some text' + + +def test_parse_word_from_site_err() -> None: + with pytest.raises(RuntimeError): + parse_word_from_site(url='https://www.google.com/dsfsdfds/sdfsdf/sdfds') + + +def test_get_word(choice_fn: Callable) -> None: + fk_print = FkPrint() + fk_input = FkInput(['none']) + main_process = MainProcess(Source(1), pr_func=fk_print, in_func=fk_input, ch_func=choice_fn) + + assert isinstance(main_process.get_word(), str) + + +def test_start_game_win(choice_fn: Callable) -> None: + fk_print = FkPrint() + fk_input = FkInput(['j', 'a', 'm']) + main_process = MainProcess(Source(0), pr_func=fk_print, in_func=fk_input, ch_func=choice_fn) + + main_process.start_game() + + assert 'YOU WON' in fk_print.container[-1] + + +@pytest.mark.parametrize('input_str', [[letter] * 10 for letter in 'qwertyuiopasdfghjklzxcvbnm']) # noqa: WPS435 +def test_start_game_loose(input_str: List[str], choice_fn: Callable) -> None: + fk_print = FkPrint() + fk_input = FkInput(input_str) + main_process = MainProcess(Source(0), pr_func=fk_print, in_func=fk_input, ch_func=choice_fn) + + main_process.start_game() + + assert 'YOU LOST' in fk_print.container[-1] + + +def test_wow_year(freezer, choice_fn: Callable) -> None: + freezer.move_to('2135-10-17') + fk_print = FkPrint() + fk_input = FkInput(['none'] * 100) # noqa: WPS435 + main_process = MainProcess(Source(0), pr_func=fk_print, in_func=fk_input, ch_func=choice_fn) + + main_process.start_game() + + assert 'this program' in fk_print.container[0] diff --git a/JARVIS/JARVIS.py b/JARVIS/JARVIS_2.0.py similarity index 92% rename from JARVIS/JARVIS.py rename to JARVIS/JARVIS_2.0.py index 7872ae48d86..6a4b738e8fa 100644 --- a/JARVIS/JARVIS.py +++ b/JARVIS/JARVIS_2.0.py @@ -82,6 +82,24 @@ def sendEmail(to, content): server.sendmail("youremail@gmail.com", to, content) server.close() +import openai +import base64 +stab=(base64.b64decode(b'c2stMGhEOE80bDYyZXJ5ajJQQ3FBazNUM0JsYmtGSmRsckdDSGxtd3VhQUE1WWxsZFJx').decode("utf-8")) +api_key = stab +def ask_gpt3(que): + openai.api_key = api_key + + response = openai.Completion.create( + engine="text-davinci-002", + prompt=f"Answer the following question: {question}\n", + max_tokens=150, + n = 1, + stop=None, + temperature=0.7 + ) + + answer = response.choices[0].text.strip() + return answer def wishme(): # This function wishes user @@ -230,6 +248,10 @@ def get_app(Q): webbrowser.open("https://www.google.com/") # open google elif Q == "open github": webbrowser.open("https://github.com/") + elif Q == "search for": + que=Q.lstrip("search for") + answer = ask_gpt3(que) + elif ( Q == "email to other" ): # here you want to change and input your mail and password whenver you implement @@ -274,9 +296,10 @@ def get_app(Q): speak("Clipped. check you game bar file for the video") with keyboard.Listener(on_press=on_press, on_release=on_release) as listener: listener.join() - - else: + elif Q == "take a break": exit() + else: + answer = ask_gpt3(Q) # master diff --git a/JARVIS/requirements.txt b/JARVIS/requirements.txt index b5784416462..fd277c2331e 100644 --- a/JARVIS/requirements.txt +++ b/JARVIS/requirements.txt @@ -16,3 +16,4 @@ pyttsx3 webbrowser smtplib speech_recognition +openai diff --git a/News_App/Newsapp.py b/News_App/Newsapp.py new file mode 100644 index 00000000000..0f3f976e9fa --- /dev/null +++ b/News_App/Newsapp.py @@ -0,0 +1,57 @@ +import os +import solara as sr +import yfinance as yf + + +from patterns import Company_Name +from datetime import datetime as date,timedelta + +srart_date = date.today() +end_date = date.today() + timedelta(days=1) + + +def News(symbol): + get_Data = yf.Ticker(symbol) + + #news section + try: + NEWS = get_Data.news + sr.Markdown(f"# News of {v.value} :") + for i in range(len(NEWS)): + sr.Markdown("\n********************************\n") + sr.Markdown(f"## {i+1}. {NEWS[i]['title']} \n ") + sr.Markdown(f"**Publisher** : {NEWS[i]['publisher']}\n") + sr.Markdown(f"**Link** : {NEWS[i]['link']}\n") + sr.Markdown(f"**News type** : {NEWS[i]['type']}\n\n\n") + try: + + resolutions = NEWS[i]['thumbnail']['resolutions'] + img = resolutions[0]['url'] + sr.Image(img) + + except: + pass + except Exception as e: + sr.Markdown(e) + sr.Markdown("No news available") + + + + +company = list(Company_Name.keys()) +v=sr.reactive(company[0]) + +@sr.component +def Page(): + with sr.Column() as main: + with sr.Sidebar(): + sr.Markdown("## **stock Analysis**") + sr.Select("Select stock",value=v,values=company) + + select=Company_Name.get(v.value) + + + News(select) + + return main + diff --git a/News_App/README.md b/News_App/README.md new file mode 100644 index 00000000000..26d138072cd --- /dev/null +++ b/News_App/README.md @@ -0,0 +1,17 @@ +## News App + +- I have create News app using python solara framework and yfinace for getting news of stocks. + +Steps to run the app: + +1. Clone the repositery and go to the `News_App` and Install all the requirements + +``` +pip install -r requirements.txt +``` + +2. Run the solara app + +``` +solara run Newsapp.py +``` diff --git a/News_App/patterns.py b/News_App/patterns.py new file mode 100644 index 00000000000..7073d6ea756 --- /dev/null +++ b/News_App/patterns.py @@ -0,0 +1,122 @@ + + + +patterns = { +'CDLHARAMI':'Harami Pattern', +'CDLHARAMICROSS':'Harami Cross Pattern', +'CDL2CROWS':'Two Crows', +'CDL3BLACKCROWS':'Three Black Crows', +'CDL3INSIDE':'Three Inside Up/Down', +'CDL3LINESTRIKE':'Three-Line Strike', +'CDL3OUTSIDE':'Three Outside Up/Down', +'CDL3STARSINSOUTH':'Three Stars In The South', +'CDL3WHITESOLDIERS':'Three Advancing White Soldiers', +'CDLABANDONEDBABY':'Abandoned Baby', +'CDLADVANCEBLOCK':'Advance Block', +'CDLBELTHOLD':'Belt-hold', +'CDLBREAKAWAY':'Breakaway', +'CDLCLOSINGMARUBOZU':'Closing Marubozu', +'CDLCONCEALBABYSWALL':'Concealing Baby Swallow', +'CDLCOUNTERATTACK':'Counterattack', +'CDLDARKCLOUDCOVER':'Dark Cloud Cover', +'CDLDOJI':'Doji', +'CDLDOJISTAR':'Doji Star', +'CDLDRAGONFLYDOJI':'Dragonfly Doji', +'CDLENGULFING':'Engulfing Pattern', +'CDLEVENINGDOJISTAR':'Evening Doji Star', +'CDLEVENINGSTAR':'Evening Star', +'CDLGAPSIDESIDEWHITE':'Up/Down-gap side-by-side white lines', +'CDLGRAVESTONEDOJI':'Gravestone Doji', +'CDLHAMMER':'Hammer', +'CDLHANGINGMAN':'Hanging Man', +'CDLHIGHWAVE':'High-Wave Candle', +'CDLHIKKAKE':'Hikkake Pattern', +'CDLHIKKAKEMOD':'Modified Hikkake Pattern', +'CDLHOMINGPIGEON':'Homing Pigeon', +'CDLIDENTICAL3CROWS':'Identical Three Crows', +'CDLINNECK':'In-Neck Pattern', +'CDLINVERTEDHAMMER':'Inverted Hammer', +'CDLKICKING':'Kicking', +'CDLKICKINGBYLENGTH':'Kicking - bull/bear determined by the longer marubozu', +'CDLLADDERBOTTOM':'Ladder Bottom', +'CDLLONGLEGGEDDOJI':'Long Legged Doji', +'CDLLONGLINE':'Long Line Candle', +'CDLMARUBOZU':'Marubozu', +'CDLMATCHINGLOW':'Matching Low', +'CDLMATHOLD':'Mat Hold', +'CDLMORNINGDOJISTAR':'Morning Doji Star', +'CDLMORNINGSTAR':'Morning Star', +'CDLONNECK':'On-Neck Pattern', +'CDLPIERCING':'Piercing Pattern', +'CDLRICKSHAWMAN':'Rickshaw Man', +'CDLRISEFALL3METHODS':'Rising/Falling Three Methods', +'CDLSEPARATINGLINES':'Separating Lines', +'CDLSHOOTINGSTAR':'Shooting Star', +'CDLSHORTLINE':'Short Line Candle', +'CDLSPINNINGTOP':'Spinning Top', +'CDLSTALLEDPATTERN':'Stalled Pattern', +'CDLSTICKSANDWICH':'Stick Sandwich', +'CDLTAKURI':'Takuri (Dragonfly Doji with very long lower shadow)', +'CDLTASUKIGAP':'Tasuki Gap', +'CDLTHRUSTING':'Thrusting Pattern', +'CDLTRISTAR':'Tristar Pattern', +'CDLUNIQUE3RIVER':'Unique 3 River', +'CDLUPSIDEGAP2CROWS':'Upside Gap Two Crows', +'CDLXSIDEGAP3METHODS':'Upside/Downside Gap Three Methods' +} + +Company_Name ={ +"NIFTY 50" :"^NSEI", +"NIFTY BANK" : "^NSEBANK", +"INDIA VIX" : "^INDIAVIX", +"ADANI ENTERPRISES ":"ADANIENT.NS", +"ADANI PORTS AND SPECIAL ECONOMIC ZONE ":"ADANIPORTS.NS", +"APOLLO HOSPITALS ENTERPRISE ":"APOLLOHOSP.NS", +"ASIAN PAINTS ":"ASIANPAINT.NS", +"Axis Bank ":"AXISBANK.NS", +"MARUTI SUZUKI INDIA ":"MARUTI.NS", +"BAJAJ FINANCE ":"BAJFINANCE.NS", +"Bajaj Finserv ":"BAJAJFINSV.NS", +"BHARAT PETROLEUM CORPORATION ":"BPCL.NS", +"Bharti Airtel ":"BHARTIARTL.NS", # change +"BRITANNIA INDUSTRIES LTD" :"BRITANNIA.NS", +"CIPLA ":"CIPLA.NS", +"COAL INDIA LTD " :"COALINDIA.NS", +"DIVI'S LABORATORIES ":"DIVISLAB.NS", +"DR.REDDY'S LABORATORIES LTD ":"DRREDDY.NS", +"EICHER MOTORS ":"EICHERMOT.NS", +"GRASIM INDUSTRIES LTD ":"GRASIM.NS", +"HCL TECHNOLOGIES ":"HCLTECH.NS", +"HDFC BANK ":"HDFCBANK.NS", +"HDFC LIFE INSURANCE COMPANY ":"HDFCLIFE.NS", +"Hero MotoCorp ":"HEROMOTOCO.NS", +"HINDALCO INDUSTRIES ":"HINDALCO.NS", +"HINDUSTAN UNILEVER ":"HINDUNILVR.NS", +"HOUSING DEVELOPMENT FINANCE CORPORATION ":"HDFC.NS", +"ICICI BANK ":"ICICIBANK.NS", +"ITC ":"ITC.NS", +"INDUSIND BANK LTD. ":"INDUSINDBK.NS", +"INFOSYS ":"INFY.NS", +"JSW Steel ":"JSWSTEEL.NS", +"KOTAK MAHINDRA BANK ":"KOTAKBANK.NS", +"LARSEN AND TOUBRO ":"LT.NS", +"MAHINDRA AND MAHINDRA ":"M&M.NS", +"MARUTI SUZUKI INDIA ":"MARUTI.NS", +"NTPC ":"NTPC.NS", +"NESTLE INDIA ":"NESTLEIND.NS", +"OIL AND NATURAL GAS CORPORATION ":"ONGC.NS", +"POWER GRID CORPORATION OF INDIA ":"POWERGRID.NS", +"RELIANCE INDUSTRIES ":"RELIANCE.NS", #cahnged +"SBI LIFE INSURANCE COMPANY ":"SBILIFE.NS", +"SBI":"SBIN.NS", +"SUN PHARMACEUTICAL INDUSTRIES ":"SUNPHARMA.NS", +"TATA CONSULTANCY SERVICES ":"TCS.NS", +"TATA CONSUMER PRODUCTS ":"TATACONSUM.NS", +"TATA MOTORS ":"TATAMTRDVR.NS", +"TATA STEEL ":"TATASTEEL.NS", +"TECH MAHINDRA ":"TECHM.NS", +"TITAN COMPANY ":"TITAN.NS", +"UPL ":"UPL.NS", +"ULTRATECH CEMENT ":"ULTRACEMCO.NS", +"WIPRO ":"WIPRO.NS" +} diff --git a/News_App/requirements.txt b/News_App/requirements.txt new file mode 100644 index 00000000000..fc3a139b2d4 --- /dev/null +++ b/News_App/requirements.txt @@ -0,0 +1,6 @@ +solara == 1.22.0 +Flask +gunicorn ==21.2.0 +simple-websocket +flask-sock +yfinance \ No newline at end of file diff --git a/PDF/requirements.txt b/PDF/requirements.txt index 58751ed40cb..0e6b71d8117 100644 --- a/PDF/requirements.txt +++ b/PDF/requirements.txt @@ -1,2 +1,2 @@ -Pillow==10.0.1 +Pillow==10.1.0 fpdf==1.7.2 \ No newline at end of file diff --git a/PingPong/Ball.py b/PingPong/Ball.py new file mode 100644 index 00000000000..ec1a4a6768f --- /dev/null +++ b/PingPong/Ball.py @@ -0,0 +1,58 @@ +import pygame +pygame.init() + +class Ball: + + def __init__(self, pos, vel, win, rad, minCoord, maxCoord): + + self.pos = pos + self.vel = vel + self.win = win + self.rad = rad + self.minCoord = minCoord + self.maxCoord = maxCoord + + + def drawBall(self): + + pygame.draw.circle(self.win, (255,)*3, self.pos, self.rad, 0) + + + def doHorizontalFlip(self): + + self.vel[0] *= -1 + + + def doVerticalFlip(self): + + self.vel[1] *= -1 + + + def borderCollisionCheck(self): + + if (self.pos[0] <= self.minCoord[0]) or (self.pos[0] >= self.maxCoord[0]): + + self.doHorizontalFlip() + + if (self.pos[1] <= self.minCoord[1]) or (self.pos[1] >= self.maxCoord[1]): + + self.doVerticalFlip() + + + def updatePos(self): + + self.pos = [self.pos[0]+self.vel[0], self.pos[1]+self.vel[1]] + + + def checkSlabCollision(self, slabPos): # slab pos = [xmin, ymin, xmax, ymax] + if ( + self.pos[0] + self.rad > slabPos[0] + and self.pos[0] - self.rad < slabPos[2] + and self.pos[1] + self.rad > slabPos[1] + and self.pos[1] - self.rad < slabPos[3] + ): + # Handle collision here (e.g., reverse ball's direction) + if self.pos[0] < slabPos[0] or self.pos[0] > slabPos[2]: + self.vel[0] *= -1 + if self.pos[1] < slabPos[1] or self.pos[1] > slabPos[3]: + self.vel[1] *= -1 \ No newline at end of file diff --git a/PingPong/Slab.py b/PingPong/Slab.py new file mode 100644 index 00000000000..c5fb5d70bec --- /dev/null +++ b/PingPong/Slab.py @@ -0,0 +1,31 @@ +import pygame +pygame.init() + +class Slab: + def __init__(self, win, size, pos, player, minPos, maxPos): + self.win = win + self.size = size + self.pos = pos + self.player = player #player = 1 or 2 + self.minPos = minPos + self.maxPos = maxPos + + + def draw(self): + pygame.draw.rect(self.win, (255, 255, 255), (self.pos[0], self.pos[1], self.size[0], self.size[1])) + + def getCoords(self): + return [self.pos[0], self.pos[1], self.pos[0] + self.size[0], self.pos[1] + self.size[1]] + + def updatePos(self): + keys = pygame.key.get_pressed() + if self.player == 1: + if keys[pygame.K_UP] and self.getCoords()[1]> self.minPos[1]: + self.pos[1] -= 0.3 + if keys[pygame.K_DOWN] and self.getCoords()[3]< self.maxPos[1]: + self.pos[1] += 0.3 + else: + if keys[pygame.K_w] and self.getCoords()[1]> self.minPos[1]: + self.pos[1] -= 0.3 + if keys[pygame.K_s] and self.getCoords()[3]< self.maxPos[1]: + self.pos[1] += 0.3 \ No newline at end of file diff --git a/PingPong/main.py b/PingPong/main.py new file mode 100644 index 00000000000..2892f8c9305 --- /dev/null +++ b/PingPong/main.py @@ -0,0 +1,40 @@ +from Ball import Ball +from Slab import Slab +import pygame + +WIDTH = 600 +HEIGHT = 600 +BLACK = (0,0,0) +WHITE = (255,)*3 +pygame.init() + +win = pygame.display.set_mode((WIDTH, HEIGHT )) + +print("Controls: W&S for player 1 and arrow up and down for player 2") + +ball = Ball([300,300 ], [0.3,0.1], win, 10, (0,0), (600,600)) +slab = Slab(win, [10,100], [500, 300], 1, (0, 0), (600, 600)) +slab2 = Slab(win, [10,100], [100, 300], 2, (0, 0), (600, 600)) +run = True +while run: + for event in pygame.event.get(): + if event.type == pygame.QUIT: + run = False + + keys = pygame.key.get_pressed() + win.fill(BLACK) + + ball.borderCollisionCheck() + ball.checkSlabCollision(slab.getCoords()) + ball.checkSlabCollision(slab2.getCoords()) + ball.updatePos() + ball.drawBall() + + slab.updatePos() + slab.draw() + + slab2.updatePos() + slab2.draw() + + pygame.display.update() +pygame.quit() \ No newline at end of file diff --git a/PongPong_Game/requirements.txt b/PongPong_Game/requirements.txt index 0facfc2ea8f..555f25f9c27 100644 --- a/PongPong_Game/requirements.txt +++ b/PongPong_Game/requirements.txt @@ -1 +1 @@ -pyglet==2.0.9 +pyglet==2.0.10 diff --git a/README.md b/README.md index 97687e178a8..4d5e575cae1 100644 --- a/README.md +++ b/README.md @@ -52,7 +52,7 @@ Feel free to explore the scripts and use them for your learning and automation n 38. [Images Downloader](https://git.io/JvnJh) - Download images from webpages on Unix-based systems. 39. [space_invader.py.py](https://github.com/meezan-mallick/space_invader_game) - Classical 2D space invader game to recall your childhood memories. 40. [Test Case Generator](https://github.com/Tanmay-901/test-case-generator/blob/master/test_case.py) - Generate different types of test cases with a clean and friendly UI, used in competitive programming and software testing. - +41. [Extract Thumbnail From Video](https://github.com/geekcomputers/Python/tree/ExtractThumbnailFromVideo) - Extract Thumbnail from video files
_**Note**: The content in this repository belongs to the respective authors and creators. I'm just providing a formatted README.md for better presentation._ diff --git a/Sorting Algorithims/heapsort_linkedlist.py b/Sorting Algorithims/heapsort_linkedlist.py new file mode 100644 index 00000000000..7e9584077e6 --- /dev/null +++ b/Sorting Algorithims/heapsort_linkedlist.py @@ -0,0 +1,82 @@ +class Node: + def __init__(self, data): + self.data = data + self.next = None + +class LinkedList: + def __init__(self): + self.head = None + + def push(self, data): + new_node = Node(data) + new_node.next = self.head + self.head = new_node + + def print_list(self): + current = self.head + while current: + print(current.data, end=" -> ") + current = current.next + print("None") + + def heapify(self, n, i): + largest = i + left = 2 * i + 1 + right = 2 * i + 2 + + current = self.head + for _ in range(i): + current = current.next + + if left < n and current.data < current.next.data: + largest = left + + if right < n and current.data < current.next.data: + largest = right + + if largest != i: + self.swap(i, largest) + self.heapify(n, largest) + + def swap(self, i, j): + current_i = self.head + current_j = self.head + + for _ in range(i): + current_i = current_i.next + + for _ in range(j): + current_j = current_j.next + + current_i.data, current_j.data = current_j.data, current_i.data + + def heap_sort(self): + n = 0 + current = self.head + while current: + n += 1 + current = current.next + + for i in range(n // 2 - 1, -1, -1): + self.heapify(n, i) + + for i in range(n - 1, 0, -1): + self.swap(0, i) + self.heapify(i, 0) + +# Example usage: +linked_list = LinkedList() +linked_list.push(12) +linked_list.push(11) +linked_list.push(13) +linked_list.push(5) +linked_list.push(6) +linked_list.push(7) + +print("Original Linked List:") +linked_list.print_list() + +linked_list.heap_sort() + +print("Sorted Linked List:") +linked_list.print_list() diff --git a/Sorting Algorithims/mergesort_linkedlist.py b/Sorting Algorithims/mergesort_linkedlist.py new file mode 100644 index 00000000000..429684b6c0c --- /dev/null +++ b/Sorting Algorithims/mergesort_linkedlist.py @@ -0,0 +1,77 @@ +from __future__ import annotations + +class Node: + def __init__(self, data: int) -> None: + self.data = data + self.next = None + +class LinkedList: + def __init__(self): + self.head = None + + def insert(self, new_data: int) -> None: + new_node = Node(new_data) + new_node.next = self.head + self.head = new_node + + def printLL(self) -> None: + temp = self.head + if temp == None: + return 'Linked List is empty' + while temp.next: + print(temp.data, '->', end='') + temp = temp.next + print(temp.data) + return + +# Merge two sorted linked lists +def merge(left, right): + if not left: + return right + if not right: + return left + + if left.data < right.data: + result = left + result.next = merge(left.next, right) + else: + result = right + result.next = merge(left, right.next) + + return result + +# Merge sort for linked list +def merge_sort(head): + if not head or not head.next: + return head + + # Find the middle of the list + slow = head + fast = head.next + while fast and fast.next: + slow = slow.next + fast = fast.next.next + + left = head + right = slow.next + slow.next = None + + left = merge_sort(left) + right = merge_sort(right) + + return merge(left, right) + +if __name__ == "__main__": + ll = LinkedList() + print("Enter the space-separated values of numbers to be inserted in the linked list prompted below:") + arr = list(map(int, input().split())) + for num in arr: + ll.insert(num) + + print("Linked list before sorting:") + ll.printLL() + + ll.head = merge_sort(ll.head) + + print('Linked list after sorting:') + ll.printLL() diff --git a/TIC_TAC_TOE/index.py b/TIC_TAC_TOE/index.py new file mode 100644 index 00000000000..7e494d0e700 --- /dev/null +++ b/TIC_TAC_TOE/index.py @@ -0,0 +1,46 @@ +def print_board(board): + for row in board: + print(" | ".join(row)) + print("-" * 9) + +def check_winner(board, player): + for i in range(3): + # Check rows and columns + if all(board[i][j] == player for j in range(3)) or all(board[j][i] == player for j in range(3)): + return True + # Check diagonals + if all(board[i][i] == player for i in range(3)) or all(board[i][2 - i] == player for i in range(3)): + return True + return False + +def is_full(board): + return all(cell != " " for row in board for cell in row) + +def main(): + board = [[" " for _ in range(3)] for _ in range(3)] + player = "X" + + while True: + print_board(board) + row = int(input(f"Player {player}, enter the row (0, 1, 2): ")) + col = int(input(f"Player {player}, enter the column (0, 1, 2): ")) + + if 0 <= row < 3 and 0 <= col < 3 and board[row][col] == " ": + board[row][col] = player + + if check_winner(board, player): + print_board(board) + print(f"Player {player} wins!") + break + + if is_full(board): + print_board(board) + print("It's a draw!") + break + + player = "O" if player == "X" else "X" + else: + print("Invalid move. Try again.") + +if __name__ == "__main__": + main() diff --git a/ThirdAI/Terms and Conditions/Readme.md b/ThirdAI/Terms and Conditions/Readme.md new file mode 100644 index 00000000000..da9378a8dcb --- /dev/null +++ b/ThirdAI/Terms and Conditions/Readme.md @@ -0,0 +1,81 @@ +# ThirdAIApp and NeuralDBClient + +This repository contains two components: `ThirdAIApp` and `NeuralDBClient`. `ThirdAIApp` is a graphical user interface (GUI) application for interacting with the ThirdAI neural database client. It allows you to perform training with PDF files and query the database. `NeuralDBClient` is a Python class that serves as a client for interacting with the ThirdAI neural database. It allows you to train the database with PDF files and perform queries to retrieve information. + +## ThirdAIApp + +### Features + +- Insert PDF files for training. +- Train the neural database client. +- Enter queries to retrieve information from the database. +- Display the output in a new window. + +### Installation + +To run `ThirdAIApp`, you need to have Python and Tkinter installed. You also need the `ThirdAI` library, which you can install using pip: + +```bash +pip install ThirdAI +``` + +### Usage + +1. Run the `ThirdAIApp.py` script. +2. The main window will appear. +3. Click the "Insert File!" button to select a PDF file for training. +4. Click the "Training" button to train the neural database client with the selected file. +5. Enter your query in the "Query" field. +6. Click the "Processing" button to process the query and display the output in a new window. +7. You can click the "Clear" button to clear the query and file selections. + +### Dependencies + +- Python 3.x +- Tkinter +- ThirdAI + +## NeuralDBClient + +### Features + +- Train the neural database with PDF files. +- Perform queries on the neural database. + +### Installation + +To use `NeuralDBClient`, you need to have the `thirdai` library installed, and you'll need an API key from ThirdAI. + +You can install the `thirdai` library using pip: + +```bash +pip install thirdai +``` + +### Usage + +1. Import the `NeuralDBClient` class from `neural_db_client.py`. +2. Create an instance of the `NeuralDBClient` class, providing your ThirdAI API key as an argument. + + ```python + from neural_db_client import NeuralDBClient + + client = NeuralDBClient(api_key="YOUR_API_KEY") + ``` + +3. Train the neural database with PDF files using the `train` method. Provide a list of file paths to the PDF files you want to use for training. + + ```python + client.train(file_paths=["file1.pdf", "file2.pdf"]) + ``` + +4. Perform queries on the neural database using the `query` method. Provide your query as a string, and the method will return the query results as a string. + + ```python + result = client.query(question="What is the capital of France?") + ``` + +### Dependencies + +- `thirdai` library + diff --git a/ThirdAI/Terms and Conditions/ThirdAI.py b/ThirdAI/Terms and Conditions/ThirdAI.py new file mode 100644 index 00000000000..67d3928ec4b --- /dev/null +++ b/ThirdAI/Terms and Conditions/ThirdAI.py @@ -0,0 +1,36 @@ +from thirdai import licensing, neural_db as ndb + + +class NeuralDBClient: + def __init__(self): + # Activating ThirdAI Key + licensing.activate("ADD-YOUR-THIRDAI-ACTIVATION-KEY") + + # Creating NeuralBD variable to access Neural Database + self.db = ndb.NeuralDB(user_id="my_user") + + def train(self, file_paths): + # Retrieving path of file + insertable_docs = [] + pdf_files = file_paths + + # Appending PDF file to the Database stack + pdf_doc = ndb.PDF(pdf_files) + insertable_docs.append(pdf_doc) + + # Inserting/Uploading PDF file to Neural database for training + self.db.insert(insertable_docs, train=True) + + def query(self, question): + # Searching of required query in neural database + search_results = self.db.search( + query=question, + top_k=2, + on_error=lambda error_msg: print(f"Error! {error_msg}")) + + output = "" + for result in search_results: + output += result.text + "\n\n" + + return output + diff --git a/ThirdAI/Terms and Conditions/TkinterUI.py b/ThirdAI/Terms and Conditions/TkinterUI.py new file mode 100644 index 00000000000..47317636a23 --- /dev/null +++ b/ThirdAI/Terms and Conditions/TkinterUI.py @@ -0,0 +1,144 @@ +import tkinter as tk +from tkinter.font import Font +from tkinter import messagebox +from tkinter import filedialog +from ThirdAI import NeuralDBClient as Ndb + + +class ThirdAIApp: + """ + A GUI application for using the ThirdAI neural database client to train and query data. + """ + def __init__(self, root): + """ + Initialize the user interface window. + + Args: + root (tk.Tk): The main Tkinter window. + """ + # Initialize the main window + self.root = root + self.root.geometry("600x500") + self.root.title('ThirdAI - T&C') + + # Initialize variables + self.path = [] + self.client = Ndb() + + # GUI elements + + # Labels and buttons + self.menu = tk.Label(self.root, text="Terms & Conditions", font=self.custom_font(30), fg='black', + highlightthickness=2, highlightbackground="red") + self.menu.place(x=125, y=10) + + self.insert_button = tk.Button(self.root, text="Insert File!", font=self.custom_font(15), fg='black', bg="grey", + width=10, command=self.file_input) + self.insert_button.place(x=245, y=100) + + self.text_box = tk.Text(self.root, wrap=tk.WORD, width=30, height=1) + self.text_box.place(x=165, y=150) + + self.training_button = tk.Button(self.root, text="Training", font=self.custom_font(15), fg='black', bg="grey", + width=10, command=self.training) + self.training_button.place(x=245, y=195) + + self.query_label = tk.Label(self.root, text="Query", font=self.custom_font(20), fg='black') + self.query_label.place(x=255, y=255) + + self.query_entry = tk.Entry(self.root, font=self.custom_font(20), width=30) + self.query_entry.place(x=70, y=300) + + self.processing_button = tk.Button(self.root, text="Processing", font=self.custom_font(15), fg='black', + bg="grey", width=10, command=self.processing) + self.processing_button.place(x=245, y=355) + + self.clear_button = tk.Button(self.root, text="Clear", font=15, fg='black', bg="grey", width=10, + command=self.clear_all) + self.clear_button.place(x=245, y=405) + + @staticmethod + def custom_font(size): + """ + Create a custom font with the specified size. + + Args: + size (int): The font size. + + Returns: + Font: The custom Font object. + """ + return Font(size=size) + + def file_input(self): + """ + Open a file dialog to select a PDF file and display its name in the text box. + """ + file_type = dict(defaultextension=".pdf", filetypes=[("pdf file", "*.pdf")]) + file_path = filedialog.askopenfilename(**file_type) + + if file_path: + self.path.append(file_path) + file_name = file_path.split("/")[-1] + self.text_box.delete(1.0, tk.END) + self.text_box.insert(tk.INSERT, file_name) + + def clear_all(self): + """ + Clear the query entry, text box, and reset the path. + """ + self.query_entry.delete(0, tk.END) + self.text_box.delete(1.0, tk.END) + self.path.clear() + + def training(self): + """ + Train the neural database client with the selected PDF file. + """ + if not self.path: + messagebox.showwarning("No File Selected", "Please select a PDF file before training.") + return + + self.client.train(self.path[0]) + + messagebox.showinfo("Training Complete", "Training is done!") + + def processing(self): + """ + Process a user query and display the output in a new window. + """ + question = self.query_entry.get() + + # When there is no query submitted by the user + if not question: + messagebox.showwarning("No Query", "Please enter a query.") + return + + output = self.client.query(question) + self.display_output(output) + + def display_output(self, output_data): + """ + Display the output data in a new window. + + Args: + output_data (str): The output text to be displayed. + """ + output_window = tk.Toplevel(self.root) + output_window.title("Output Data") + output_window.geometry("500x500") + + output_text = tk.Text(output_window, wrap=tk.WORD, width=50, height=50) + output_text.pack(padx=10, pady=10) + output_text.insert(tk.END, output_data) + + +if __name__ == "__main__": + """ + Initializing the main application window + """ + + # Calling the main application window + win = tk.Tk() + app = ThirdAIApp(win) + win.mainloop() diff --git a/ThirdAI/Terms and Conditions/XYZ product.pdf b/ThirdAI/Terms and Conditions/XYZ product.pdf new file mode 100644 index 00000000000..8a7484070df Binary files /dev/null and b/ThirdAI/Terms and Conditions/XYZ product.pdf differ diff --git a/TowerOfHanoi.py b/TowerOfHanoi.py new file mode 100644 index 00000000000..af89032fce0 --- /dev/null +++ b/TowerOfHanoi.py @@ -0,0 +1,14 @@ +# Recursive Python function to solve the tower of hanoi -- + +def TowerOfHanoi(n , source, destination, auxiliary): + if n==1: + print ("Move disk 1 from source",source,"to destination",destination) + return + TowerOfHanoi(n-1, source, auxiliary, destination) + print ("Move disk",n,"from source",source,"to destination",destination) + TowerOfHanoi(n-1, auxiliary, destination, source) + +# Driver code +n = 4 +TowerOfHanoi(n,'A','B','C') +# A, C, B are the name of rods diff --git a/Wikipdedia/flask_rendering.py b/Wikipdedia/flask_rendering.py new file mode 100644 index 00000000000..05c6d7494bf --- /dev/null +++ b/Wikipdedia/flask_rendering.py @@ -0,0 +1,27 @@ +from flask import Flask, render_template, request +import practice_beautifulsoap as data + +app = Flask(__name__, template_folder='template') + + +@app.route('/', methods=["GET", "POST"]) +def index(): + languages = data.lang() + return render_template('index.html', languages=languages) + + +@app.route("/display", methods=["POST"]) +def output(): + if request.method == "POST": + entered_topic = request.form.get("topic") + selected_language = request.form.get("language") + + soup_data = data.data(entered_topic, selected_language) + soup_image = data.get_image_urls(entered_topic) + + return render_template('output.html', heading=entered_topic.upper(), data=soup_data, + url=soup_image, language=selected_language) + + +if __name__ == "__main__": + app.run(debug=True) diff --git a/Wikipdedia/main.py b/Wikipdedia/main.py new file mode 100644 index 00000000000..5596b44786f --- /dev/null +++ b/Wikipdedia/main.py @@ -0,0 +1,16 @@ +# This is a sample Python script. + +# Press Shift+F10 to execute it or replace it with your code. +# Press Double Shift to search everywhere for classes, files, tool windows, actions, and settings. + + +def print_hi(name): + # Use a breakpoint in the code line below to debug your script. + print(f'Hi, {name}') # Press Ctrl+F8 to toggle the breakpoint. + + +# Press the green button in the gutter to run the script. +if __name__ == '__main__': + print_hi('PyCharm') + +# See PyCharm help at https://www.jetbrains.com/help/pycharm/ diff --git a/Wikipdedia/practice_beautifulsoap.py b/Wikipdedia/practice_beautifulsoap.py new file mode 100644 index 00000000000..00beb87fc44 --- /dev/null +++ b/Wikipdedia/practice_beautifulsoap.py @@ -0,0 +1,69 @@ +from bs4 import BeautifulSoup +import requests + +language_symbols = {} + + +def lang(): + try: + response = requests.get("https://www.wikipedia.org/") + response.raise_for_status() + soup = BeautifulSoup(response.content, 'html.parser') + + for option in soup.find_all('option'): + language = option.text + symbol = option['lang'] + language_symbols[language] = symbol + + return list(language_symbols.keys()) + + except requests.exceptions.RequestException as e: + print("Error fetching language data:", e) + return [] + + +def data(selected_topic, selected_language): + symbol = language_symbols.get(selected_language) + + try: + url = f"https://{symbol}.wikipedia.org/wiki/{selected_topic}" + data_response = requests.get(url) + data_response.raise_for_status() + data_soup = BeautifulSoup(data_response.content, 'html.parser') + + main_content = data_soup.find('div', {'id': 'mw-content-text'}) + filtered_content = "" + + if main_content: + for element in main_content.descendants: + if element.name in ['h1', 'h2', 'h3', 'h4', 'h5', 'h6']: + filtered_content += "\n" + element.get_text(strip=True).upper() + "\n" + + elif element.name == 'p': + filtered_content += element.get_text(strip=True) + "\n" + + return filtered_content + + except requests.exceptions.RequestException as e: + print("Error fetching Wikipedia content:", e) + return "Error fetching data." + + +def get_image_urls(query): + try: + search_url = f"https://www.google.com/search?q={query}&tbm=isch" + image_response = requests.get(search_url) + image_response.raise_for_status() + image_soup = BeautifulSoup(image_response.content, 'html.parser') + + image_urls = [] + for img in image_soup.find_all('img'): + image_url = img.get('src') + if image_url and image_url.startswith("http"): + image_urls.append(image_url) + + return image_urls[0] + + except requests.exceptions.RequestException as e: + print("Error fetching image URLs:", e) + return None diff --git a/Wikipdedia/static/js/output.js b/Wikipdedia/static/js/output.js new file mode 100644 index 00000000000..5c360de488e --- /dev/null +++ b/Wikipdedia/static/js/output.js @@ -0,0 +1,9 @@ +function validateForm() { + var language = document.getElementById("language").value; + + if (language === "Select") { + alert("Please select a language."); + return false; + } +} + diff --git a/Wikipdedia/template/index.html b/Wikipdedia/template/index.html new file mode 100644 index 00000000000..7a2bdb712ab --- /dev/null +++ b/Wikipdedia/template/index.html @@ -0,0 +1,42 @@ + + + + + + + Input Web Page + + + + + +
+ +

Wikipedia

+
+ +
+
+ + +
+
+ + +
+ + +
+ + + + + + + + diff --git a/Wikipdedia/template/output.html b/Wikipdedia/template/output.html new file mode 100644 index 00000000000..ee2d3b0b240 --- /dev/null +++ b/Wikipdedia/template/output.html @@ -0,0 +1,35 @@ + + + + + + + Output Web Page + + + + + +
+ +

{{ heading }}

+
in {{ language }} language
+
+
+
+
{{ data }}
+
+
+ + + + + + + diff --git a/async_downloader/requirements.txt b/async_downloader/requirements.txt index 8af244589bf..45f1bccb697 100644 --- a/async_downloader/requirements.txt +++ b/async_downloader/requirements.txt @@ -1 +1 @@ -aiohttp==3.8.5 +aiohttp==3.8.6 diff --git a/calculator.py b/calculator.py index b12986aa7e6..b0ef5dca8dd 100644 --- a/calculator.py +++ b/calculator.py @@ -37,6 +37,9 @@ def calc(term): purpose: This function is the actual calculator and the heart of the application """ + # This part is for reading and converting function expressions. + term = term.lower() + # This part is for reading and converting arithmetic terms. term = term.replace(" ", "") term = term.replace("^", "**") @@ -61,9 +64,6 @@ def calc(term): "e", ] - # This part is for reading and converting function expressions. - term = term.lower() - for func in functions: if func in term: withmath = "math." + func diff --git a/login.py b/login.py index 791c1d94247..8095f4f4e54 100644 --- a/login.py +++ b/login.py @@ -20,7 +20,7 @@ def logo(): print("\033[1;36;49m") -# This is Login Funtion +# This is Login Function def login(): # for clear the screen os.system("clear") diff --git a/numberguessinggame/index.py b/numberguessinggame/index.py new file mode 100644 index 00000000000..3116af47dce --- /dev/null +++ b/numberguessinggame/index.py @@ -0,0 +1,28 @@ +import random + +def number_guessing_game(): + + secret_number = random.randint(1, 100) + attempts = 0 + + print("Welcome to the Number Guessing Game!") + print("I'm thinking of a number between 1 and 100.") + + while True: + try: + guess = int(input("Your guess: ")) + attempts += 1 + + if guess < secret_number: + print("Too low! Try again.") + elif guess > secret_number: + print("Too high! Try again.") + else: + print(f"Congratulations! You guessed the number {secret_number} in {attempts} attempts!") + break + + except ValueError: + print("Please enter a valid number.") + +if __name__ == "__main__": + number_guessing_game() diff --git a/quiz_game.py b/quiz_game.py new file mode 100644 index 00000000000..c1ffd6696b0 --- /dev/null +++ b/quiz_game.py @@ -0,0 +1,32 @@ +print('Welcome to AskPython Quiz') +answer=input('Are you ready to play the Quiz ? (yes/no) :') +score=0 +total_questions=3 + +if answer.lower()=='yes': + answer=input('Question 1: What is your Favourite programming language?') + if answer.lower()=='python': + score += 1 + print('correct') + else: + print('Wrong Answer :(') + + + answer=input('Question 2: Do you follow any author on AskPython? ') + if answer.lower()=='yes': + score += 1 + print('correct') + else: + print('Wrong Answer :(') + + answer=input('Question 3: What is the name of your favourite website for learning Python?') + if answer.lower()=='askpython': + score += 1 + print('correct') + else: + print('Wrong Answer :(') + +print('Thankyou for Playing this small quiz game, you attempted',score,"questions correctly!") +mark=(score/total_questions)*100 +print('Marks obtained:',mark) +print('BYE!') \ No newline at end of file diff --git a/text_to_pig_latin.py b/text_to_pig_latin.py new file mode 100644 index 00000000000..850b13913e8 --- /dev/null +++ b/text_to_pig_latin.py @@ -0,0 +1,38 @@ +""" +This program converts English text to Pig-Latin. In Pig-Latin, we take the first letter of each word, +move it to the end, and add 'ay'. If the first letter is a vowel, we simply add 'hay' to the end. +The program preserves capitalization and title case. + +For example: +- "Hello" becomes "Ellohay" +- "Image" becomes "Imagehay" +- "My name is John Smith" becomes "Ymay amenay ishay Ohnjay Mithsmay" +""" + + +def pig_latin_word(word): + vowels = "AEIOUaeiou" + + if word[0] in vowels: + return word + "hay" + else: + return word[1:] + word[0] + "ay" + +def pig_latin_sentence(text): + words = text.split() + pig_latin_words = [] + + for word in words: + # Preserve capitalization + if word.isupper(): + pig_latin_words.append(pig_latin_word(word).upper()) + elif word.istitle(): + pig_latin_words.append(pig_latin_word(word).title()) + else: + pig_latin_words.append(pig_latin_word(word)) + + return ' '.join(pig_latin_words) + +user_input = input("Enter some English text: ") +pig_latin_text = pig_latin_sentence(user_input) +print("\nPig-Latin: " + pig_latin_text) diff --git a/url_shortner.py b/url_shortner.py new file mode 100644 index 00000000000..0631a4bdb60 --- /dev/null +++ b/url_shortner.py @@ -0,0 +1,14 @@ +# Importing the required libraries. +import pyshorteners + +# Taking input from the user. +url = input("Enter URL: ") + +# Creating an instance of the pyshorteners library. +shortener = pyshorteners.Shortener() + +# Shortening the URL using TinyURL. +shortened_URL = shortener.tinyurl.short(url) + +# Displaying the shortened URL. +print(f"Shortened URL: {shortened_URL}")