From 110b48459ba618a443afda4b571c29bffce53abf Mon Sep 17 00:00:00 2001 From: Vaibhav Maheshwari Date: Sun, 3 Nov 2024 04:25:22 +0530 Subject: [PATCH 01/12] the night is young --- app/__init__.py | 12 -- app/core/views/admin_views.py | 109 -------------- app/core/views/auth_views.py | 100 ------------- app/core/views/history_views.py | 59 -------- app/core/views/user_v2_views.py | 101 ++++--------- app/core/views/user_views.py | 213 --------------------------- docker-compose.yml | 8 +- myenv/bin/Activate.ps1 | 247 ++++++++++++++++++++++++++++++++ myenv/bin/activate | 70 +++++++++ myenv/bin/activate.csh | 27 ++++ myenv/bin/activate.fish | 69 +++++++++ myenv/bin/pip | 8 ++ myenv/bin/pip3 | 8 ++ myenv/bin/pip3.12 | 8 ++ myenv/bin/python | 1 + myenv/bin/python3 | 1 + myenv/bin/python3.12 | 1 + myenv/pyvenv.cfg | 5 + 18 files changed, 480 insertions(+), 567 deletions(-) delete mode 100644 app/core/views/admin_views.py delete mode 100644 app/core/views/auth_views.py delete mode 100644 app/core/views/history_views.py delete mode 100644 app/core/views/user_views.py create mode 100644 myenv/bin/Activate.ps1 create mode 100644 myenv/bin/activate create mode 100644 myenv/bin/activate.csh create mode 100644 myenv/bin/activate.fish create mode 100755 myenv/bin/pip create mode 100755 myenv/bin/pip3 create mode 100755 myenv/bin/pip3.12 create mode 120000 myenv/bin/python create mode 120000 myenv/bin/python3 create mode 120000 myenv/bin/python3.12 create mode 100644 myenv/pyvenv.cfg diff --git a/app/__init__.py b/app/__init__.py index 4cb6530..5385fa6 100755 --- a/app/__init__.py +++ b/app/__init__.py @@ -26,21 +26,9 @@ def register_blueprints(app): """ # Import blueprints - from .core.views.user_views import core as core_user from .core.views.user_v2_views import core as core_user_v2 - from .core.views.auth_views import core as core_auth - from .core.views.history_views import core as core_history - from .core.views.admin_views import core as admin_views # Register blueprints with proper versioned URL prefixes - app.register_blueprint(core_user, name="user_api", url_prefix="/api/v1/core/user") app.register_blueprint( core_user_v2, name="user_api_v2", url_prefix="/api/v2/core/user" ) - app.register_blueprint(core_auth, name="auth_api", url_prefix="/api/v1/core/auth") - app.register_blueprint( - core_history, name="history_api", url_prefix="/api/v1/core/history" - ) - app.register_blueprint( - admin_views, name="admin_api", url_prefix="/api/v1/core/admin" - ) diff --git a/app/core/views/admin_views.py b/app/core/views/admin_views.py deleted file mode 100644 index 234941b..0000000 --- a/app/core/views/admin_views.py +++ /dev/null @@ -1,109 +0,0 @@ -from flask import Blueprint, jsonify, request -from ..models.user import get_all_users_with_count -from celery import current_app as current_celery_app -from app.celery.tasks import * -from collections import defaultdict -import ast - -core = Blueprint("core", __name__) - - - - -def revoke_user_tasks(slug, scheduled_tasks): - """Revoke existing tasks for a given user slug.""" - revoked_count = 0 - for worker, tasks in scheduled_tasks.items(): - for task in tasks: - if ( - task["request"]["name"] == "app.celery.tasks.create_pending_card" - and task["request"]["kwargs"].get("slug") == slug - ): - try: - current_celery_app.control.revoke( - task["request"]["id"], terminate=True - ) - revoked_count += 1 - except Exception: # Catch any exception for a revoked task - pass # Task was already completed or doesn't exist - return revoked_count - - - - - - -@core.route("/tasks/active_users", methods=["POST"]) -def list_inactive_users(): - """List users with published card counts.""" - users = get_all_users_with_count() - active_users_with_no_publishing_cards = [] - for user in users: - slug = user["slug"] - count = 0 - active_users_with_no_publishing_cards.append( - {"slug": user["slug"], "count": count} - ) - return jsonify(active_users_with_no_publishing_cards), 200 - - -@core.route("/tasks/update_milestone", methods=["POST"]) -def update_milestone(): - """Update a user's milestone and Kleo points.""" - data = request.get_json() - - # Extract input parameters - address = data.get("address") - mileStoneKey = data.get("mileStoneKey") - kleoPoints = data.get("kleoPoints", 0) # Default to 0 if not provided - newValue = data.get("newValue") - - # Input validation - if not address or not mileStoneKey or newValue is None: - return ( - jsonify( - { - "error": "Invalid input. Address, mileStoneKey, and newValue are required." - } - ), - 400, - ) - - # Find the user by address - user = find_by_address(address) - if not user: - return jsonify({"error": f"User with address {address} not found."}), 404 - - # Check if the milestone key exists - milestones = user.get("milestones", {}) - if mileStoneKey not in milestones: - return ( - jsonify({"error": f"Milestone key {mileStoneKey} not found in user data."}), - 400, - ) - - # Update the milestone value - milestones[mileStoneKey] = newValue - - # Add kleoPoints to the user's current kleo_points - current_kleo_points = user.get("kleo_points", 0) - updated_kleo_points = current_kleo_points + kleoPoints - - # Update the user in the database - updated_user = update_user_milestones_data_by_address( - address, milestones, updated_kleo_points - ) - - if updated_user: - return ( - jsonify( - { - "message": "Milestone and Kleo points updated successfully", - "milestones": updated_user.get("milestones"), - "kleo_points": updated_user.get("kleo_points"), - } - ), - 200, - ) - else: - return jsonify({"error": "Failed to update user data."}), 500 diff --git a/app/core/views/auth_views.py b/app/core/views/auth_views.py deleted file mode 100644 index adf81b5..0000000 --- a/app/core/views/auth_views.py +++ /dev/null @@ -1,100 +0,0 @@ -from flask import Blueprint, current_app, request, jsonify -import jwt -import os -from werkzeug.local import LocalProxy -from functools import wraps -from web3 import Web3 - -from app.core.models.user import find_by_address_slug - -core = Blueprint("core", __name__) -w3 = Web3() -logger = LocalProxy(lambda: current_app.logger) - - -# Decorator to require token authentication for endpoints -def token_required(f): - @wraps(f) - def decorated(*args, **kwargs): - token = None - - # Get the token from the Authorization header - if "Authorization" in request.headers: - try: - token = request.headers["Authorization"].split(" ")[1] - except IndexError: - return jsonify({"message": "Bearer token malformed."}), 401 - - if not token: - return jsonify({"message": "Token is missing."}), 401 - - try: - # Decode the token - data = jwt.decode( - token, os.environ.get("SECRET", "default_secret"), algorithms=["HS256"] - ) - except jwt.ExpiredSignatureError: - return jsonify({"message": "Token is expired."}), 401 - except jwt.InvalidTokenError: - return jsonify({"message": "Token is invalid."}), 401 - except: - return ( - jsonify( - { - "message": "Something went wrong while authenticating. Please try again." - } - ), - 401, - ) - - # Add the user data to the kwargs - kwargs["user_data"] = data - return f(*args, **kwargs) - - return decorated - - -# Test API endpoint -@core.route("/test_api", methods=["GET"]) -@token_required -def test_api(**kwargs): - public_address = kwargs.get("user_data")["payload"]["publicAddress"] - return jsonify( - {"message": f"Test API accessed by user with public address: {public_address}"} - ) - - -# Endpoint to create JWT authentication for a user -@core.route("/v2/create_jwt_authentication", methods=["POST"]) -def create_jwt_for_slug(): - data = request.json - slug = data.get("slug") - public_address = data.get("publicAddress") - - # Find user by address slug - address = find_by_address_slug(slug) - - if not address: - return ( - jsonify( - error=f"User with publicAddress {public_address} is not found in database" - ), - 401, - ) - - if address != public_address: - return jsonify(error="Signature verification failed"), 401 - - try: - SECRET = os.environ.get("SECRET", "default_secret") - ALGORITHM = os.environ.get("ALGORITHM", "HS256") - - # Create JWT token - access_token = jwt.encode( - {"payload": {"slug": slug, "publicAddress": public_address}}, - SECRET, - algorithm=ALGORITHM, - ) - return jsonify(accessToken=access_token) - except Exception as e: - return jsonify(error=str(e)), 500 diff --git a/app/core/views/history_views.py b/app/core/views/history_views.py deleted file mode 100644 index cd0bdcb..0000000 --- a/app/core/views/history_views.py +++ /dev/null @@ -1,59 +0,0 @@ -from flask import Blueprint, current_app, request, jsonify -from ..controllers.history import * -from werkzeug.local import LocalProxy -from ...celery.tasks import * -from math import ceil -from celery import chord, group -from .auth_views import token_required - -core = Blueprint("core", __name__) -logger = LocalProxy(lambda: current_app.logger) - - -@core.before_request -def before_request_func(): - """Set logger name for the current request context.""" - current_app.logger.name = "core" - - -@core.route("/upload", methods=["POST"]) -@token_required -def upload(**kwargs): - """ - Endpoint to upload history data and categorize it. - Requires token authentication. - """ - data = request.get_json() - history = data.get("history") - slug = data.get("slug") - - # Validate required parameters - if not all([slug, history]): - return jsonify({"error": "Missing required parameters"}), 400 - - # Check if user exists - result = find_by_address_slug_first_time(slug) - if result is None: - return jsonify({"error": "User is not found"}), 401 - - address, signup = result - - # Validate user authenticity - address_from_token = kwargs.get("user_data")["payload"]["publicAddress"] - if not check_user_authenticity(address, address_from_token): - return jsonify({"error": "User is not authorized"}), 401 - - # Split history into chunks - chunks = [history[i : i + 50] for i in range(0, len(history), 50)] - categorize_tasks = [ - categorize_history.s({"chunk": chunk, "slug": slug}) for chunk in chunks - ] - - # Execute tasks based on signup status - if signup: - callback = create_pending_card.s(slug) - chord(categorize_tasks)(callback) - else: - group(categorize_tasks).apply_async() - - return jsonify({"message": "History Upload and Categorization is queued!"}), 202 diff --git a/app/core/views/user_v2_views.py b/app/core/views/user_v2_views.py index 73716f9..41c6c91 100644 --- a/app/core/views/user_v2_views.py +++ b/app/core/views/user_v2_views.py @@ -13,17 +13,11 @@ core = Blueprint("core", __name__) - - @core.route("/get-user-graph/", methods=["GET"]) def get_user_graph(userAddress): try: if not userAddress: return jsonify({"error": "Address is required"}), 400 - activity_json = get_activity_json(userAddress) - top_activities = get_top_activities(activity_json) - # if not top_activities: - # return jsonify({"error": "No activity data found"}), 404 cache_key = f"user_graph:{userAddress}" cached_data = redis_client.get(cache_key) @@ -43,17 +37,16 @@ def get_user_graph(userAddress): return jsonify({"error": str(e)}), 500 - @core.route("/save-history", methods=["POST"]) def save_history(): data = request.get_json() - print(data) + # print(data) user_address = str(data.get("address")).lower() signup = data.get("signup") history = data.get("history") return_abi_contract = False user = find_by_address(user_address) - + try: if signup: referee_address = find_referral_in_history(history) @@ -64,29 +57,29 @@ def save_history(): else: if get_history_count(user_address) > 50: return_abi_contract = True - + for item in history: if "content" in item: user = find_by_address(user_address) contextual_activity_classification.delay(item, user_address) - + if return_abi_contract: user = find_by_address(user_address) previous_hash = user.get("previous_hash", "first_hash") chain_data_list = [ - { - "name": "polygon", - "rpc": POLYGON_RPC, - "contractData": { - "address": "0xD133A1aE09EAA45c51Daa898031c0037485347B0", - "abi": ABI, - "functionName": "safeMint", - "functionParams": [ - user_address, - previous_hash, - ], - }, - } + { + "name": "polygon", + "rpc": POLYGON_RPC, + "contractData": { + "address": "0xD133A1aE09EAA45c51Daa898031c0037485347B0", + "abi": ABI, + "functionName": "safeMint", + "functionParams": [ + user_address, + previous_hash, + ], + }, + } ] response = { @@ -95,51 +88,13 @@ def save_history(): } return jsonify({"data": response}), 200 - return jsonify({ - "status": "success", - "message": "History saved successfully" - }), 200 + return ( + jsonify({"status": "success", "message": "History saved successfully"}), + 200, + ) except Exception as e: - return jsonify({ - "status": "error", - "message": str(e) - }), 500 - - - -# @core.route("/save-history", methods=["POST"]) -# def save_history(): -# data = request.get_json() -# user_address = data.get("address") -# print(user_address) -# print(data.get("signup")) -# history = data.get("history") -# for item in history: -# if "content" not in item: -# task = contextual_activity_classification.delay(item, user_address) -# else: -# user = find_by_address(user_address) -# contractData = { -# "address": "0xD133A1aE09EAA45c51Daa898031c0037485347B0", -# "abi": ABI, -# "functionName": "safeMint", -# "functionParams": [ -# user_address, -# "https://www.youtube.com/watch?v=bUrCR4jQQg8", -# ], -# } - -# # Construct the response -# response = { -# "contractData": contractData, -# "password": user.get("slug"), -# "rpc": POLYGON_RPC, -# } -# print(response) -# # THIS IS JSON OF ITEM -# # {'id': '16132', 'url': 'https://www.google.com/search?q=imgflip&oq=imgflip&gs_lcrp=EgZjaHJvbWUyDAgAEEUYORixAxiABDIHCAEQABiABDIHCAIQABiABDIHCAMQABiABDIHCAQQABiABDIHCAUQABiABDIHCAYQABiABDIHCAcQABiABDIHCAgQABiABNIBCDE1MDRqMGo3qAIAsAIA&sourceid=chrome&ie=UTF-8', 'title': 'imgflip - Google Search', 'lastVisitTime': 1727571259983.67, 'visitCount': 2, 'typedCount': 0} -# return jsonify({"data": response}), 200 -# return jsonify({"process": True}), 200 + return jsonify({"status": "error", "message": str(e)}), 500 + @core.route("/create-user", methods=["POST"]) @@ -151,11 +106,11 @@ def create_user(): and generate a 5-digit random code. """ data = request.get_json() - print("create user hit") + # print("create user hit") wallet_address = data.get("address") user = find_by_address(wallet_address) - print(user) + # print(user) if user: user["token"] = get_jwt_token(wallet_address, wallet_address) return jsonify(user), 200 @@ -166,13 +121,13 @@ def create_user(): # Create a new user with the random code user = User(address=wallet_address, slug=random_code) response = user.save(signup=True) - + # Prepare the response object user_data = { "password": response["slug"], "token": get_jwt_token(wallet_address, wallet_address), } - print(user_data) + # print(user_data) return jsonify(user_data), 200 # 201 Created @@ -267,4 +222,4 @@ def get_user_referrals(userAddress): referrals = fetch_users_referrals(userAddress) return referrals except Exception as e: - return jsonify({"error": "An error occurred while fetching user's referrals"}) + return jsonify({"error": "An error occurred while fetching user's referrals"}) \ No newline at end of file diff --git a/app/core/views/user_views.py b/app/core/views/user_views.py deleted file mode 100644 index c4bc396..0000000 --- a/app/core/views/user_views.py +++ /dev/null @@ -1,213 +0,0 @@ -from flask import Blueprint, current_app, request, jsonify -from app.core.modules.auth import get_jwt_token -from werkzeug.local import LocalProxy -from .auth_views import * -from ..models.user import * -import os -from google.oauth2 import id_token -from google.auth.transport import requests as google_requests -from app.core.controllers.history import * - -core = Blueprint("core", __name__) -logger = LocalProxy(lambda: current_app.logger) - - -@core.route("/get-user/", methods=["GET"]) -def get_mongo_user(slug, **kwargs): - """Retrieve user information by slug.""" - if not all([slug]): - return jsonify({"error": "Missing required parameters"}), 400 - - response = find_by_slug(slug) - return jsonify(response), 200 - - -@core.route("/create-user", methods=["POST"]) -def create_user(): - """Create a new user or return existing user information.""" - data = request.get_json() - signup = data.get("signup", False) - stage = data.get("stage") - slug = data.get("slug", "") - code = data.get("code") - - # Verify user info from the token - user_info_from_google = id_token.verify_oauth2_token( - code, google_requests.Request(), os.environ.get("GOOGLE_CLIENT_ID") - ) - - if not all([code, stage is not None, user_info_from_google]): - return jsonify({"error": "Missing required parameters"}), 400 - - if signup: - user = find_by_address(user_info_from_google["email"]) - if user: - user["token"] = get_jwt_token(user["slug"], user_info_from_google["email"]) - return jsonify(user), 200 - else: - # Create a new user - user = User( - user_info_from_google["email"], - slug, - stage, - user_info_from_google["name"], - user_info_from_google["picture"], - ) - response = user.save(signup) - if slug == "": - slug = response["slug"] - response["email"] = user_info_from_google["email"] - response["token"] = get_jwt_token(slug, user_info_from_google["email"]) - return jsonify(response), 201 # 201 Created - else: - # Case 3: User does not exist and signup is false - user = find_by_address(user_info_from_google["email"]) - if user is None: - return jsonify({"message": "Please sign up"}), 200 - else: - user["token"] = get_jwt_token(user["slug"], user_info_from_google["email"]) - return jsonify(user), 200 - - -@core.route("/update-user/", methods=["PUT"]) -@token_required -def update_user(slug, **kwargs): - """Update user information.""" - data = request.get_json() - name = data.get("name") - verified = data.get("verified") - about = data.get("about") - pfp = data.get("pfp") - content_tags = data.get("content_tags") - identity_tags = data.get("identity_tags") - badges = data.get("badges") - profile_metadata = data.get("profile_metadata") - - if not all( - [ - address, - name, - slug, - about, - pfp, - content_tags, - identity_tags, - badges, - profile_metadata, - ] - ): - return jsonify({"error": "Missing required parameters"}), 400 - - address = find_by_address_slug(slug) - if not address: - return jsonify({"error": "User is not found"}), 401 - - address_from_token = kwargs.get("user_data")["payload"]["publicAddress"] - if not check_user_authenticity(address, address_from_token): - return jsonify({"error": "User is not authorized"}), 401 - - response = update_by_slug( - address, - slug, - name, - verified, - about, - pfp, - content_tags, - identity_tags, - badges, - profile_metadata, - ) - return jsonify(response), 200 - - -@core.route("/update-settings/", methods=["PUT"]) -@token_required -def update_user_settings(slug, **kwargs): - """Update user settings.""" - data = request.get_json() - settings = data.get("settings") - stage = data.get("stage") - - if not all([slug, settings, stage]): - return jsonify({"error": "Missing required parameters"}), 400 - - address = find_by_address_slug(slug) - if not address: - return jsonify({"error": "User is not found"}), 401 - - address_from_token = kwargs.get("user_data")["payload"]["publicAddress"] - if not check_user_authenticity(address, address_from_token): - return jsonify({"error": "User is not authorized"}), 401 - - response = update_settings_by_slug(slug, settings, stage, "") - return jsonify(response), 200 - - -@core.route("/check_slug", methods=["GET"]) -def check_slug(): - """Check if a slug is already in use.""" - slug = request.args.get("slug") - if not slug: - return jsonify({"error": "Slug parameter is missing."}), 400 - - slugs = fetch_user_slug() - return jsonify({"result": slug not in slugs}), 200 - - -@core.route("/update-mint-count/", methods=["PUT"]) -def update_mint_count(slug): - """Update the mint count for a user.""" - if not slug: - return jsonify({"error": "Slug parameter is missing."}), 400 - - try: - update_minting_count(slug) - return jsonify({"message": f"Mint count updated for user {slug}"}), 200 - except Exception as e: - print(f"Error while updating mint count: {str(e)}") - return jsonify({"error": "Error while updating mint count"}), 500 - - -@core.route("/update-about/", methods=["PUT"]) -@token_required -def update_about_for_user(slug, **kwargs): - try: - data = request.get_json() - about = data.get("about") - - if not all([slug, about]): - return jsonify({"error": f"Missing required parameters"}), 400 - - address = find_by_address_slug(slug) - if not address: - return jsonify({"error": "User is not found"}), 401 - address_from_token = kwargs.get("user_data")["payload"]["publicAddress"] - if not check_user_authenticity(address, address_from_token): - return jsonify({"error": "User is not authorized"}), 401 - - response = update_about_by_slug(slug, about) - return jsonify(response), 200 - - except Exception as e: - print(e) - return jsonify({"error": f"Error while updating about for user {slug}"}), 500 - - -@core.route("/top-users", methods=["GET"]) -def get_top_users(): - """Fetch the top users based on Kleo points.""" - try: - limit = request.args.get("limit", default=20, type=int) - leaderboard = get_top_users_by_kleo_points(limit) - return jsonify(leaderboard), 200 - except Exception as e: - logger.error(f"Error in get_top_users: {str(e)}") - return jsonify({"error": "An error occurred while fetching top users"}), 500 - - -@core.route("/rank/", methods=["GET"]) -def get_user_rank(slug): - """Get the rank of a user by slug.""" - result, status_code = calculate_rank(slug) - return jsonify(result), status_code diff --git a/docker-compose.yml b/docker-compose.yml index b80faed..70faf7f 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -5,7 +5,13 @@ services: - 6379:6379 api: build: . - command: gunicorn -w 4 --bind 0.0.0.0:5001 run:app + command: gunicorn --workers 4 \ + --threads 2 \ + --timeout 30 \ + --keep-alive 5 \ + --max-requests 1000 \ + --max-requests-jitter 50 \ + 'app:create_app()' ports: - 5001:5001 volumes: diff --git a/myenv/bin/Activate.ps1 b/myenv/bin/Activate.ps1 new file mode 100644 index 0000000..b49d77b --- /dev/null +++ b/myenv/bin/Activate.ps1 @@ -0,0 +1,247 @@ +<# +.Synopsis +Activate a Python virtual environment for the current PowerShell session. + +.Description +Pushes the python executable for a virtual environment to the front of the +$Env:PATH environment variable and sets the prompt to signify that you are +in a Python virtual environment. Makes use of the command line switches as +well as the `pyvenv.cfg` file values present in the virtual environment. + +.Parameter VenvDir +Path to the directory that contains the virtual environment to activate. The +default value for this is the parent of the directory that the Activate.ps1 +script is located within. + +.Parameter Prompt +The prompt prefix to display when this virtual environment is activated. By +default, this prompt is the name of the virtual environment folder (VenvDir) +surrounded by parentheses and followed by a single space (ie. '(.venv) '). + +.Example +Activate.ps1 +Activates the Python virtual environment that contains the Activate.ps1 script. + +.Example +Activate.ps1 -Verbose +Activates the Python virtual environment that contains the Activate.ps1 script, +and shows extra information about the activation as it executes. + +.Example +Activate.ps1 -VenvDir C:\Users\MyUser\Common\.venv +Activates the Python virtual environment located in the specified location. + +.Example +Activate.ps1 -Prompt "MyPython" +Activates the Python virtual environment that contains the Activate.ps1 script, +and prefixes the current prompt with the specified string (surrounded in +parentheses) while the virtual environment is active. + +.Notes +On Windows, it may be required to enable this Activate.ps1 script by setting the +execution policy for the user. You can do this by issuing the following PowerShell +command: + +PS C:\> Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser + +For more information on Execution Policies: +https://go.microsoft.com/fwlink/?LinkID=135170 + +#> +Param( + [Parameter(Mandatory = $false)] + [String] + $VenvDir, + [Parameter(Mandatory = $false)] + [String] + $Prompt +) + +<# Function declarations --------------------------------------------------- #> + +<# +.Synopsis +Remove all shell session elements added by the Activate script, including the +addition of the virtual environment's Python executable from the beginning of +the PATH variable. + +.Parameter NonDestructive +If present, do not remove this function from the global namespace for the +session. + +#> +function global:deactivate ([switch]$NonDestructive) { + # Revert to original values + + # The prior prompt: + if (Test-Path -Path Function:_OLD_VIRTUAL_PROMPT) { + Copy-Item -Path Function:_OLD_VIRTUAL_PROMPT -Destination Function:prompt + Remove-Item -Path Function:_OLD_VIRTUAL_PROMPT + } + + # The prior PYTHONHOME: + if (Test-Path -Path Env:_OLD_VIRTUAL_PYTHONHOME) { + Copy-Item -Path Env:_OLD_VIRTUAL_PYTHONHOME -Destination Env:PYTHONHOME + Remove-Item -Path Env:_OLD_VIRTUAL_PYTHONHOME + } + + # The prior PATH: + if (Test-Path -Path Env:_OLD_VIRTUAL_PATH) { + Copy-Item -Path Env:_OLD_VIRTUAL_PATH -Destination Env:PATH + Remove-Item -Path Env:_OLD_VIRTUAL_PATH + } + + # Just remove the VIRTUAL_ENV altogether: + if (Test-Path -Path Env:VIRTUAL_ENV) { + Remove-Item -Path env:VIRTUAL_ENV + } + + # Just remove VIRTUAL_ENV_PROMPT altogether. + if (Test-Path -Path Env:VIRTUAL_ENV_PROMPT) { + Remove-Item -Path env:VIRTUAL_ENV_PROMPT + } + + # Just remove the _PYTHON_VENV_PROMPT_PREFIX altogether: + if (Get-Variable -Name "_PYTHON_VENV_PROMPT_PREFIX" -ErrorAction SilentlyContinue) { + Remove-Variable -Name _PYTHON_VENV_PROMPT_PREFIX -Scope Global -Force + } + + # Leave deactivate function in the global namespace if requested: + if (-not $NonDestructive) { + Remove-Item -Path function:deactivate + } +} + +<# +.Description +Get-PyVenvConfig parses the values from the pyvenv.cfg file located in the +given folder, and returns them in a map. + +For each line in the pyvenv.cfg file, if that line can be parsed into exactly +two strings separated by `=` (with any amount of whitespace surrounding the =) +then it is considered a `key = value` line. The left hand string is the key, +the right hand is the value. + +If the value starts with a `'` or a `"` then the first and last character is +stripped from the value before being captured. + +.Parameter ConfigDir +Path to the directory that contains the `pyvenv.cfg` file. +#> +function Get-PyVenvConfig( + [String] + $ConfigDir +) { + Write-Verbose "Given ConfigDir=$ConfigDir, obtain values in pyvenv.cfg" + + # Ensure the file exists, and issue a warning if it doesn't (but still allow the function to continue). + $pyvenvConfigPath = Join-Path -Resolve -Path $ConfigDir -ChildPath 'pyvenv.cfg' -ErrorAction Continue + + # An empty map will be returned if no config file is found. + $pyvenvConfig = @{ } + + if ($pyvenvConfigPath) { + + Write-Verbose "File exists, parse `key = value` lines" + $pyvenvConfigContent = Get-Content -Path $pyvenvConfigPath + + $pyvenvConfigContent | ForEach-Object { + $keyval = $PSItem -split "\s*=\s*", 2 + if ($keyval[0] -and $keyval[1]) { + $val = $keyval[1] + + # Remove extraneous quotations around a string value. + if ("'""".Contains($val.Substring(0, 1))) { + $val = $val.Substring(1, $val.Length - 2) + } + + $pyvenvConfig[$keyval[0]] = $val + Write-Verbose "Adding Key: '$($keyval[0])'='$val'" + } + } + } + return $pyvenvConfig +} + + +<# Begin Activate script --------------------------------------------------- #> + +# Determine the containing directory of this script +$VenvExecPath = Split-Path -Parent $MyInvocation.MyCommand.Definition +$VenvExecDir = Get-Item -Path $VenvExecPath + +Write-Verbose "Activation script is located in path: '$VenvExecPath'" +Write-Verbose "VenvExecDir Fullname: '$($VenvExecDir.FullName)" +Write-Verbose "VenvExecDir Name: '$($VenvExecDir.Name)" + +# Set values required in priority: CmdLine, ConfigFile, Default +# First, get the location of the virtual environment, it might not be +# VenvExecDir if specified on the command line. +if ($VenvDir) { + Write-Verbose "VenvDir given as parameter, using '$VenvDir' to determine values" +} +else { + Write-Verbose "VenvDir not given as a parameter, using parent directory name as VenvDir." + $VenvDir = $VenvExecDir.Parent.FullName.TrimEnd("\\/") + Write-Verbose "VenvDir=$VenvDir" +} + +# Next, read the `pyvenv.cfg` file to determine any required value such +# as `prompt`. +$pyvenvCfg = Get-PyVenvConfig -ConfigDir $VenvDir + +# Next, set the prompt from the command line, or the config file, or +# just use the name of the virtual environment folder. +if ($Prompt) { + Write-Verbose "Prompt specified as argument, using '$Prompt'" +} +else { + Write-Verbose "Prompt not specified as argument to script, checking pyvenv.cfg value" + if ($pyvenvCfg -and $pyvenvCfg['prompt']) { + Write-Verbose " Setting based on value in pyvenv.cfg='$($pyvenvCfg['prompt'])'" + $Prompt = $pyvenvCfg['prompt']; + } + else { + Write-Verbose " Setting prompt based on parent's directory's name. (Is the directory name passed to venv module when creating the virtual environment)" + Write-Verbose " Got leaf-name of $VenvDir='$(Split-Path -Path $venvDir -Leaf)'" + $Prompt = Split-Path -Path $venvDir -Leaf + } +} + +Write-Verbose "Prompt = '$Prompt'" +Write-Verbose "VenvDir='$VenvDir'" + +# Deactivate any currently active virtual environment, but leave the +# deactivate function in place. +deactivate -nondestructive + +# Now set the environment variable VIRTUAL_ENV, used by many tools to determine +# that there is an activated venv. +$env:VIRTUAL_ENV = $VenvDir + +if (-not $Env:VIRTUAL_ENV_DISABLE_PROMPT) { + + Write-Verbose "Setting prompt to '$Prompt'" + + # Set the prompt to include the env name + # Make sure _OLD_VIRTUAL_PROMPT is global + function global:_OLD_VIRTUAL_PROMPT { "" } + Copy-Item -Path function:prompt -Destination function:_OLD_VIRTUAL_PROMPT + New-Variable -Name _PYTHON_VENV_PROMPT_PREFIX -Description "Python virtual environment prompt prefix" -Scope Global -Option ReadOnly -Visibility Public -Value $Prompt + + function global:prompt { + Write-Host -NoNewline -ForegroundColor Green "($_PYTHON_VENV_PROMPT_PREFIX) " + _OLD_VIRTUAL_PROMPT + } + $env:VIRTUAL_ENV_PROMPT = $Prompt +} + +# Clear PYTHONHOME +if (Test-Path -Path Env:PYTHONHOME) { + Copy-Item -Path Env:PYTHONHOME -Destination Env:_OLD_VIRTUAL_PYTHONHOME + Remove-Item -Path Env:PYTHONHOME +} + +# Add the venv to the PATH +Copy-Item -Path Env:PATH -Destination Env:_OLD_VIRTUAL_PATH +$Env:PATH = "$VenvExecDir$([System.IO.Path]::PathSeparator)$Env:PATH" diff --git a/myenv/bin/activate b/myenv/bin/activate new file mode 100644 index 0000000..27ac115 --- /dev/null +++ b/myenv/bin/activate @@ -0,0 +1,70 @@ +# This file must be used with "source bin/activate" *from bash* +# You cannot run it directly + +deactivate () { + # reset old environment variables + if [ -n "${_OLD_VIRTUAL_PATH:-}" ] ; then + PATH="${_OLD_VIRTUAL_PATH:-}" + export PATH + unset _OLD_VIRTUAL_PATH + fi + if [ -n "${_OLD_VIRTUAL_PYTHONHOME:-}" ] ; then + PYTHONHOME="${_OLD_VIRTUAL_PYTHONHOME:-}" + export PYTHONHOME + unset _OLD_VIRTUAL_PYTHONHOME + fi + + # Call hash to forget past commands. Without forgetting + # past commands the $PATH changes we made may not be respected + hash -r 2> /dev/null + + if [ -n "${_OLD_VIRTUAL_PS1:-}" ] ; then + PS1="${_OLD_VIRTUAL_PS1:-}" + export PS1 + unset _OLD_VIRTUAL_PS1 + fi + + unset VIRTUAL_ENV + unset VIRTUAL_ENV_PROMPT + if [ ! "${1:-}" = "nondestructive" ] ; then + # Self destruct! + unset -f deactivate + fi +} + +# unset irrelevant variables +deactivate nondestructive + +# on Windows, a path can contain colons and backslashes and has to be converted: +if [ "${OSTYPE:-}" = "cygwin" ] || [ "${OSTYPE:-}" = "msys" ] ; then + # transform D:\path\to\venv to /d/path/to/venv on MSYS + # and to /cygdrive/d/path/to/venv on Cygwin + export VIRTUAL_ENV=$(cygpath "/Users/vaibhavgeek/kleo/backend/myenv") +else + # use the path as-is + export VIRTUAL_ENV="/Users/vaibhavgeek/kleo/backend/myenv" +fi + +_OLD_VIRTUAL_PATH="$PATH" +PATH="$VIRTUAL_ENV/bin:$PATH" +export PATH + +# unset PYTHONHOME if set +# this will fail if PYTHONHOME is set to the empty string (which is bad anyway) +# could use `if (set -u; : $PYTHONHOME) ;` in bash +if [ -n "${PYTHONHOME:-}" ] ; then + _OLD_VIRTUAL_PYTHONHOME="${PYTHONHOME:-}" + unset PYTHONHOME +fi + +if [ -z "${VIRTUAL_ENV_DISABLE_PROMPT:-}" ] ; then + _OLD_VIRTUAL_PS1="${PS1:-}" + PS1="(myenv) ${PS1:-}" + export PS1 + VIRTUAL_ENV_PROMPT="(myenv) " + export VIRTUAL_ENV_PROMPT +fi + +# Call hash to forget past commands. Without forgetting +# past commands the $PATH changes we made may not be respected +hash -r 2> /dev/null diff --git a/myenv/bin/activate.csh b/myenv/bin/activate.csh new file mode 100644 index 0000000..36a4e78 --- /dev/null +++ b/myenv/bin/activate.csh @@ -0,0 +1,27 @@ +# This file must be used with "source bin/activate.csh" *from csh*. +# You cannot run it directly. + +# Created by Davide Di Blasi . +# Ported to Python 3.3 venv by Andrew Svetlov + +alias deactivate 'test $?_OLD_VIRTUAL_PATH != 0 && setenv PATH "$_OLD_VIRTUAL_PATH" && unset _OLD_VIRTUAL_PATH; rehash; test $?_OLD_VIRTUAL_PROMPT != 0 && set prompt="$_OLD_VIRTUAL_PROMPT" && unset _OLD_VIRTUAL_PROMPT; unsetenv VIRTUAL_ENV; unsetenv VIRTUAL_ENV_PROMPT; test "\!:*" != "nondestructive" && unalias deactivate' + +# Unset irrelevant variables. +deactivate nondestructive + +setenv VIRTUAL_ENV "/Users/vaibhavgeek/kleo/backend/myenv" + +set _OLD_VIRTUAL_PATH="$PATH" +setenv PATH "$VIRTUAL_ENV/bin:$PATH" + + +set _OLD_VIRTUAL_PROMPT="$prompt" + +if (! "$?VIRTUAL_ENV_DISABLE_PROMPT") then + set prompt = "(myenv) $prompt" + setenv VIRTUAL_ENV_PROMPT "(myenv) " +endif + +alias pydoc python -m pydoc + +rehash diff --git a/myenv/bin/activate.fish b/myenv/bin/activate.fish new file mode 100644 index 0000000..6b059cc --- /dev/null +++ b/myenv/bin/activate.fish @@ -0,0 +1,69 @@ +# This file must be used with "source /bin/activate.fish" *from fish* +# (https://fishshell.com/). You cannot run it directly. + +function deactivate -d "Exit virtual environment and return to normal shell environment" + # reset old environment variables + if test -n "$_OLD_VIRTUAL_PATH" + set -gx PATH $_OLD_VIRTUAL_PATH + set -e _OLD_VIRTUAL_PATH + end + if test -n "$_OLD_VIRTUAL_PYTHONHOME" + set -gx PYTHONHOME $_OLD_VIRTUAL_PYTHONHOME + set -e _OLD_VIRTUAL_PYTHONHOME + end + + if test -n "$_OLD_FISH_PROMPT_OVERRIDE" + set -e _OLD_FISH_PROMPT_OVERRIDE + # prevents error when using nested fish instances (Issue #93858) + if functions -q _old_fish_prompt + functions -e fish_prompt + functions -c _old_fish_prompt fish_prompt + functions -e _old_fish_prompt + end + end + + set -e VIRTUAL_ENV + set -e VIRTUAL_ENV_PROMPT + if test "$argv[1]" != "nondestructive" + # Self-destruct! + functions -e deactivate + end +end + +# Unset irrelevant variables. +deactivate nondestructive + +set -gx VIRTUAL_ENV "/Users/vaibhavgeek/kleo/backend/myenv" + +set -gx _OLD_VIRTUAL_PATH $PATH +set -gx PATH "$VIRTUAL_ENV/bin" $PATH + +# Unset PYTHONHOME if set. +if set -q PYTHONHOME + set -gx _OLD_VIRTUAL_PYTHONHOME $PYTHONHOME + set -e PYTHONHOME +end + +if test -z "$VIRTUAL_ENV_DISABLE_PROMPT" + # fish uses a function instead of an env var to generate the prompt. + + # Save the current fish_prompt function as the function _old_fish_prompt. + functions -c fish_prompt _old_fish_prompt + + # With the original prompt function renamed, we can override with our own. + function fish_prompt + # Save the return status of the last command. + set -l old_status $status + + # Output the venv prompt; color taken from the blue of the Python logo. + printf "%s%s%s" (set_color 4B8BBE) "(myenv) " (set_color normal) + + # Restore the return status of the previous command. + echo "exit $old_status" | . + # Output the original/"old" prompt. + _old_fish_prompt + end + + set -gx _OLD_FISH_PROMPT_OVERRIDE "$VIRTUAL_ENV" + set -gx VIRTUAL_ENV_PROMPT "(myenv) " +end diff --git a/myenv/bin/pip b/myenv/bin/pip new file mode 100755 index 0000000..dcc819f --- /dev/null +++ b/myenv/bin/pip @@ -0,0 +1,8 @@ +#!/Users/vaibhavgeek/kleo/backend/myenv/bin/python3.12 +# -*- coding: utf-8 -*- +import re +import sys +from pip._internal.cli.main import main +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/myenv/bin/pip3 b/myenv/bin/pip3 new file mode 100755 index 0000000..dcc819f --- /dev/null +++ b/myenv/bin/pip3 @@ -0,0 +1,8 @@ +#!/Users/vaibhavgeek/kleo/backend/myenv/bin/python3.12 +# -*- coding: utf-8 -*- +import re +import sys +from pip._internal.cli.main import main +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/myenv/bin/pip3.12 b/myenv/bin/pip3.12 new file mode 100755 index 0000000..dcc819f --- /dev/null +++ b/myenv/bin/pip3.12 @@ -0,0 +1,8 @@ +#!/Users/vaibhavgeek/kleo/backend/myenv/bin/python3.12 +# -*- coding: utf-8 -*- +import re +import sys +from pip._internal.cli.main import main +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/myenv/bin/python b/myenv/bin/python new file mode 120000 index 0000000..11b9d88 --- /dev/null +++ b/myenv/bin/python @@ -0,0 +1 @@ +python3.12 \ No newline at end of file diff --git a/myenv/bin/python3 b/myenv/bin/python3 new file mode 120000 index 0000000..11b9d88 --- /dev/null +++ b/myenv/bin/python3 @@ -0,0 +1 @@ +python3.12 \ No newline at end of file diff --git a/myenv/bin/python3.12 b/myenv/bin/python3.12 new file mode 120000 index 0000000..a3f0508 --- /dev/null +++ b/myenv/bin/python3.12 @@ -0,0 +1 @@ +/opt/homebrew/opt/python@3.12/bin/python3.12 \ No newline at end of file diff --git a/myenv/pyvenv.cfg b/myenv/pyvenv.cfg new file mode 100644 index 0000000..2726b66 --- /dev/null +++ b/myenv/pyvenv.cfg @@ -0,0 +1,5 @@ +home = /opt/homebrew/opt/python@3.12/bin +include-system-site-packages = false +version = 3.12.5 +executable = /opt/homebrew/Cellar/python@3.12/3.12.5/Frameworks/Python.framework/Versions/3.12/bin/python3.12 +command = /opt/homebrew/opt/python@3.12/bin/python3.12 -m venv /Users/vaibhavgeek/kleo/backend/myenv From 46c189621656de495c17fcc27e900f9ca928cea4 Mon Sep 17 00:00:00 2001 From: Vaibhav Maheshwari Date: Sun, 3 Nov 2024 04:25:44 +0530 Subject: [PATCH 02/12] fix everything 2 --- myenv/bin/Activate.ps1 | 247 ---------------------------------------- myenv/bin/activate | 70 ------------ myenv/bin/activate.csh | 27 ----- myenv/bin/activate.fish | 69 ----------- myenv/bin/pip | 8 -- myenv/bin/pip3 | 8 -- myenv/bin/pip3.12 | 8 -- myenv/bin/python | 1 - myenv/bin/python3 | 1 - myenv/bin/python3.12 | 1 - myenv/pyvenv.cfg | 5 - 11 files changed, 445 deletions(-) delete mode 100644 myenv/bin/Activate.ps1 delete mode 100644 myenv/bin/activate delete mode 100644 myenv/bin/activate.csh delete mode 100644 myenv/bin/activate.fish delete mode 100755 myenv/bin/pip delete mode 100755 myenv/bin/pip3 delete mode 100755 myenv/bin/pip3.12 delete mode 120000 myenv/bin/python delete mode 120000 myenv/bin/python3 delete mode 120000 myenv/bin/python3.12 delete mode 100644 myenv/pyvenv.cfg diff --git a/myenv/bin/Activate.ps1 b/myenv/bin/Activate.ps1 deleted file mode 100644 index b49d77b..0000000 --- a/myenv/bin/Activate.ps1 +++ /dev/null @@ -1,247 +0,0 @@ -<# -.Synopsis -Activate a Python virtual environment for the current PowerShell session. - -.Description -Pushes the python executable for a virtual environment to the front of the -$Env:PATH environment variable and sets the prompt to signify that you are -in a Python virtual environment. Makes use of the command line switches as -well as the `pyvenv.cfg` file values present in the virtual environment. - -.Parameter VenvDir -Path to the directory that contains the virtual environment to activate. The -default value for this is the parent of the directory that the Activate.ps1 -script is located within. - -.Parameter Prompt -The prompt prefix to display when this virtual environment is activated. By -default, this prompt is the name of the virtual environment folder (VenvDir) -surrounded by parentheses and followed by a single space (ie. '(.venv) '). - -.Example -Activate.ps1 -Activates the Python virtual environment that contains the Activate.ps1 script. - -.Example -Activate.ps1 -Verbose -Activates the Python virtual environment that contains the Activate.ps1 script, -and shows extra information about the activation as it executes. - -.Example -Activate.ps1 -VenvDir C:\Users\MyUser\Common\.venv -Activates the Python virtual environment located in the specified location. - -.Example -Activate.ps1 -Prompt "MyPython" -Activates the Python virtual environment that contains the Activate.ps1 script, -and prefixes the current prompt with the specified string (surrounded in -parentheses) while the virtual environment is active. - -.Notes -On Windows, it may be required to enable this Activate.ps1 script by setting the -execution policy for the user. You can do this by issuing the following PowerShell -command: - -PS C:\> Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser - -For more information on Execution Policies: -https://go.microsoft.com/fwlink/?LinkID=135170 - -#> -Param( - [Parameter(Mandatory = $false)] - [String] - $VenvDir, - [Parameter(Mandatory = $false)] - [String] - $Prompt -) - -<# Function declarations --------------------------------------------------- #> - -<# -.Synopsis -Remove all shell session elements added by the Activate script, including the -addition of the virtual environment's Python executable from the beginning of -the PATH variable. - -.Parameter NonDestructive -If present, do not remove this function from the global namespace for the -session. - -#> -function global:deactivate ([switch]$NonDestructive) { - # Revert to original values - - # The prior prompt: - if (Test-Path -Path Function:_OLD_VIRTUAL_PROMPT) { - Copy-Item -Path Function:_OLD_VIRTUAL_PROMPT -Destination Function:prompt - Remove-Item -Path Function:_OLD_VIRTUAL_PROMPT - } - - # The prior PYTHONHOME: - if (Test-Path -Path Env:_OLD_VIRTUAL_PYTHONHOME) { - Copy-Item -Path Env:_OLD_VIRTUAL_PYTHONHOME -Destination Env:PYTHONHOME - Remove-Item -Path Env:_OLD_VIRTUAL_PYTHONHOME - } - - # The prior PATH: - if (Test-Path -Path Env:_OLD_VIRTUAL_PATH) { - Copy-Item -Path Env:_OLD_VIRTUAL_PATH -Destination Env:PATH - Remove-Item -Path Env:_OLD_VIRTUAL_PATH - } - - # Just remove the VIRTUAL_ENV altogether: - if (Test-Path -Path Env:VIRTUAL_ENV) { - Remove-Item -Path env:VIRTUAL_ENV - } - - # Just remove VIRTUAL_ENV_PROMPT altogether. - if (Test-Path -Path Env:VIRTUAL_ENV_PROMPT) { - Remove-Item -Path env:VIRTUAL_ENV_PROMPT - } - - # Just remove the _PYTHON_VENV_PROMPT_PREFIX altogether: - if (Get-Variable -Name "_PYTHON_VENV_PROMPT_PREFIX" -ErrorAction SilentlyContinue) { - Remove-Variable -Name _PYTHON_VENV_PROMPT_PREFIX -Scope Global -Force - } - - # Leave deactivate function in the global namespace if requested: - if (-not $NonDestructive) { - Remove-Item -Path function:deactivate - } -} - -<# -.Description -Get-PyVenvConfig parses the values from the pyvenv.cfg file located in the -given folder, and returns them in a map. - -For each line in the pyvenv.cfg file, if that line can be parsed into exactly -two strings separated by `=` (with any amount of whitespace surrounding the =) -then it is considered a `key = value` line. The left hand string is the key, -the right hand is the value. - -If the value starts with a `'` or a `"` then the first and last character is -stripped from the value before being captured. - -.Parameter ConfigDir -Path to the directory that contains the `pyvenv.cfg` file. -#> -function Get-PyVenvConfig( - [String] - $ConfigDir -) { - Write-Verbose "Given ConfigDir=$ConfigDir, obtain values in pyvenv.cfg" - - # Ensure the file exists, and issue a warning if it doesn't (but still allow the function to continue). - $pyvenvConfigPath = Join-Path -Resolve -Path $ConfigDir -ChildPath 'pyvenv.cfg' -ErrorAction Continue - - # An empty map will be returned if no config file is found. - $pyvenvConfig = @{ } - - if ($pyvenvConfigPath) { - - Write-Verbose "File exists, parse `key = value` lines" - $pyvenvConfigContent = Get-Content -Path $pyvenvConfigPath - - $pyvenvConfigContent | ForEach-Object { - $keyval = $PSItem -split "\s*=\s*", 2 - if ($keyval[0] -and $keyval[1]) { - $val = $keyval[1] - - # Remove extraneous quotations around a string value. - if ("'""".Contains($val.Substring(0, 1))) { - $val = $val.Substring(1, $val.Length - 2) - } - - $pyvenvConfig[$keyval[0]] = $val - Write-Verbose "Adding Key: '$($keyval[0])'='$val'" - } - } - } - return $pyvenvConfig -} - - -<# Begin Activate script --------------------------------------------------- #> - -# Determine the containing directory of this script -$VenvExecPath = Split-Path -Parent $MyInvocation.MyCommand.Definition -$VenvExecDir = Get-Item -Path $VenvExecPath - -Write-Verbose "Activation script is located in path: '$VenvExecPath'" -Write-Verbose "VenvExecDir Fullname: '$($VenvExecDir.FullName)" -Write-Verbose "VenvExecDir Name: '$($VenvExecDir.Name)" - -# Set values required in priority: CmdLine, ConfigFile, Default -# First, get the location of the virtual environment, it might not be -# VenvExecDir if specified on the command line. -if ($VenvDir) { - Write-Verbose "VenvDir given as parameter, using '$VenvDir' to determine values" -} -else { - Write-Verbose "VenvDir not given as a parameter, using parent directory name as VenvDir." - $VenvDir = $VenvExecDir.Parent.FullName.TrimEnd("\\/") - Write-Verbose "VenvDir=$VenvDir" -} - -# Next, read the `pyvenv.cfg` file to determine any required value such -# as `prompt`. -$pyvenvCfg = Get-PyVenvConfig -ConfigDir $VenvDir - -# Next, set the prompt from the command line, or the config file, or -# just use the name of the virtual environment folder. -if ($Prompt) { - Write-Verbose "Prompt specified as argument, using '$Prompt'" -} -else { - Write-Verbose "Prompt not specified as argument to script, checking pyvenv.cfg value" - if ($pyvenvCfg -and $pyvenvCfg['prompt']) { - Write-Verbose " Setting based on value in pyvenv.cfg='$($pyvenvCfg['prompt'])'" - $Prompt = $pyvenvCfg['prompt']; - } - else { - Write-Verbose " Setting prompt based on parent's directory's name. (Is the directory name passed to venv module when creating the virtual environment)" - Write-Verbose " Got leaf-name of $VenvDir='$(Split-Path -Path $venvDir -Leaf)'" - $Prompt = Split-Path -Path $venvDir -Leaf - } -} - -Write-Verbose "Prompt = '$Prompt'" -Write-Verbose "VenvDir='$VenvDir'" - -# Deactivate any currently active virtual environment, but leave the -# deactivate function in place. -deactivate -nondestructive - -# Now set the environment variable VIRTUAL_ENV, used by many tools to determine -# that there is an activated venv. -$env:VIRTUAL_ENV = $VenvDir - -if (-not $Env:VIRTUAL_ENV_DISABLE_PROMPT) { - - Write-Verbose "Setting prompt to '$Prompt'" - - # Set the prompt to include the env name - # Make sure _OLD_VIRTUAL_PROMPT is global - function global:_OLD_VIRTUAL_PROMPT { "" } - Copy-Item -Path function:prompt -Destination function:_OLD_VIRTUAL_PROMPT - New-Variable -Name _PYTHON_VENV_PROMPT_PREFIX -Description "Python virtual environment prompt prefix" -Scope Global -Option ReadOnly -Visibility Public -Value $Prompt - - function global:prompt { - Write-Host -NoNewline -ForegroundColor Green "($_PYTHON_VENV_PROMPT_PREFIX) " - _OLD_VIRTUAL_PROMPT - } - $env:VIRTUAL_ENV_PROMPT = $Prompt -} - -# Clear PYTHONHOME -if (Test-Path -Path Env:PYTHONHOME) { - Copy-Item -Path Env:PYTHONHOME -Destination Env:_OLD_VIRTUAL_PYTHONHOME - Remove-Item -Path Env:PYTHONHOME -} - -# Add the venv to the PATH -Copy-Item -Path Env:PATH -Destination Env:_OLD_VIRTUAL_PATH -$Env:PATH = "$VenvExecDir$([System.IO.Path]::PathSeparator)$Env:PATH" diff --git a/myenv/bin/activate b/myenv/bin/activate deleted file mode 100644 index 27ac115..0000000 --- a/myenv/bin/activate +++ /dev/null @@ -1,70 +0,0 @@ -# This file must be used with "source bin/activate" *from bash* -# You cannot run it directly - -deactivate () { - # reset old environment variables - if [ -n "${_OLD_VIRTUAL_PATH:-}" ] ; then - PATH="${_OLD_VIRTUAL_PATH:-}" - export PATH - unset _OLD_VIRTUAL_PATH - fi - if [ -n "${_OLD_VIRTUAL_PYTHONHOME:-}" ] ; then - PYTHONHOME="${_OLD_VIRTUAL_PYTHONHOME:-}" - export PYTHONHOME - unset _OLD_VIRTUAL_PYTHONHOME - fi - - # Call hash to forget past commands. Without forgetting - # past commands the $PATH changes we made may not be respected - hash -r 2> /dev/null - - if [ -n "${_OLD_VIRTUAL_PS1:-}" ] ; then - PS1="${_OLD_VIRTUAL_PS1:-}" - export PS1 - unset _OLD_VIRTUAL_PS1 - fi - - unset VIRTUAL_ENV - unset VIRTUAL_ENV_PROMPT - if [ ! "${1:-}" = "nondestructive" ] ; then - # Self destruct! - unset -f deactivate - fi -} - -# unset irrelevant variables -deactivate nondestructive - -# on Windows, a path can contain colons and backslashes and has to be converted: -if [ "${OSTYPE:-}" = "cygwin" ] || [ "${OSTYPE:-}" = "msys" ] ; then - # transform D:\path\to\venv to /d/path/to/venv on MSYS - # and to /cygdrive/d/path/to/venv on Cygwin - export VIRTUAL_ENV=$(cygpath "/Users/vaibhavgeek/kleo/backend/myenv") -else - # use the path as-is - export VIRTUAL_ENV="/Users/vaibhavgeek/kleo/backend/myenv" -fi - -_OLD_VIRTUAL_PATH="$PATH" -PATH="$VIRTUAL_ENV/bin:$PATH" -export PATH - -# unset PYTHONHOME if set -# this will fail if PYTHONHOME is set to the empty string (which is bad anyway) -# could use `if (set -u; : $PYTHONHOME) ;` in bash -if [ -n "${PYTHONHOME:-}" ] ; then - _OLD_VIRTUAL_PYTHONHOME="${PYTHONHOME:-}" - unset PYTHONHOME -fi - -if [ -z "${VIRTUAL_ENV_DISABLE_PROMPT:-}" ] ; then - _OLD_VIRTUAL_PS1="${PS1:-}" - PS1="(myenv) ${PS1:-}" - export PS1 - VIRTUAL_ENV_PROMPT="(myenv) " - export VIRTUAL_ENV_PROMPT -fi - -# Call hash to forget past commands. Without forgetting -# past commands the $PATH changes we made may not be respected -hash -r 2> /dev/null diff --git a/myenv/bin/activate.csh b/myenv/bin/activate.csh deleted file mode 100644 index 36a4e78..0000000 --- a/myenv/bin/activate.csh +++ /dev/null @@ -1,27 +0,0 @@ -# This file must be used with "source bin/activate.csh" *from csh*. -# You cannot run it directly. - -# Created by Davide Di Blasi . -# Ported to Python 3.3 venv by Andrew Svetlov - -alias deactivate 'test $?_OLD_VIRTUAL_PATH != 0 && setenv PATH "$_OLD_VIRTUAL_PATH" && unset _OLD_VIRTUAL_PATH; rehash; test $?_OLD_VIRTUAL_PROMPT != 0 && set prompt="$_OLD_VIRTUAL_PROMPT" && unset _OLD_VIRTUAL_PROMPT; unsetenv VIRTUAL_ENV; unsetenv VIRTUAL_ENV_PROMPT; test "\!:*" != "nondestructive" && unalias deactivate' - -# Unset irrelevant variables. -deactivate nondestructive - -setenv VIRTUAL_ENV "/Users/vaibhavgeek/kleo/backend/myenv" - -set _OLD_VIRTUAL_PATH="$PATH" -setenv PATH "$VIRTUAL_ENV/bin:$PATH" - - -set _OLD_VIRTUAL_PROMPT="$prompt" - -if (! "$?VIRTUAL_ENV_DISABLE_PROMPT") then - set prompt = "(myenv) $prompt" - setenv VIRTUAL_ENV_PROMPT "(myenv) " -endif - -alias pydoc python -m pydoc - -rehash diff --git a/myenv/bin/activate.fish b/myenv/bin/activate.fish deleted file mode 100644 index 6b059cc..0000000 --- a/myenv/bin/activate.fish +++ /dev/null @@ -1,69 +0,0 @@ -# This file must be used with "source /bin/activate.fish" *from fish* -# (https://fishshell.com/). You cannot run it directly. - -function deactivate -d "Exit virtual environment and return to normal shell environment" - # reset old environment variables - if test -n "$_OLD_VIRTUAL_PATH" - set -gx PATH $_OLD_VIRTUAL_PATH - set -e _OLD_VIRTUAL_PATH - end - if test -n "$_OLD_VIRTUAL_PYTHONHOME" - set -gx PYTHONHOME $_OLD_VIRTUAL_PYTHONHOME - set -e _OLD_VIRTUAL_PYTHONHOME - end - - if test -n "$_OLD_FISH_PROMPT_OVERRIDE" - set -e _OLD_FISH_PROMPT_OVERRIDE - # prevents error when using nested fish instances (Issue #93858) - if functions -q _old_fish_prompt - functions -e fish_prompt - functions -c _old_fish_prompt fish_prompt - functions -e _old_fish_prompt - end - end - - set -e VIRTUAL_ENV - set -e VIRTUAL_ENV_PROMPT - if test "$argv[1]" != "nondestructive" - # Self-destruct! - functions -e deactivate - end -end - -# Unset irrelevant variables. -deactivate nondestructive - -set -gx VIRTUAL_ENV "/Users/vaibhavgeek/kleo/backend/myenv" - -set -gx _OLD_VIRTUAL_PATH $PATH -set -gx PATH "$VIRTUAL_ENV/bin" $PATH - -# Unset PYTHONHOME if set. -if set -q PYTHONHOME - set -gx _OLD_VIRTUAL_PYTHONHOME $PYTHONHOME - set -e PYTHONHOME -end - -if test -z "$VIRTUAL_ENV_DISABLE_PROMPT" - # fish uses a function instead of an env var to generate the prompt. - - # Save the current fish_prompt function as the function _old_fish_prompt. - functions -c fish_prompt _old_fish_prompt - - # With the original prompt function renamed, we can override with our own. - function fish_prompt - # Save the return status of the last command. - set -l old_status $status - - # Output the venv prompt; color taken from the blue of the Python logo. - printf "%s%s%s" (set_color 4B8BBE) "(myenv) " (set_color normal) - - # Restore the return status of the previous command. - echo "exit $old_status" | . - # Output the original/"old" prompt. - _old_fish_prompt - end - - set -gx _OLD_FISH_PROMPT_OVERRIDE "$VIRTUAL_ENV" - set -gx VIRTUAL_ENV_PROMPT "(myenv) " -end diff --git a/myenv/bin/pip b/myenv/bin/pip deleted file mode 100755 index dcc819f..0000000 --- a/myenv/bin/pip +++ /dev/null @@ -1,8 +0,0 @@ -#!/Users/vaibhavgeek/kleo/backend/myenv/bin/python3.12 -# -*- coding: utf-8 -*- -import re -import sys -from pip._internal.cli.main import main -if __name__ == '__main__': - sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) - sys.exit(main()) diff --git a/myenv/bin/pip3 b/myenv/bin/pip3 deleted file mode 100755 index dcc819f..0000000 --- a/myenv/bin/pip3 +++ /dev/null @@ -1,8 +0,0 @@ -#!/Users/vaibhavgeek/kleo/backend/myenv/bin/python3.12 -# -*- coding: utf-8 -*- -import re -import sys -from pip._internal.cli.main import main -if __name__ == '__main__': - sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) - sys.exit(main()) diff --git a/myenv/bin/pip3.12 b/myenv/bin/pip3.12 deleted file mode 100755 index dcc819f..0000000 --- a/myenv/bin/pip3.12 +++ /dev/null @@ -1,8 +0,0 @@ -#!/Users/vaibhavgeek/kleo/backend/myenv/bin/python3.12 -# -*- coding: utf-8 -*- -import re -import sys -from pip._internal.cli.main import main -if __name__ == '__main__': - sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) - sys.exit(main()) diff --git a/myenv/bin/python b/myenv/bin/python deleted file mode 120000 index 11b9d88..0000000 --- a/myenv/bin/python +++ /dev/null @@ -1 +0,0 @@ -python3.12 \ No newline at end of file diff --git a/myenv/bin/python3 b/myenv/bin/python3 deleted file mode 120000 index 11b9d88..0000000 --- a/myenv/bin/python3 +++ /dev/null @@ -1 +0,0 @@ -python3.12 \ No newline at end of file diff --git a/myenv/bin/python3.12 b/myenv/bin/python3.12 deleted file mode 120000 index a3f0508..0000000 --- a/myenv/bin/python3.12 +++ /dev/null @@ -1 +0,0 @@ -/opt/homebrew/opt/python@3.12/bin/python3.12 \ No newline at end of file diff --git a/myenv/pyvenv.cfg b/myenv/pyvenv.cfg deleted file mode 100644 index 2726b66..0000000 --- a/myenv/pyvenv.cfg +++ /dev/null @@ -1,5 +0,0 @@ -home = /opt/homebrew/opt/python@3.12/bin -include-system-site-packages = false -version = 3.12.5 -executable = /opt/homebrew/Cellar/python@3.12/3.12.5/Frameworks/Python.framework/Versions/3.12/bin/python3.12 -command = /opt/homebrew/opt/python@3.12/bin/python3.12 -m venv /Users/vaibhavgeek/kleo/backend/myenv From ffd9ac4eba3a419e6053d2a7525e2df749cfdb8c Mon Sep 17 00:00:00 2001 From: Vaibhav Maheshwari Date: Sun, 3 Nov 2024 04:37:19 +0530 Subject: [PATCH 03/12] remove all dead code --- app/__init__.py | 44 ++- app/celery/tasks.py | 3 - app/core/controllers/history.py | 68 ---- app/core/controllers/test.py | 471 ----------------------- app/core/models/aws_session.py | 14 - app/core/models/celery_tasks.py | 129 ------- app/core/models/user.py | 305 +-------------- app/core/models/visits.py | 98 ----- app/core/modules/category.py | 29 -- app/core/modules/history.py | 645 -------------------------------- 10 files changed, 46 insertions(+), 1760 deletions(-) delete mode 100644 app/core/controllers/history.py delete mode 100644 app/core/controllers/test.py delete mode 100644 app/core/models/aws_session.py delete mode 100644 app/core/models/celery_tasks.py delete mode 100644 app/core/models/visits.py delete mode 100644 app/core/modules/category.py delete mode 100644 app/core/modules/history.py diff --git a/app/__init__.py b/app/__init__.py index 5385fa6..3e93e23 100755 --- a/app/__init__.py +++ b/app/__init__.py @@ -1,7 +1,9 @@ from dotenv import load_dotenv from flask import Flask from flask_cors import CORS - +from flask_limiter import Limiter +from flask_limiter.util import get_remote_address +import redis def create_app(): # Load environment variables from .env file @@ -13,6 +15,27 @@ def create_app(): # Enable Cross-Origin Resource Sharing (CORS) for all API routes CORS(app, resources={r"/api/*": {"origins": "*"}}) + # Configure Redis for rate limiting + app.config['REDIS_URL'] = "redis://localhost:6379" + redis_client = redis.from_url(app.config['REDIS_URL']) + + # Initialize rate limiter + limiter = Limiter( + app=app, + key_func=get_remote_address, # Rate limit by IP address + default_limits=["200 per day", "50 per hour"], # Default limits for all routes + storage_uri=app.config['REDIS_URL'], + strategy="fixed-window" # Use fixed time windows for rate limiting + ) + + # Custom error handler for rate limit exceeded + @app.errorhandler(429) + def ratelimit_handler(e): + return { + "error": "Rate limit exceeded", + "retry_after": e.description + }, 429 + # Register all the blueprints register_blueprints(app) @@ -30,5 +53,22 @@ def register_blueprints(app): # Register blueprints with proper versioned URL prefixes app.register_blueprint( - core_user_v2, name="user_api_v2", url_prefix="/api/v2/core/user" + core_user_v2, + name="user_api_v2", + url_prefix="/api/v2/core/user" ) + + # Apply specific rate limits to blueprint endpoints + limiter = app.extensions['limiter'] + + # Example of applying different rate limits to different endpoints + limiter.limit("30/minute")(core_user_v2, "/get-user-graph/") + limiter.limit("20/minute")(core_user_v2, "/save-history") + limiter.limit("5/minute")(core_user_v2, "/create-user") + limiter.limit("10/minute")(core_user_v2, "/upload_activity_chart") + limiter.limit("60/minute")(core_user_v2, "/top-users") + + +if __name__ == '__main__': + app = create_app() + app.run(debug=True) \ No newline at end of file diff --git a/app/celery/tasks.py b/app/celery/tasks.py index 1d77238..5507016 100644 --- a/app/celery/tasks.py +++ b/app/celery/tasks.py @@ -2,11 +2,8 @@ get_most_relevant_activity, get_most_relevant_activity_for_batch, ) -from ..core.controllers.history import * from ..core.models.history import * from ..core.models.user import * -from ..core.models.celery_tasks import * -from ..core.models.visits import * from ..core.modules.upload import upload_to_arweave, prepare_history_json import redis from celery import shared_task diff --git a/app/core/controllers/history.py b/app/core/controllers/history.py deleted file mode 100644 index d35516c..0000000 --- a/app/core/controllers/history.py +++ /dev/null @@ -1,68 +0,0 @@ -import boto3 -from decimal import Decimal -from ..modules.history import single_url_request -import boto3 -import os -from datetime import datetime, timedelta - -AWS_ACCESS_KEY_ID = os.environ.get("API_KEY") -AWS_SECRET_ACCESS_KEY = os.environ.get("AWS_SECRET_ACCESS_KEY") -AWS_DEFAULT_REGION = os.environ.get("AWS_DEFAULT_REGION") -# Initialize a session using Amazon DynamoDB credentials. -session = boto3.Session( - aws_access_key_id=AWS_ACCESS_KEY_ID, - aws_secret_access_key=AWS_SECRET_ACCESS_KEY, - region_name=AWS_DEFAULT_REGION, -) - -# Create DynamoDB resource. -dynamodb = session.resource("dynamodb") - - -def domain_exists_or_insert(domain): - table = dynamodb.Table("domains") - response = table.query( - KeyConditionExpression=boto3.dynamodb.conditions.Key("domain").eq(domain) - ) - - if len(response["Items"]) > 0: - return response["Items"][0] - else: - category_group, category_description, category = single_url_request(domain) - item = { - "domain": domain, - "category_group": category_group, - "category_description": category_description, - "category": category, - } - table.put_item(Item=item) - return item - - -def convert_floats_to_decimal(item): - for key, value in item.items(): - if isinstance(value, float): - item[key] = Decimal(str(value)) - return item - - -def check_user_authenticity(user_address_from_ui, user_address_from_header): - return user_address_from_ui == user_address_from_header - - -# Example usage - - -def get_last_third_month_start_date(): - today = datetime.now() - # Calculate the starting date of the last third month - last_month_end_date = today.replace(day=1) - timedelta(days=1) - last_to_last_month_end_date = last_month_end_date - timedelta( - days=last_month_end_date.day - ) - last_to_last_to_last_month_end_date = last_to_last_month_end_date.replace( - day=1 - ) - timedelta(days=1) - starting_date_last_third_month = last_to_last_to_last_month_end_date.replace(day=1) - - return starting_date_last_third_month diff --git a/app/core/controllers/test.py b/app/core/controllers/test.py deleted file mode 100644 index c926571..0000000 --- a/app/core/controllers/test.py +++ /dev/null @@ -1,471 +0,0 @@ -import json -import boto3 - -# Sample history data -from decimal import Decimal -from boto3.dynamodb.conditions import Key, Attr -from datetime import datetime, timedelta - -import math - -import boto3 - - -class DecimalEncoder(json.JSONEncoder): - def default(self, obj): - if isinstance(obj, Decimal): - return float(obj) # or int(obj) if the context requires integer values - return super(DecimalEncoder, self).default(obj) - - -# Initialize a session using Amazon DynamoDB credentials. -session = boto3.Session( - aws_access_key_id="os.environ.get('AWS_ACCESS_KEY_ID')", - aws_secret_access_key="os.environ.get('AWS_SECRET_ACCESS_KEY')", - region_name="ap-south-1", -) - -# Create DynamoDB resource. -dynamodb = session.resource("dynamodb") - -from collections import defaultdict - - -# def get_hour_bracket(epoch_time): -# hour = datetime.utcfromtimestamp(epoch_time / 1000.0).hour # DynamoDB timestamp is in milliseconds -# if 0 <= hour < 4: -# return "00-04" -# elif 4 <= hour < 8: -# return "04-08" -# elif 8 <= hour < 12: -# return "08-12" -# elif 12 <= hour < 16: -# return "12-16" -# elif 16 <= hour < 20: -# return "16-20" -# else: -# return "20-24" - - -# def get_pinned_graph_view(user_id, domain): -# user_domain_key = f"{user_id}#{domain}" -# graph_data_pinned_table = dynamodb.Table('pinned_graph_data') -# now = datetime.now() -# one_year_from_now = now - timedelta(days=900) -# start_date = int(one_year_from_now.timestamp()) -# end_date = int(now.timestamp()) - -# try: -# response = graph_data_pinned_table.query( -# KeyConditionExpression=Key('domain_user_id').eq(user_domain_key) & -# Key('date').between(Decimal(start_date), Decimal(end_date)) -# ) -# print(start_date) -# print(end_date) -# items = response.get('Items', []) -# return items -# except Exception as e: -# print(f"Error querying table: {e}") -# return [] - - -# def process_items_pinned_data(user_id, pinned_domain, days_counter=365): -# now = datetime.now() -# now = datetime.combine(now, datetime.min.time()) -# date=now.timestamp() -# previous_timestamp = now - timedelta(days=days_counter) - -# start_timestamp = int(previous_timestamp.timestamp() * 1000) -# end_timestamp = int(now.timestamp() * 1000) -# table = dynamodb.Table('history') -# response = table.query( -# KeyConditionExpression=Key('user_id').eq(user_id) & -# Key('visitTime').between(Decimal(start_timestamp), Decimal(end_timestamp)), -# FilterExpression="contains(#url_attr, :domain_name)", -# ExpressionAttributeNames={ -# "#url_attr": "url" -# }, -# ExpressionAttributeValues={ -# ":domain_name": pinned_domain -# }) -# items = response['Items'] - -# while 'LastEvaluatedKey' in response: -# response = table.query( -# KeyConditionExpression=Key('user_id').eq(user_id) & -# Key('visitTime').between(Decimal(start_timestamp), Decimal(end_timestamp)), -# FilterExpression="contains(#url_attr, :domain_name)", -# ExpressionAttributeNames={ -# "#url_attr": "url" -# }, -# ExpressionAttributeValues={ -# ":domain_name": pinned_domain -# }, -# ExclusiveStartKey=response['LastEvaluatedKey']) -# items.extend(response['Items']) - - -# output = defaultdict(lambda: defaultdict(lambda: {"data": defaultdict(int)})) - -# for item in items: -# date_date = datetime.fromtimestamp(float(item["visitTime"]) / 1000.0) -# date_epoch = date_date.replace(hour=0, minute=0, second=0, microsecond=0) -# date_str = int(date_epoch.timestamp()) -# time_bracket = get_hour_bracket(float(item["visitTime"])) - -# user_id = item["user_id"] -# output[user_id][date_str]["data"][time_bracket] += 1 - -# # Convert the output to the desired format -# formatted_output = [] -# for user_id, dates in output.items(): -# for date, data in dates.items(): -# formatted_output.append({ -# "user_id": user_id, -# "date": date, -# "data": [{"time_bracket": tb, "visitCount": count} for tb, count in data["data"].items()] -# }) - -# graph_data_pinned_table = dynamodb.Table('pinned_graph_data') -# for record in formatted_output: -# user_domain_key = f"{record['user_id']}#{pinned_domain}" -# data_json = json.dumps(record['data']) # Convert the data to a JSON string - -# # Construct the item to insert -# item = { -# 'domain_user_id': user_domain_key, -# 'date': Decimal(record['date']), -# 'domain': pinned_domain, -# 'data': data_json -# } - -# graph_data_pinned_table.put_item(Item=item) -# return formatted_output - - -# # a = process_items_pinned_data("0x57e7b7f1c1a8782ac9d3c4d730051bd60068aeee", "docs.google.com") -# # print(get_pinned_graph_view("0x57e7b7f1c1a8782ac9d3c4d730051bd60068aeee", "docs.google.com")) -# # print(a) -# def process_data_by_timeframe(graph_data, timeframe): -# # Helper function to convert Unix timestamp to datetime -# def unix_to_datetime(unix_timestamp): -# if isinstance(unix_timestamp, Decimal): -# unix_timestamp = int(unix_timestamp) -# return datetime.datetime.utcfromtimestamp(unix_timestamp) - -# # Helper function to get the time key (week, day, hour, month) from a datetime object -# def get_time_key(dt, timeframe): -# if timeframe == 'daily': -# return dt.strftime('%Y-%m-%d') -# elif timeframe == 'weekly': -# return f"Week {dt.isocalendar()[1]}" -# elif timeframe == 'monthly': -# return dt.strftime('%Y-%m') -# else: -# raise ValueError("Invalid timeframe") - -# # Initialize the data structure -# organized_data = defaultdict(lambda: defaultdict(lambda: {"domains": [], "totalCategoryVisits": 0})) - -# # Process each record -# for record in graph_data: -# time_key = get_time_key(unix_to_datetime(record["date"]), timeframe) - -# for visit in record["data"]: -# category = f"Category: {visit['Category']}" -# domain_info = { -# "domain": visit["domain"], -# "icon": f"https://www.google.com/s2/favicons?domain={visit['domain']}&sz=48", -# "name": visit["domain"], -# "visitCounterTimeRange": visit["visit_count"] -# } - -# organized_data[time_key][category]["domains"].append(domain_info) -# organized_data[time_key][category]["totalCategoryVisits"] += visit["visit_count"] - -# # Convert defaultdict to regular dict for final output -# return {time_key: dict(categories) for time_key, categories in organized_data.items()} - -# Example usage: -# Replace `your_data` with the actual data fetched from DynamoDB -# timeframe = 'weekly' # Can be 'hourly', 'daily', 'weekly', or 'monthly' -# table = dynamodb.Table('graph_data') -# response = table.scan() -# items = response['Items'] -# print(len(items)) - -# items = items[0:5] -# print(items) - -# processed_data = process_data_by_timeframe(items, 'daily') -# print(json.dumps(processed_data, cls=DecimalEncoder)) - -# users_table = dynamodb.Table('users') - -# user_ids = [ -# '4a29cd40-7981-4969-beea-c712ef80a0d0', -# '5962973e-afc3-483f-a53c-fbecd49813f9', -# 'e09720d3-15cd-4b39-b9ca-e54534f3c31c', -# '4c5fce3c-38aa-4199-b72e-73f195c8ab6d', -# '05ecb209-8e92-4e2b-a2f0-c0d638f415ae', -# '7ab8833b-8f22-487f-9d5a-9fa561ffedd9' -# ] - -# # Use a batch writer to efficiently write multiple items to a DynamoDB table -# with users_table.batch_writer() as batch: -# for user_id in user_ids: -# batch.put_item( -# Item={ -# 'id': user_id, -# 'proccessed': False, -# 'verified': True, -# 'gitcoin_passport': False, - -# } -# ) - -# print("Batch write successful.") -# history_table = dynamodb.Table('history') # change to your table's name - -# # Placeholder for unique user IDs -# unique_user_ids = set() - -# # Scan the history_table for unique user IDs -# response = None -# while response is None or 'LastEvaluatedKey' in response: -# # If this is the first run, we don't have a LastEvaluatedKey yet -# if response is None: -# response = history_table.scan( -# ProjectionExpression="user_id", # Only retrieve the user_id field -# ) -# else: -# # Start the new scan where we left off -# response = history_table.scan( -# ProjectionExpression="user_id", -# ExclusiveStartKey=response['LastEvaluatedKey'] # Continue scanning from the previous point -# ) - -# for item in response['Items']: -# unique_user_ids.add(item['user_id']) - -# # At this point, unique_user_ids set contains all unique user IDs - -# # Now, if you want to scan the entire table, you can perform another scan without the ProjectionExpression. -# # This operation might be expensive in terms of read capacity units (RCUs) depending on the size of your table. - -# # Placeholder for the full items -# all_items = [] - -# # Scan the history_table for all items -# response = None -# while response is None or 'LastEvaluatedKey' in response: -# # If this is the first run, we don't have a LastEvaluatedKey yet -# if response is None: -# response = history_table.scan() -# else: -# # Start the new scan where we left off -# response = history_table.scan( -# ExclusiveStartKey=response['LastEvaluatedKey'] # Continue scanning from the previous point -# ) - -# all_items.extend(response['Items']) -# print(unique_user_ids) -# def delete_category(cat): -# table = dynamodb.Table('history') -# response = table.scan( -# FilterExpression="category = :category_val", -# ExpressionAttributeValues={":category_val": cat} -# ) -# print(response['Items']) - -# # Loop through the items and delete each one -# for item in response['Items']: -# print(f"Deleting item with user_id: {item['user_id']} and domain: {item['domain']}") -# table.delete_item( -# Key={ -# 'user_id': item['user_id'], -# 'visitTime': item['visitTime'] # Assuming domain is your sort key -# } -# ) - -# # Check for any remaining items (due to pagination in DynamoDB) -# while 'LastEvaluatedKey' in response: -# response = table.scan( -# FilterExpression="category = :category_val", -# ExpressionAttributeValues={":category_val": cat}, -# ExclusiveStartKey=response['LastEvaluatedKey'] -# ) - -# for item in response['Items']: -# print(f"Deleting item with user_id: {item['user_id']} and domain: {item['domain']}") -# table.delete_item( -# Key={ -# 'user_id': item['user_id'], -# 'visitTime': item['visitTime'] # Assuming domain is your sort key -# } -# ) - - -def delete_all_history_items(user_id): - table = dynamodb.Table("history") - - # Scan the table to get all items. - response = table.scan(FilterExpression=Attr("user_id").eq(user_id)) - - items = response["Items"] - counter = 0 - for item in items: - print(counter) - counter = counter + 1 - table.delete_item( - Key={"user_id": item["user_id"], "visitTime": item["visitTime"]} - ) - # Keep scanning until all items are fetched - while "LastEvaluatedKey" in response: - response = table.scan(ExclusiveStartKey=response["LastEvaluatedKey"]) - items.extend(response["Items"]) - - # Delete each item - counter = 0 - for item in items: - print(counter) - counter + 1 - table.delete_item( - Key={"user_id": item["user_id"], "visitTime": item["visitTime"]} - ) - - print(f"Deleted {len(items)} items from the history table.") - - -delete_all_history_items("0x86b06319b906e61631f7edbe5a3fe2edb95a3fae") -# Call the function to delete all items -# delete_category("Pornography") -# delete_category("Search Engines and Portals") -# Your list of dictionaries from the history table - -# Initialize the output data structure - - -# Sample history data - -# def get_domain(url): -# return url.split("//")[-1].split("/")[0].split("?")[0] - -# # Grouping by hours of the day -# def group_by_hour(timestamp): -# dt_object = datetime.utcfromtimestamp(timestamp/1000) # Convert to seconds -# hour = dt_object.hour -# if 0 <= hour < 4: -# return "00-04" -# elif 4 <= hour < 8: -# return "04-08" -# elif 8 <= hour < 12: -# return "08-12" -# elif 12 <= hour < 16: -# return "12-16" -# elif 16 <= hour < 20: -# return "16-20" -# elif 20 <= hour < 24: -# return "20-24" - -# # Grouping by days of the week -# def group_by_day(timestamp): -# dt_object = datetime.utcfromtimestamp(timestamp/1000) -# return dt_object.strftime('%A') - -# # Grouping by weeks of the month -# def group_by_week(timestamp): -# dt_object = datetime.utcfromtimestamp(timestamp/1000) -# day_of_month = dt_object.day -# week_of_month = math.ceil(day_of_month / 7.0) -# return f"Week {week_of_month}" - -# grouping_methods = { -# 'hour': group_by_hour, -# 'day': group_by_day, -# 'week': group_by_week -# } - -# def process_data(group_by, history_data): -# # Choose the grouping method based on the parameter -# group_function = grouping_methods[group_by] - -# # Empty output data -# output_data = {} - -# for entry in history_data: -# group_value = group_function(int(entry["lastVisitTime"])) -# category = entry["category"] -# domain = get_domain(entry["url"]) - -# if group_value not in output_data: -# output_data[group_value] = {} - -# if category not in output_data[group_value]: -# output_data[group_value][category] = { -# "domains": {}, -# "totalCategoryVisits": 0 -# } - -# if domain not in output_data[group_value][category]["domains"]: -# output_data[group_value][category]["domains"][domain] = 0 - -# output_data[group_value][category]["domains"][domain] += 1 -# output_data[group_value][category]["totalCategoryVisits"] += 1 - -# # Convert domain data to desired output format -# for group_value, categories in output_data.items(): -# for category, data in categories.items(): -# domains_list = [{"domain": k, "visitCounterTimeRange": v} for k, v in data["domains"].items()] -# output_data[group_value][category]["domains"] = domains_list - -# return output_data - -# # To use: -# def graph_query(group_by_parameter): -# table = dynamodb.Table('history') -# response = table.scan() -# history_data = response['Items'] -# result = process_data(group_by_parameter, history_data) -# return result - -# def update_history_items_by_user_id(user_id): -# table = dynamodb.Table('history') - -# # Scan the table to get all items for the given user_id. -# response = table.scan( -# FilterExpression=Attr('user_id').eq(user_id) -# ) -# items = response['Items'] - -# # Keep scanning until all items are fetched -# while 'LastEvaluatedKey' in response: -# response = table.scan( -# FilterExpression=Attr('user_id').eq(user_id), -# ExclusiveStartKey=response['LastEvaluatedKey'] -# ) -# items.extend(response['Items']) - -# # Update each item -# for item in items: -# print("update item with id: {}".format(item["id"])) -# # Here you can modify the item as needed, e.g.: -# # item['new_attribute'] = 'new_value' - -# # Call the update_item method to update the item in DynamoDB -# table.update_item( -# Key={ -# "user_id": item["user_id"], -# "visitTime": item["visitTime"] # Assuming 'visitTime' is the sort key -# }, -# UpdateExpression="SET user_id = :val", # Specify your update expression -# ExpressionAttributeValues={ -# ":val": "0x86B06319b906e61631f7edbe5A3fe2Edb95A3faE" # Provide the new value -# } -# ) -# print(f"Updated item with user_id: {item['user_id']} and visitTime: {item['visitTime']}") - -# print(f"Updated {len(items)} items in the history table for user_id: {user_id}.") - -# Call the function to update items for a specific user_id -# update_history_items_by_user_id('e09720d3-15cd-4b39-b9ca-e54534f3c31c') diff --git a/app/core/models/aws_session.py b/app/core/models/aws_session.py deleted file mode 100644 index cb29139..0000000 --- a/app/core/models/aws_session.py +++ /dev/null @@ -1,14 +0,0 @@ -# aws_session.py - -import boto3 -from .constants import * - -# Initialize a session using Amazon DynamoDB credentials. -session = boto3.Session( - aws_access_key_id=AWS_ACCESS_KEY_ID, - aws_secret_access_key=AWS_SECRET_ACCESS_KEY, - region_name=AWS_DEFAULT_REGION, -) - -# Create DynamoDB resource. -dynamodb = session.resource("dynamodb") diff --git a/app/core/models/celery_tasks.py b/app/core/models/celery_tasks.py deleted file mode 100644 index b82cd33..0000000 --- a/app/core/models/celery_tasks.py +++ /dev/null @@ -1,129 +0,0 @@ -from bson import ObjectId -import pymongo -from datetime import datetime -import os - -# MongoDB connection URI -mongo_uri = os.environ.get("DB_URL") -db_name = os.environ.get("DB_NAME") - -# Connect to MongoDB -client = pymongo.MongoClient(mongo_uri) -db = client.get_database(db_name) - - -class CeleryTask: - def __init__( - self, slug, task_id, type_, status, timestamp=int(datetime.now().timestamp()) - ): - assert isinstance(slug, str) - assert isinstance(task_id, str) - assert isinstance(type_, str) - assert isinstance(status, str) - assert isinstance(timestamp, int) - - self.document = { - "slug": slug, - "task_id": task_id, - "type_": type_, - "status": status, - "timestamp": timestamp, - } - - def save(self): - if find_by_slug_and_task_id(self.document["slug"], self.document["task_id"]): - return - db.celery.insert_one(self.document) - - -def get_celery_tasks_by_slug(slug): - """ - Retrieve all celery tasks for a given user slug. - - :param slug: The user's slug - :return: List of celery tasks - """ - pipeline = [ - {"$match": {"slug": slug}}, - { - "$project": { - "_id": {"$toString": "$_id"}, - "task_id": 1, - "type_": 1, - "status": 1, - "slug": 1, - "timestamp": 1, - } - }, - ] - print(pipeline) - tasks = list(db.celery.aggregate(pipeline)) - print(tasks) - return tasks - - -def get_all_celery_tasks(): - """ - Retrieve all celery tasks for all users. - - :return: List of all celery tasks - """ - pipeline = [ - { - "$project": { - "_id": {"$toString": "$_id"}, - "slug": 1, - "task_id": 1, - "type_": 1, - "status": 1, - "timestamp": 1, - } - } - ] - - tasks = list(db.celery.aggregate(pipeline)) - return tasks - - -def find_by_slug_and_task_id(slug, task_id): - """ - Find a specific celery task by slug and task_id. - - :param slug: The user's slug - :param task_id: The task ID - :return: The task document or None if not found - """ - task = db.celery.find_one({"slug": slug, "task_id": task_id}) - if task: - task["_id"] = str(task["_id"]) - return task - - -def update_celery_task_status(slug, task_id, new_status): - """ - Update the status of a celery task. If the new status is "SUCCESS", delete the task. - - :param slug: The user's slug - :param task_id: The task ID - :param new_status: The new status to set - :return: The updated task document, None if deleted, or None if not found - """ - if new_status == "SUCCESS": - # Delete the task if the status is SUCCESS - result = db.celery.delete_one({"slug": slug, "task_id": task_id}) - return None if result.deleted_count > 0 else None - else: - # Update the task status - updated_task = db.celery.find_one_and_update( - {"slug": slug, "task_id": task_id}, - { - "$set": { - "status": new_status, - "timestamp": int(datetime.now().timestamp()), - } - }, - return_document=pymongo.ReturnDocument.AFTER, - ) - if updated_task: - updated_task["_id"] = str(updated_task["_id"]) - return updated_task diff --git a/app/core/models/user.py b/app/core/models/user.py index 8fca5a8..3722f76 100644 --- a/app/core/models/user.py +++ b/app/core/models/user.py @@ -143,68 +143,6 @@ def update_activity_json(address, new_activity_json): return {} -def set_signup_upload_by_slug(slug): - try: - filter_query = {"slug": slug} - update_operation = {"$set": {"first_time_user": False}} - user_of_db = db.users.find_one_and_update( - filter_query, - update_operation, - projection={"_id": 0}, - return_document=pymongo.ReturnDocument.AFTER, - ) - return user_of_db - - except StopIteration as _: - return None - - except Exception as e: - print(e) - return {} - - -def find_by_slug(slug): - try: - pipeline = [ - {"$match": {"slug": slug}}, - {"$project": {"_id": 0, "address": 0}}, # Exclude the _id field - ] - user_of_db = db.users.aggregate(pipeline).next() - return user_of_db - - # TODO: Error Handling - # If an invalid ID is passed to `get_movie`, it should return None. - except StopIteration as _: - return None - - except Exception as e: - return {} - - -def find_by_address_slug_first_time(slug): - try: - pipeline = [{"$match": {"slug": slug}}] - user_of_db = db.users.aggregate(pipeline).next() - return user_of_db.get("address", "0x"), user_of_db.get("first_time_user", False) - except StopIteration as _: - return None - - -def find_by_address_slug(slug): - try: - pipeline = [{"$match": {"slug": slug}}] - user_of_db = db.users.aggregate(pipeline).next() - return user_of_db["address"] - - # TODO: Error Handling - # If an invalid ID is passed to `get_movie`, it should return None. - except StopIteration as _: - return None - - except Exception as e: - return {} - - def update_previous_hash(address, new_hash): try: filter_query = {"address": address} @@ -241,241 +179,6 @@ def find_by_address(address): except Exception as e: return {} - -def update_by_slug( - address, - slug, - stage, - name="", - verified=False, - about="", - pfp="", - content_tags=[], - identity_tags=[], - badges=[], - profile_metadata={}, -): - try: - filter_query = {"slug": slug} - update_operation = { - "$set": { - "address": address, - "name": name, - "slug": slug, - "stage": stage, - "verified": verified, - "about": about, - "pfp": pfp, - "content_tags": content_tags, - "identity_tags": identity_tags, - "badges": badges, - "profile_metadata": profile_metadata, - } - } - user_of_db = db.users.find_one_and_update( - filter_query, - update_operation, - projection={"_id": 0}, - return_document=pymongo.ReturnDocument.AFTER, - ) - return user_of_db - - # TODO: Error Handling - # If an invalid ID is passed to `get_movie`, it should return None. - except StopIteration as _: - return None - - except Exception as e: - print(e) - return {} - - -def update_settings_by_slug(slug, settings, stage, about): - try: - filter_query = {"slug": slug} - update_operation = { - "$set": {"settings": settings, "stage": stage, "about": about} - } - user_of_db = db.users.find_one_and_update( - filter_query, - update_operation, - projection={"_id": 0}, - return_document=pymongo.ReturnDocument.AFTER, - ) - return user_of_db - - # TODO: Error Handling - # If an invalid ID is passed to `get_movie`, it should return None. - except StopIteration as _: - return None - - except Exception as e: - print(e) - return {} - - -def fetch_user_slug(): - slug_from_db = db.users.find({}, {"slug": 1}) - user_slugs = [user["slug"] for user in slug_from_db if "slug" in user] - return user_slugs - - -def update_last_cards_marked(slug): - try: - db.users.update_one( - {"slug": slug}, - {"$set": {"last_cards_marked": int(datetime.now().timestamp())}}, - ) - - # TODO: Error Handling - # If an invalid ID is passed to `get_movie`, it should return None. - except StopIteration as _: - return None - - except Exception as e: - print(e) - return {} - - -def update_last_attested(slug): - try: - db.users.update_one( - {"slug": slug}, {"$set": {"last_attested": int(datetime.now().timestamp())}} - ) - except Exception as e: - print(e) - return {} - - -def update_minting_count(slug): - try: - pipeline = [{"$match": {"slug": slug}}] - - # Execute the pipeline and get the user - cursor = db.users.aggregate(pipeline) - user = next(cursor, None) - - if user: - user_profile_metadata = user.get("profile_metadata", {}) - mint_count = user_profile_metadata.get("mint_count", 0) - kleo_token = user_profile_metadata.get("kleo_token", 0) - tobe_release_tokens = user_profile_metadata.get("tobe_release_tokens", 0) - - if user_profile_metadata and mint_count: - mint_count_updated = int(mint_count) + 1 - user_profile_metadata["mint_count"] = mint_count_updated - else: - user_profile_metadata["mint_count"] = 1 - - if user_profile_metadata and tobe_release_tokens: - if kleo_token: - user_profile_metadata["kleo_token"] = ( - kleo_token + tobe_release_tokens - ) - else: - user_profile_metadata["kleo_token"] = tobe_release_tokens - user_profile_metadata["tobe_release_tokens"] = 0 - else: - if not kleo_token: - user_profile_metadata["kleo_token"] = 1 - - db.users.update_one( - {"slug": slug}, {"$set": {"profile_metadata": user_profile_metadata}} - ) - except Exception as e: - print(e) - return {} - - -def update_tobe_release_kleo_token(slug): - try: - pipeline = [{"$match": {"slug": slug}}] - - # Execute the pipeline and get the user - cursor = db.users.aggregate(pipeline) - user = next(cursor, None) - - if user: - user_profile_metadata = user.get("profile_metadata", {}) - tobe_release_tokens = user_profile_metadata.get("tobe_release_tokens", 0) - - if user_profile_metadata and tobe_release_tokens: - updated_tobe_release_tokens = int(tobe_release_tokens) + 1 - user_profile_metadata["tobe_release_tokens"] = ( - updated_tobe_release_tokens - ) - else: - user_profile_metadata["tobe_release_tokens"] = 1 - db.users.update_one( - {"slug": slug}, {"$set": {"profile_metadata": user_profile_metadata}} - ) - except Exception as e: - print(e) - return {} - - -def update_about_by_slug(slug, about): - try: - filter_query = {"slug": slug} - update_operation = {"$set": {"about": about}} - user_of_db = db.users.find_one_and_update( - filter_query, - update_operation, - projection={"_id": 0}, - return_document=pymongo.ReturnDocument.AFTER, - ) - return user_of_db - - # TODO: Error Handling - # If an invalid ID is passed to `get_movie`, it should return None. - except StopIteration as _: - return None - - except Exception as e: - print(e) - return {} - - -def get_all_users_with_count(): - try: - users = list(db.users.find({}, {"_id": 0})) - return users - except Exception as e: - print(f"An error occurred: {e}") - return [] - - -def update_kleo_points_for_user(slug): - try: - pipeline = [{"$match": {"slug": slug}}] - - # Execute the pipeline and get the user - cursor = db.users.aggregate(pipeline) - user = next(cursor, None) - - if user: - user_profile_metadata = user.get("profile_metadata", {}) - kleo_points_for_user = user_profile_metadata.get("kleo_points", 0) - kleo_token_of_user = user_profile_metadata.get("kleo_token", 0) - tobe_released_token_of_user = user_profile_metadata.get( - "tobe_release_tokens", 0 - ) - - if user_profile_metadata and kleo_points_for_user: - updated_kleo_points = int(kleo_points_for_user) + 1 - user_profile_metadata["kleo_points"] = updated_kleo_points - else: - user_profile_metadata["kleo_points"] = ( - int(kleo_token_of_user) + int(tobe_released_token_of_user) + 1 - ) - db.users.update_one( - {"slug": slug}, {"$set": {"profile_metadata": user_profile_metadata}} - ) - except Exception as e: - print(e) - return {} - - # Updates the PIIRemovedCount and TotalDataContributed Size in DB for an User. def update_user_data_by_address(address, pii_count, text_size): try: @@ -701,8 +404,8 @@ def update_referee_and_bonus(user_address, referee_address): # {"$inc": {"kleo_points": referral_bonus}} # ) - print( - f"Assigned referee {referee_address} to user {user_address}, added bonus, and updated referrals." - ) + # print( + # f"Assigned referee {referee_address} to user {user_address}, added bonus, and updated referrals." + # ) except Exception as e: - print(f"An error occurred while updating referral: {e}") + print(f"An error occurred while updating referral: {e}") \ No newline at end of file diff --git a/app/core/models/visits.py b/app/core/models/visits.py deleted file mode 100644 index 447f7ab..0000000 --- a/app/core/models/visits.py +++ /dev/null @@ -1,98 +0,0 @@ -from bson import ObjectId -import pymongo -from datetime import datetime, timedelta -import os - -# MongoDB connection URI -mongo_uri = os.environ.get("DB_URL") -db_name = os.environ.get("DB_NAME") - -# Connect to MongoDB -client = pymongo.MongoClient(mongo_uri) -db = client.get_database(db_name) - - -class Visits: - def __init__( - self, - slug, - category, - domain, - visitTime, - create_timestamp=int(datetime.now().timestamp()), - ): - assert isinstance(slug, str) - assert isinstance(create_timestamp, int) - assert isinstance(category, str) - assert isinstance(domain, str) - assert isinstance(visitTime, int) - - self.document = { - "slug": slug, - "create_timestamp": create_timestamp, - "category": category, - "domain": domain, - "visitTime": visitTime, - } - - def save(self): - if find_by_slug_and_time( - self.document["slug"], self.document["visitTime"], self.document["domain"] - ): - return - db.visits.insert_one(self.document) - - -def find_by_slug_and_time(slug, visitTime, domain): - try: - pipeline = [ - {"$match": {"slug": slug, "visitTime": visitTime, "domain": domain}}, - {"$project": {"_id": 0}}, # Exclude the _id field - ] - user_of_db = db.visits.aggregate(pipeline).next() - return user_of_db - except StopIteration as _: - return None - - except Exception as e: - return {} - - -def fetch_visits_for_week(slug, start_date, end_date): - pipeline = [ - { - "$match": { - "visitTime": { - "$gte": int(start_date.timestamp()), - "$lte": int(end_date.timestamp()), - }, - "slug": slug, - } - }, - {"$group": {"_id": "$domain", "count": {"$sum": 1}}}, - ] - return {doc["_id"]: doc["count"] for doc in db.visits.aggregate(pipeline)} - - -def fetch_visits_for_last_15_days(slug): - today = datetime.today() - start_date = (today - timedelta(days=15)).replace( - hour=0, minute=0, second=0, microsecond=0 - ) - end_date = today.replace(hour=23, minute=59, second=59, microsecond=999999) - - pipeline = [ - { - "$match": { - "visitTime": { - "$gte": int(start_date.timestamp()), - "$lte": int(end_date.timestamp()), - }, - "slug": slug, - } - }, - {"$group": {"_id": "$category", "count": {"$sum": 1}}}, - {"$sort": {"count": -1}}, - {"$limit": 8}, - ] - return list(db.visits.aggregate(pipeline)) diff --git a/app/core/modules/category.py b/app/core/modules/category.py deleted file mode 100644 index aac19eb..0000000 --- a/app/core/modules/category.py +++ /dev/null @@ -1,29 +0,0 @@ -import requests -from bs4 import BeautifulSoup as bs -import json -from urllib.parse import urlparse -import time - - -def get_category(raw_resp): - soup = bs(raw_resp.text) - result = soup.find("div", {"id": "webfilter-result"}) - paragraph = result.select_one("div > p").getText() - main_result = result.find("h4", {"class": "info_title"}) - category_description = paragraph.split("Group:")[0] - category_group = paragraph.split("Group:")[1] - category = main_result.getText() - time.sleep(1) - - return category_group, category_description, category - - -def single_url_request(main_url, item): - url = "https://www.fortiguard.com/webfilter" - payload = {"url": main_url} - response = requests.request("POST", url, headers={}, data=payload, files=[]) - category_group, category_description, category = get_category(response) - item["category_group"] = category_group - item["category_description"] = category_description - item["category"] = category - return item diff --git a/app/core/modules/history.py b/app/core/modules/history.py deleted file mode 100644 index e483985..0000000 --- a/app/core/modules/history.py +++ /dev/null @@ -1,645 +0,0 @@ -import logging -import math - -logging.basicConfig(level=logging.ERROR) - -from datetime import timedelta -from app.core.models.visits import fetch_visits_for_last_15_days, fetch_visits_for_week -from ..models.history import * - -import requests -import json -import openai -import os -from pydantic_core import from_json - -from pydantic import BaseModel -import time - - -class CardObject(BaseModel): - activity: str - description: str - tags: list - titles: list - - -categories_to_exclude = [ - "Abortion", - "Alcohol", - "Marijuana", - "Nudity and Risque", - "Other Adult Materials", - "Pornography", - "Tobacco", - "Weapons (Sales)", - "Child Sexual Abuse", - "Discrimination", - "Drug Abuse", - "Explicit Violence", - "Extremist Groups", - "Illegal or Unethical", - "Plagiarism", - "Potentially Unwanted Program", - "Terrorism", - "Malicious Websites", - "Phishing", - "Spam URLs", - "Web-based Email", - "Web Chat", - "Online Meeting", - "Instant Messaging", - "File Sharing and Storage", -] - -tags = { - "Lifestyle": [ - "Dating", - "Gambling", - "Lingerie and Swimsuit", - "Sports Hunting and War Games", - "Health and Wellness", - "Restaurant and Dining", - "Shopping", - "Society and Lifestyles", - "Travel", - ], - "Entertainment": [ - "Internet Radio and TV", - "Streaming Media and Download", - "Arts and Culture", - "Entertainment", - "Folklore", - "Games", - "Global Religion", - ], - "Education & Beliefs": [ - "Advocacy Organizations", - "Alternative Beliefs", - "Sex Education", - "Child Education", - "Education", - "Reference", - ], - "Technology": [ - "File Sharing and Storage", - "Freeware and Software Downloads", - "Internet Telephony", - "Peer-to-peer File Sharing", - "Artificial Intelligence Technology", - "Information Technology", - "Information and Computer Security", - "Remote Access", - "Search Engines and Portals", - "Secure Websites", - "URL Shortening", - "Web Analytics", - "Web Hosting", - "Web-based Applications", - "Dynamic Content", - "Crypto Mining", - "Hacking", - "Proxy Avoidance", - "Dynamic DNS", - ], - "Business & Finance": [ - "Business", - "Charitable Organizations", - "Cryptocurrency", - "Finance and Banking", - "Auction", - "Brokerage and Trading", - "Job Search", - "Real Estate", - ], - "Government": [ - "Armed Forces", - "General Organizations", - "Government and Legal Organizations", - "Political Organizations", - ], - "Media & Communication": [ - "Advertising", - "Content Servers", - "Digital Postcards", - "Domain Parking", - "News and Media", - "Newsgroups and Message Boards", - "Personal Websites and Blogs", - "Social Networking", - ], - "Personal": ["Personal Privacy", "Personal Vehicles", "Meaningless Content"], - "Health & Medicine": ["Medicine"], - "Miscellaneous": ["Newly Observed Domain", "Newly Registered Domain", "Not Rated"], -} - - -def get_tags_from_category(tag_map, category): - for tag, cats in tag_map.items(): - if category in cats: - return tag - return "Miscellaneous" - - -keys_to_keep = ["visitTime", "category", "title", "url", "domain", "id"] - - -# Function to clean individual item -def clean_item(item): - cleaned_item = {key: item[key] for key in keys_to_keep if key in item} - return ( - cleaned_item if cleaned_item["category"] not in categories_to_exclude else None - ) - - -# def get_category(raw_resp): -# try: -# soup = bs(raw_resp.text, 'html.parser') -# result = soup.find("div", {"id": "webfilter-result"}) -# if result is None: -# raise ValueError("Could not find the 'webfilter-result' div in the response.") -# paragraph = result.select_one("div > p") -# if paragraph is None: -# raise ValueError("Could not find the paragraph element within the 'webfilter-result' div.") -# main_result = result.find("h4", {"class": "info_title"}) -# if main_result is None: -# raise ValueError("Could not find the 'info_title' element within the 'webfilter-result' div.") -# category_description = paragraph.getText().split("Group:")[0].strip() -# category_group = paragraph.getText().split("Group:")[1].strip() -# category = main_result.getText().split("Category:")[1].strip() -# return category_group, category_description, category -# except (AttributeError, IndexError) as e: -# print(f"Error occurred while parsing the response: {str(e)}") -# return "Other", "Unknown", "Other" -# except ValueError as e: -# print(str(e)) -# return "Other", "Unknown", "Other" -# except Exception as e: -# print(f"An unexpected error occurred: {str(e)}") -# return "Other", "Unknown", "Other" - - -# def single_url_request(domain): -# try: -# url = "https://www.fortiguard.com/webfilter" -# payload = {'url': domain} -# response = requests.request("POST", url, headers={}, data=payload, files=[]) -# print(response.text) -# return get_category(response) -# except requests.exceptions.RequestException as e: -# print(f"Error occurred while making request to {url}: {str(e)}") -# return None -# except Exception as e: -# print(f"An unexpected error occurred: {str(e)}") -# return None - - -def single_url_request(domain): - try: - url = f"https://website-categorization-api-now-with-ai.p.rapidapi.com/website-categorization/{domain}" - headers = { - "X-RapidAPI-Key": "Os4X7YlgE2mshuPlMvD8ROAkCNApp1Uhbqpjsnno2qXlvgJ0gW", - "X-RapidAPI-Host": "website-categorization-api-now-with-ai.p.rapidapi.com", - } - response = requests.get(url, headers=headers) - response_json = response.json() - - if "categories" in response_json: - categories = response_json["categories"] - if len(categories) > 0: - highest_confidence_category = max( - categories, key=lambda x: x["confidence"] - ) - return ( - highest_confidence_category["name"], - "", - highest_confidence_category["name"], - ) - else: - return "Other", "Unknown", "Other" - else: - return "Other", "Unknown", "Other" - except requests.exceptions.RequestException as e: - print(f"Error occurred while making request to {url}: {str(e)}") - return None - except Exception as e: - print(f"An unexpected error occurred: {str(e)}") - return None - - -def create_pending_cards(slug): - if datetime.today().weekday() == 0: # Check if today is Monday - last_week_start, last_week_end = get_date_range(1) - last_to_last_week_start, last_to_last_week_end = get_date_range(2) - - last_week_visits = fetch_visits_for_week(slug, last_week_start, last_week_end) - last_to_last_week_visits = fetch_visits_for_week( - slug, last_to_last_week_start, last_to_last_week_end - ) - - deviations = calculate_deviation(last_week_visits, last_to_last_week_visits) - top_domains = sorted( - deviations.items(), key=lambda item: item[1], reverse=True - )[:3] - - for domain, deviation in top_domains: - last_week_count = last_week_visits[domain] - last_to_last_week_count = last_to_last_week_visits.get(domain, 0) - create_visit_count_card( - slug, - domain, - deviation, - last_week_count, - last_to_last_week_count, - format_date_range( - int(last_week_start.timestamp()), int(last_week_end.timestamp()) - ), - ) - - today = datetime.today() - if today.day == 1 or today.day == 15: - start_date = (today - timedelta(days=15)).replace( - hour=0, minute=0, second=0, microsecond=0 - ) - end_date = today.replace(hour=23, minute=59, second=59, microsecond=999999) - - top_domains = fetch_visits_for_last_15_days(slug) - if top_domains: - create_visit_chart_card(slug, top_domains, start_date, end_date) - - history_from_db = get_history_item(slug) - print("Step 1") - if not history_from_db: - return - cluster_history_list = cluster_and_save(history_from_db) - print("Step 2") - if not cluster_history_list: - return - response_from_llm = create_card_from_llm(slug, cluster_history_list) - print(response_from_llm) - return response_from_llm - - -def cluster_and_save(data): - # Prepare the result structure - # Clean the data and remove duplicates based on title - titles_seen = set() - cleaned_data = [] - final_data = {} - categories_json = {} - - for item in data: - cleaned_item = clean_item(item) - if cleaned_item and cleaned_item["title"] not in titles_seen: - titles_seen.add(cleaned_item["title"]) - cleaned_data.append(cleaned_item) - - if cleaned_item and cleaned_item["category"] in categories_json: - categories_json[cleaned_item["category"]] += 1 - elif cleaned_item: - categories_json[cleaned_item["category"]] = 1 - - # Determine the new file name - final_data["items"] = cleaned_data - final_data["frequency"] = categories_json - - return final_data - - -def message_from_LLM_API( - initial_prompt, - model_name, - prompt, - temperature, - base_url, - api_key, - service, - max_tokens=200, -): - max_retries = 3 - retry_delay = 600 # seconds - - for attempt in range(max_retries): - try: - if service == "azure": - headers = {"Content-Type": "application/json", "api-key": f"{api_key}"} - data = { - "messages": [ - {"role": "system", "content": initial_prompt}, - {"role": "user", "content": prompt}, - ], - "response_format": {"type": "json_object"}, - "max_tokens": max_tokens, - "temperature": temperature, - "top_p": 0.8, - } - response = requests.post(base_url, headers=headers, json=data) - response_json = response.json() - - if ( - "error" in response_json - and response_json["error"].get("code") == "429" - ): - if attempt < max_retries - 1: # don't sleep on the last attempt - logging.warning( - f"Rate limit exceeded. Retrying in {retry_delay} seconds... (Attempt {attempt + 1}/{max_retries})" - ) - time.sleep(retry_delay) - continue - else: - logging.info(f"Azure API response: {response_json}") - return response_json - - elif service == "ansycale": - client = openai.OpenAI(base_url=base_url, api_key=api_key) - chat_completion = client.chat.completions.create( - model=model_name, - messages=[ - {"role": "system", "content": initial_prompt}, - {"role": "user", "content": prompt}, - ], - temperature=temperature, - ) - logging.info(f"Ansycale API response: {chat_completion}") - return chat_completion.choices[0].message.content - - except requests.exceptions.RequestException as e: - if attempt < max_retries - 1: - logging.error( - f"Request failed. Retrying in {retry_delay} seconds... (Attempt {attempt + 1}/{max_retries})" - ) - logging.error(f"Error details: {str(e)}") - time.sleep(retry_delay) - else: - logging.error(f"All retry attempts failed. Last error: {str(e)}") - raise - - # If we've exhausted all retries, return the last error response - logging.error(f"All retry attempts failed. Last response: {response_json}") - return response_json - - -def get_category_cards(data, num_cards): - frequency_data = data["frequency"] - total_frequency = sum(frequency_data.values()) - category_ratios = { - category: (freq / total_frequency) * num_cards - for category, freq in frequency_data.items() - } - category_cards = {} - for category, ratio in category_ratios.items(): - if category in ["Social Networking", "Streaming Media and Download"]: - category_cards[category] = max( - 0, math.floor(ratio) - ) # Ensure a minimum count of 0 - else: - category_cards[category] = math.ceil(ratio) - - while sum(category_cards.values()) != num_cards: - if sum(category_cards.values()) < num_cards: - max_diff_category = max( - category_ratios, key=lambda x: category_ratios[x] - category_cards[x] - ) - category_cards[max_diff_category] += 1 - else: - min_diff_category = min( - category_ratios, - key=lambda x: ( - category_cards[x] - category_ratios[x] - if category_cards[x] > 0 - else float("inf") - ), - ) - category_cards[min_diff_category] -= 1 - - return category_cards - - -def get_titles_and_items_by_category(data, category): - titles = [] - items = [] - for item in data["items"]: - if item["category"] == category: - titles.append(item["title"]) - items.append(item) - - return titles, items - - -def generate_results(slug, items, initial_prompt, input_service, max_tokens=100): - cards_main = [] - prompt = "" - for item in items: - prompt += json.dumps({"title": item["title"], "domain": item["domain"]}) + "\n" - - num_tokens = len(prompt) // 4 - if num_tokens > 4000: - return - - bot_response = message_from_LLM_API( - initial_prompt=initial_prompt, - model_name="mistralai/Mixtral-8x7B-Instruct-v0.1", - prompt=prompt, - temperature=0.8, - base_url=os.environ.get("OPEN_AI_BASE_URL"), - api_key=os.environ.get("OPEN_AI_API_KEY"), - service=input_service, - max_tokens=max_tokens, - ) - print(bot_response) - if ( - "choices" in bot_response - and len(bot_response["choices"]) > 0 - and "message" in bot_response["choices"][0] - and "content" in bot_response["choices"][0]["message"] - ): - response_text_json = from_json( - bot_response["choices"][0]["message"]["content"], allow_partial=True - ) - if isinstance(response_text_json, dict): - response_text_json = [response_text_json] - else: - response_text_json = [] - - print(response_text_json) - if response_text_json is not None and len(response_text_json) > 0: - for card_data in response_text_json: - try: - validated_card_data = CardObject.model_validate(card_data) - except ValidationError as e: - logging.error( - f"Validation error for card data in slug: {slug}. Error: {str(e)}" - ) - logging.error(f"Problematic card data: {card_data}") - continue # Skip this card and continue with the next one - - items_list = [] - for item in items: - if "titles" in validated_card_data.dict() and item["title"].lower() in [ - title.lower() for title in validated_card_data.titles - ]: - items_list.append( - {"title": item["title"], "url": item["url"], "id": item["id"]} - ) - - card = { - "cardType": "DataCard", - "content": validated_card_data.description, - "metadata": validated_card_data.dict(), - "tags": validated_card_data.tags, - "urls": items_list, - } - - try: - pendingCard = PendingCard( - slug, - "DataCard", - validated_card_data.description, - validated_card_data.tags, - items_list, - validated_card_data.dict(), - get_tags_from_category(tags, items[0]["category"]), - ) - pendingCard.save() - for item in items_list: - cards_main.append(card) - except Exception as e: - logging.error( - f"Error while saving or processing PendingCard for slug: {slug}. Error: {str(e)}" - ) - - return cards_main - - -def create_card_from_llm(slug, data): - - initial_prompt_single_card = """ - Pick one specific context from the history having at maximum 4 titles, ignore other items. - The JSON strictly conforms to this schema. - {{ - "activity" : verb, - "tags": [2-3 categories] - "description": describe one-two-line motive, reason or interest for @{slug} - "titles": [related titles to this context] - }} - Use past tense for verbs - """.format( - slug=slug - ) - - initial_prompt_multiple_card = """ - The JSON object strictly conforms to this schema. - {{ - "activity" : verb, - "tags": [2-3 categories] - "description": describe one-two-line motive, reason or interest for @{slug} - "titles": [related titles in this cluster context] - }} - Use past tense for verbs - """.format( - slug=slug - ) - - number_of_cards_category = get_category_cards(data, 15) - final_results = [] - for category, num_cards in number_of_cards_category.items(): - if num_cards > 0: - if num_cards == 1: - titles, items = get_titles_and_items_by_category( - data, category=category - ) - res = generate_results( - slug, items, initial_prompt_single_card, "azure", 200 - ) - final_results.append(res) - if num_cards >= 2: - initial_prompt_multiple_card += "Create {} clusters based on specific context from given titles, for EACH cluster create a JSON object".format( - str(num_cards) - ) - titles, items = get_titles_and_items_by_category( - data, category=category - ) - res = generate_results( - slug, items, initial_prompt_multiple_card, "azure", 200 * num_cards - ) - final_results.append(res) - if len(final_results) > 0: - delete_all_history(slug) - return final_results - - -def get_date_range(weeks_ago=0): - today = datetime.today() - start_date = (today - timedelta(days=today.weekday() + 7 * weeks_ago)).replace( - hour=0, minute=0, second=0, microsecond=0 - ) - end_date = (start_date + timedelta(days=6)).replace( - hour=23, minute=59, second=59, microsecond=999999 - ) - return start_date, end_date - - -def format_date_range(start_epoch, end_epoch): - # Convert epoch to datetime objects - start_date = datetime.fromtimestamp(start_epoch) - end_date = datetime.fromtimestamp(end_epoch) - - # Format the dates - start_date_str = start_date.strftime("%d %b") - end_date_str = end_date.strftime("%d %b") - - # Return the formatted date range - return f"{start_date_str} - {end_date_str}" - - -def calculate_deviation(last_week, last_to_last_week): - deviation = {} - for domain in last_week: - last_week_count = last_week[domain] - last_to_last_week_count = last_to_last_week.get(domain, 0) - deviation[domain] = abs(last_week_count - last_to_last_week_count) - return deviation - - -def create_visit_count_card( - slug, domain, deviation, last_week_count, last_to_last_week_count, date_range -): - description = f"{'increased' if last_week_count > last_to_last_week_count else 'decreased'} in visiting {domain}" - activity_percentage = round( - (deviation / (last_to_last_week_count if last_to_last_week_count else 1)) * 100, - 0, - ) - activity = [ - "increased" if last_week_count > last_to_last_week_count else "decreased" - ] - if activity_percentage > 0: - pendingCard = PendingCard( - slug, - "DomainVisitCard", - description, - [str(activity_percentage) + "%", activity, date_range], - [{"title": "", "url": domain}], - {"activity": [activity_percentage, activity], "description": domain}, - "Miscellaneous", - ) - pendingCard.save() - - -def create_visit_chart_card(slug, domains_data, start_date, end_date): - activity = [ - {"category": domain["_id"], "count": domain["count"]} for domain in domains_data - ] - pendingCard = PendingCard( - slug, - "VisitChartCard", - "", - [], - [], - { - "activity": activity, - "dateFrom": int(start_date.timestamp()), - "dateTo": int(end_date.timestamp()), - }, - "Miscellaneous", - ) - pendingCard.save() From 33e4849d56fec76db823f55256695f935f0c72ea Mon Sep 17 00:00:00 2001 From: Vaibhav Maheshwari Date: Sun, 3 Nov 2024 04:40:49 +0530 Subject: [PATCH 04/12] fix: remove all that is not used --- .../classifier.py} | 0 .../{userDataComputation => compute}/pii.py | 4 -- app/celery/tasks.py | 46 +------------------ 3 files changed, 2 insertions(+), 48 deletions(-) rename app/celery/{userDataComputation/activityClassification.py => compute/classifier.py} (100%) rename app/celery/{userDataComputation => compute}/pii.py (70%) diff --git a/app/celery/userDataComputation/activityClassification.py b/app/celery/compute/classifier.py similarity index 100% rename from app/celery/userDataComputation/activityClassification.py rename to app/celery/compute/classifier.py diff --git a/app/celery/userDataComputation/pii.py b/app/celery/compute/pii.py similarity index 70% rename from app/celery/userDataComputation/pii.py rename to app/celery/compute/pii.py index 007b2ee..5ada1ff 100644 --- a/app/celery/userDataComputation/pii.py +++ b/app/celery/compute/pii.py @@ -5,17 +5,13 @@ def remove_pii(text): - # Initialize Presidio engines for PII detection and anonymization analyzer = AnalyzerEngine() anonymizer = AnonymizerEngine() - # Step 1: Analyze the text for PII entities results = analyzer.analyze(text=text, entities=[], language="en") - # Anonymize the text based on detected PII and the anonymization configuration anonymized_result = anonymizer.anonymize(text=text, analyzer_results=results) - # Extract the anonymized text from the EngineResult object anonymized_text = anonymized_result.text pii_pattern = r"<(.*?)>" diff --git a/app/celery/tasks.py b/app/celery/tasks.py index 5507016..38467cb 100644 --- a/app/celery/tasks.py +++ b/app/celery/tasks.py @@ -1,4 +1,4 @@ -from app.celery.userDataComputation.activityClassification import ( +from app.celery.compute.classifier import ( get_most_relevant_activity, get_most_relevant_activity_for_batch, ) @@ -47,46 +47,6 @@ def update_user_graph_cache(self, userAddress): -def send_telegram_message(slug, body): - tg_token_api = os.environ.get("TELEGRAM_API_TOKEN") - channel_id = "-1002178791722" # The channel ID you provided - - subject = f"Activity for Slug: {slug}" - message = f"```{json.dumps(body, indent=2)}```" - - # Send the message - telegram_api_url = f"https://api.telegram.org/bot{tg_token_api}/sendMessage" - - payload = { - "chat_id": channel_id, - "text": f"{subject}\n\n{message}", - "parse_mode": "Markdown", - } - - try: - response = requests.post(telegram_api_url, json=payload) - if response.status_code == 200: - print(f"Telegram message sent successfully for slug: {slug}") - else: - print( - f"Failed to send Telegram message for slug: {slug}. Status code: {response.status_code}" - ) - except Exception as e: - print(f"Failed to send Telegram message for slug: {slug}. Error: {str(e)}") - - -@shared_task( - bind=True, - base=AbortableTask, - ack_later=True, - default_retry_delay=20, - max_retries=2, - queue="send-email", -) -def send_telegram_notification(self, slug, response): - send_telegram_message(slug, response) - - @shared_task( bind=True, base=AbortableTask, @@ -107,9 +67,7 @@ def contextual_activity_classification(self, item, address): if not user: print(f"User with address {address} not found") return - - - print(item) + activity_json = get_activity_json(address) history_entry = History( address=address, From d97c8cff1244ad3cc69710ecbcf87b778bb2ca9f Mon Sep 17 00:00:00 2001 From: Vaibhav Maheshwari Date: Sun, 3 Nov 2024 04:49:23 +0530 Subject: [PATCH 05/12] fix: rate limiting for every IP --- app/__init__.py | 64 ++++++++++++------------------------------------- 1 file changed, 15 insertions(+), 49 deletions(-) diff --git a/app/__init__.py b/app/__init__.py index 3e93e23..5d4cfa6 100755 --- a/app/__init__.py +++ b/app/__init__.py @@ -1,74 +1,40 @@ from dotenv import load_dotenv -from flask import Flask +from flask import Flask,jsonify from flask_cors import CORS + from flask_limiter import Limiter from flask_limiter.util import get_remote_address -import redis +from flask_limiter.errors import RateLimitExceeded + def create_app(): - # Load environment variables from .env file load_dotenv() - # Initialize Flask app with a descriptive name app = Flask("KLEO-NETWORK") - # Enable Cross-Origin Resource Sharing (CORS) for all API routes CORS(app, resources={r"/api/*": {"origins": "*"}}) - - # Configure Redis for rate limiting - app.config['REDIS_URL'] = "redis://localhost:6379" - redis_client = redis.from_url(app.config['REDIS_URL']) - - # Initialize rate limiter limiter = Limiter( - app=app, - key_func=get_remote_address, # Rate limit by IP address - default_limits=["200 per day", "50 per hour"], # Default limits for all routes - storage_uri=app.config['REDIS_URL'], - strategy="fixed-window" # Use fixed time windows for rate limiting + app, + key_func=get_remote_address, + default_limits=["200 per day", "50 per hour"] # Adjust limits as needed ) + @app.errorhandler(RateLimitExceeded) + def rate_limit_handler(e): + return jsonify(error="Rate limit exceeded. Please try again later."), 429 - # Custom error handler for rate limit exceeded - @app.errorhandler(429) - def ratelimit_handler(e): - return { - "error": "Rate limit exceeded", - "retry_after": e.description - }, 429 - - # Register all the blueprints - register_blueprints(app) + register_blueprints(app, limiter) return app -def register_blueprints(app): +def register_blueprints(app, limiter): """ Function to register all blueprints to the Flask app. Keeps the create_app function clean and modular. """ - - # Import blueprints from .core.views.user_v2_views import core as core_user_v2 - - # Register blueprints with proper versioned URL prefixes + + limiter.limit("100 per hour")(core_user_v2) app.register_blueprint( - core_user_v2, - name="user_api_v2", - url_prefix="/api/v2/core/user" + core_user_v2, name="user_api_v2", url_prefix="/api/v2/core/user" ) - - # Apply specific rate limits to blueprint endpoints - limiter = app.extensions['limiter'] - - # Example of applying different rate limits to different endpoints - limiter.limit("30/minute")(core_user_v2, "/get-user-graph/") - limiter.limit("20/minute")(core_user_v2, "/save-history") - limiter.limit("5/minute")(core_user_v2, "/create-user") - limiter.limit("10/minute")(core_user_v2, "/upload_activity_chart") - limiter.limit("60/minute")(core_user_v2, "/top-users") - - -if __name__ == '__main__': - app = create_app() - app.run(debug=True) \ No newline at end of file From df79161b449c8df3b255145d0dffe671b4cf6329 Mon Sep 17 00:00:00 2001 From: Vaibhav Maheshwari Date: Sun, 3 Nov 2024 06:12:30 +0530 Subject: [PATCH 06/12] fix: tested api in local --- app/__init__.py | 4 +- app/celery/tasks.py | 3 - app/core/views/user_v2_views.py | 4 +- backend/bin/Activate.ps1 | 247 +++++++++++++++++++++++++++++ backend/bin/activate | 70 ++++++++ backend/bin/activate.csh | 27 ++++ backend/bin/activate.fish | 69 ++++++++ backend/bin/celery | 8 + backend/bin/convert-caffe2-to-onnx | 8 + backend/bin/convert-onnx-to-caffe2 | 8 + backend/bin/dotenv | 8 + backend/bin/f2py | 8 + backend/bin/flask | 8 + backend/bin/gunicorn | 8 + backend/bin/huggingface-cli | 8 + backend/bin/isympy | 8 + backend/bin/markdown-it | 8 + backend/bin/nltk | 8 + backend/bin/normalizer | 8 + backend/bin/numpy-config | 8 + backend/bin/pip | 8 + backend/bin/pip3 | 8 + backend/bin/pip3.12 | 8 + backend/bin/pygmentize | 8 + backend/bin/python | 1 + backend/bin/python3 | 1 + backend/bin/python3.12 | 1 + backend/bin/spacy | 8 + backend/bin/tldextract | 8 + backend/bin/torchfrtrace | 8 + backend/bin/torchrun | 8 + backend/bin/tqdm | 8 + backend/bin/transformers-cli | 8 + backend/bin/typer | 8 + backend/bin/weasel | 8 + backend/pyvenv.cfg | 5 + backend/share/man/man1/isympy.1 | 188 ++++++++++++++++++++++ docker-compose.yml | 8 +- requirements.txt | 203 ++++++++---------------- 39 files changed, 882 insertions(+), 149 deletions(-) create mode 100644 backend/bin/Activate.ps1 create mode 100644 backend/bin/activate create mode 100644 backend/bin/activate.csh create mode 100644 backend/bin/activate.fish create mode 100755 backend/bin/celery create mode 100755 backend/bin/convert-caffe2-to-onnx create mode 100755 backend/bin/convert-onnx-to-caffe2 create mode 100755 backend/bin/dotenv create mode 100755 backend/bin/f2py create mode 100755 backend/bin/flask create mode 100755 backend/bin/gunicorn create mode 100755 backend/bin/huggingface-cli create mode 100755 backend/bin/isympy create mode 100755 backend/bin/markdown-it create mode 100755 backend/bin/nltk create mode 100755 backend/bin/normalizer create mode 100755 backend/bin/numpy-config create mode 100755 backend/bin/pip create mode 100755 backend/bin/pip3 create mode 100755 backend/bin/pip3.12 create mode 100755 backend/bin/pygmentize create mode 120000 backend/bin/python create mode 120000 backend/bin/python3 create mode 120000 backend/bin/python3.12 create mode 100755 backend/bin/spacy create mode 100755 backend/bin/tldextract create mode 100755 backend/bin/torchfrtrace create mode 100755 backend/bin/torchrun create mode 100755 backend/bin/tqdm create mode 100755 backend/bin/transformers-cli create mode 100755 backend/bin/typer create mode 100755 backend/bin/weasel create mode 100644 backend/pyvenv.cfg create mode 100644 backend/share/man/man1/isympy.1 diff --git a/app/__init__.py b/app/__init__.py index 5d4cfa6..4dace27 100755 --- a/app/__init__.py +++ b/app/__init__.py @@ -14,9 +14,9 @@ def create_app(): CORS(app, resources={r"/api/*": {"origins": "*"}}) limiter = Limiter( - app, key_func=get_remote_address, - default_limits=["200 per day", "50 per hour"] # Adjust limits as needed + app=app, + default_limits=["200 per day", "50 per hour"] ) @app.errorhandler(RateLimitExceeded) def rate_limit_handler(e): diff --git a/app/celery/tasks.py b/app/celery/tasks.py index 38467cb..0612440 100644 --- a/app/celery/tasks.py +++ b/app/celery/tasks.py @@ -147,7 +147,6 @@ def contextual_activity_classification_for_batch(self, history_batch, address): print(f"User with address {address} not found") continue - # Create a new History entry history_entry = History( address=address, url=item["url"], @@ -155,8 +154,6 @@ def contextual_activity_classification_for_batch(self, history_batch, address): visitTime=float(item.get("lastVisitTime", datetime.now().timestamp())), category=activity, ) - - # Save the history entry to the database history_entry.save() print( diff --git a/app/core/views/user_v2_views.py b/app/core/views/user_v2_views.py index 41c6c91..83bc0a5 100644 --- a/app/core/views/user_v2_views.py +++ b/app/core/views/user_v2_views.py @@ -1,8 +1,6 @@ from flask import Blueprint, request, jsonify import random -from app.celery.userDataComputation.activityClassification import ( - get_most_relevant_activity, -) + from app.core.modules.activity_chart import upload_image_to_image_bb from ..models.user import * from ..modules.auth import get_jwt_token diff --git a/backend/bin/Activate.ps1 b/backend/bin/Activate.ps1 new file mode 100644 index 0000000..b49d77b --- /dev/null +++ b/backend/bin/Activate.ps1 @@ -0,0 +1,247 @@ +<# +.Synopsis +Activate a Python virtual environment for the current PowerShell session. + +.Description +Pushes the python executable for a virtual environment to the front of the +$Env:PATH environment variable and sets the prompt to signify that you are +in a Python virtual environment. Makes use of the command line switches as +well as the `pyvenv.cfg` file values present in the virtual environment. + +.Parameter VenvDir +Path to the directory that contains the virtual environment to activate. The +default value for this is the parent of the directory that the Activate.ps1 +script is located within. + +.Parameter Prompt +The prompt prefix to display when this virtual environment is activated. By +default, this prompt is the name of the virtual environment folder (VenvDir) +surrounded by parentheses and followed by a single space (ie. '(.venv) '). + +.Example +Activate.ps1 +Activates the Python virtual environment that contains the Activate.ps1 script. + +.Example +Activate.ps1 -Verbose +Activates the Python virtual environment that contains the Activate.ps1 script, +and shows extra information about the activation as it executes. + +.Example +Activate.ps1 -VenvDir C:\Users\MyUser\Common\.venv +Activates the Python virtual environment located in the specified location. + +.Example +Activate.ps1 -Prompt "MyPython" +Activates the Python virtual environment that contains the Activate.ps1 script, +and prefixes the current prompt with the specified string (surrounded in +parentheses) while the virtual environment is active. + +.Notes +On Windows, it may be required to enable this Activate.ps1 script by setting the +execution policy for the user. You can do this by issuing the following PowerShell +command: + +PS C:\> Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser + +For more information on Execution Policies: +https://go.microsoft.com/fwlink/?LinkID=135170 + +#> +Param( + [Parameter(Mandatory = $false)] + [String] + $VenvDir, + [Parameter(Mandatory = $false)] + [String] + $Prompt +) + +<# Function declarations --------------------------------------------------- #> + +<# +.Synopsis +Remove all shell session elements added by the Activate script, including the +addition of the virtual environment's Python executable from the beginning of +the PATH variable. + +.Parameter NonDestructive +If present, do not remove this function from the global namespace for the +session. + +#> +function global:deactivate ([switch]$NonDestructive) { + # Revert to original values + + # The prior prompt: + if (Test-Path -Path Function:_OLD_VIRTUAL_PROMPT) { + Copy-Item -Path Function:_OLD_VIRTUAL_PROMPT -Destination Function:prompt + Remove-Item -Path Function:_OLD_VIRTUAL_PROMPT + } + + # The prior PYTHONHOME: + if (Test-Path -Path Env:_OLD_VIRTUAL_PYTHONHOME) { + Copy-Item -Path Env:_OLD_VIRTUAL_PYTHONHOME -Destination Env:PYTHONHOME + Remove-Item -Path Env:_OLD_VIRTUAL_PYTHONHOME + } + + # The prior PATH: + if (Test-Path -Path Env:_OLD_VIRTUAL_PATH) { + Copy-Item -Path Env:_OLD_VIRTUAL_PATH -Destination Env:PATH + Remove-Item -Path Env:_OLD_VIRTUAL_PATH + } + + # Just remove the VIRTUAL_ENV altogether: + if (Test-Path -Path Env:VIRTUAL_ENV) { + Remove-Item -Path env:VIRTUAL_ENV + } + + # Just remove VIRTUAL_ENV_PROMPT altogether. + if (Test-Path -Path Env:VIRTUAL_ENV_PROMPT) { + Remove-Item -Path env:VIRTUAL_ENV_PROMPT + } + + # Just remove the _PYTHON_VENV_PROMPT_PREFIX altogether: + if (Get-Variable -Name "_PYTHON_VENV_PROMPT_PREFIX" -ErrorAction SilentlyContinue) { + Remove-Variable -Name _PYTHON_VENV_PROMPT_PREFIX -Scope Global -Force + } + + # Leave deactivate function in the global namespace if requested: + if (-not $NonDestructive) { + Remove-Item -Path function:deactivate + } +} + +<# +.Description +Get-PyVenvConfig parses the values from the pyvenv.cfg file located in the +given folder, and returns them in a map. + +For each line in the pyvenv.cfg file, if that line can be parsed into exactly +two strings separated by `=` (with any amount of whitespace surrounding the =) +then it is considered a `key = value` line. The left hand string is the key, +the right hand is the value. + +If the value starts with a `'` or a `"` then the first and last character is +stripped from the value before being captured. + +.Parameter ConfigDir +Path to the directory that contains the `pyvenv.cfg` file. +#> +function Get-PyVenvConfig( + [String] + $ConfigDir +) { + Write-Verbose "Given ConfigDir=$ConfigDir, obtain values in pyvenv.cfg" + + # Ensure the file exists, and issue a warning if it doesn't (but still allow the function to continue). + $pyvenvConfigPath = Join-Path -Resolve -Path $ConfigDir -ChildPath 'pyvenv.cfg' -ErrorAction Continue + + # An empty map will be returned if no config file is found. + $pyvenvConfig = @{ } + + if ($pyvenvConfigPath) { + + Write-Verbose "File exists, parse `key = value` lines" + $pyvenvConfigContent = Get-Content -Path $pyvenvConfigPath + + $pyvenvConfigContent | ForEach-Object { + $keyval = $PSItem -split "\s*=\s*", 2 + if ($keyval[0] -and $keyval[1]) { + $val = $keyval[1] + + # Remove extraneous quotations around a string value. + if ("'""".Contains($val.Substring(0, 1))) { + $val = $val.Substring(1, $val.Length - 2) + } + + $pyvenvConfig[$keyval[0]] = $val + Write-Verbose "Adding Key: '$($keyval[0])'='$val'" + } + } + } + return $pyvenvConfig +} + + +<# Begin Activate script --------------------------------------------------- #> + +# Determine the containing directory of this script +$VenvExecPath = Split-Path -Parent $MyInvocation.MyCommand.Definition +$VenvExecDir = Get-Item -Path $VenvExecPath + +Write-Verbose "Activation script is located in path: '$VenvExecPath'" +Write-Verbose "VenvExecDir Fullname: '$($VenvExecDir.FullName)" +Write-Verbose "VenvExecDir Name: '$($VenvExecDir.Name)" + +# Set values required in priority: CmdLine, ConfigFile, Default +# First, get the location of the virtual environment, it might not be +# VenvExecDir if specified on the command line. +if ($VenvDir) { + Write-Verbose "VenvDir given as parameter, using '$VenvDir' to determine values" +} +else { + Write-Verbose "VenvDir not given as a parameter, using parent directory name as VenvDir." + $VenvDir = $VenvExecDir.Parent.FullName.TrimEnd("\\/") + Write-Verbose "VenvDir=$VenvDir" +} + +# Next, read the `pyvenv.cfg` file to determine any required value such +# as `prompt`. +$pyvenvCfg = Get-PyVenvConfig -ConfigDir $VenvDir + +# Next, set the prompt from the command line, or the config file, or +# just use the name of the virtual environment folder. +if ($Prompt) { + Write-Verbose "Prompt specified as argument, using '$Prompt'" +} +else { + Write-Verbose "Prompt not specified as argument to script, checking pyvenv.cfg value" + if ($pyvenvCfg -and $pyvenvCfg['prompt']) { + Write-Verbose " Setting based on value in pyvenv.cfg='$($pyvenvCfg['prompt'])'" + $Prompt = $pyvenvCfg['prompt']; + } + else { + Write-Verbose " Setting prompt based on parent's directory's name. (Is the directory name passed to venv module when creating the virtual environment)" + Write-Verbose " Got leaf-name of $VenvDir='$(Split-Path -Path $venvDir -Leaf)'" + $Prompt = Split-Path -Path $venvDir -Leaf + } +} + +Write-Verbose "Prompt = '$Prompt'" +Write-Verbose "VenvDir='$VenvDir'" + +# Deactivate any currently active virtual environment, but leave the +# deactivate function in place. +deactivate -nondestructive + +# Now set the environment variable VIRTUAL_ENV, used by many tools to determine +# that there is an activated venv. +$env:VIRTUAL_ENV = $VenvDir + +if (-not $Env:VIRTUAL_ENV_DISABLE_PROMPT) { + + Write-Verbose "Setting prompt to '$Prompt'" + + # Set the prompt to include the env name + # Make sure _OLD_VIRTUAL_PROMPT is global + function global:_OLD_VIRTUAL_PROMPT { "" } + Copy-Item -Path function:prompt -Destination function:_OLD_VIRTUAL_PROMPT + New-Variable -Name _PYTHON_VENV_PROMPT_PREFIX -Description "Python virtual environment prompt prefix" -Scope Global -Option ReadOnly -Visibility Public -Value $Prompt + + function global:prompt { + Write-Host -NoNewline -ForegroundColor Green "($_PYTHON_VENV_PROMPT_PREFIX) " + _OLD_VIRTUAL_PROMPT + } + $env:VIRTUAL_ENV_PROMPT = $Prompt +} + +# Clear PYTHONHOME +if (Test-Path -Path Env:PYTHONHOME) { + Copy-Item -Path Env:PYTHONHOME -Destination Env:_OLD_VIRTUAL_PYTHONHOME + Remove-Item -Path Env:PYTHONHOME +} + +# Add the venv to the PATH +Copy-Item -Path Env:PATH -Destination Env:_OLD_VIRTUAL_PATH +$Env:PATH = "$VenvExecDir$([System.IO.Path]::PathSeparator)$Env:PATH" diff --git a/backend/bin/activate b/backend/bin/activate new file mode 100644 index 0000000..913b2c3 --- /dev/null +++ b/backend/bin/activate @@ -0,0 +1,70 @@ +# This file must be used with "source bin/activate" *from bash* +# You cannot run it directly + +deactivate () { + # reset old environment variables + if [ -n "${_OLD_VIRTUAL_PATH:-}" ] ; then + PATH="${_OLD_VIRTUAL_PATH:-}" + export PATH + unset _OLD_VIRTUAL_PATH + fi + if [ -n "${_OLD_VIRTUAL_PYTHONHOME:-}" ] ; then + PYTHONHOME="${_OLD_VIRTUAL_PYTHONHOME:-}" + export PYTHONHOME + unset _OLD_VIRTUAL_PYTHONHOME + fi + + # Call hash to forget past commands. Without forgetting + # past commands the $PATH changes we made may not be respected + hash -r 2> /dev/null + + if [ -n "${_OLD_VIRTUAL_PS1:-}" ] ; then + PS1="${_OLD_VIRTUAL_PS1:-}" + export PS1 + unset _OLD_VIRTUAL_PS1 + fi + + unset VIRTUAL_ENV + unset VIRTUAL_ENV_PROMPT + if [ ! "${1:-}" = "nondestructive" ] ; then + # Self destruct! + unset -f deactivate + fi +} + +# unset irrelevant variables +deactivate nondestructive + +# on Windows, a path can contain colons and backslashes and has to be converted: +if [ "${OSTYPE:-}" = "cygwin" ] || [ "${OSTYPE:-}" = "msys" ] ; then + # transform D:\path\to\venv to /d/path/to/venv on MSYS + # and to /cygdrive/d/path/to/venv on Cygwin + export VIRTUAL_ENV=$(cygpath "/Users/vaibhavgeek/kleo/backend/backend") +else + # use the path as-is + export VIRTUAL_ENV="/Users/vaibhavgeek/kleo/backend/backend" +fi + +_OLD_VIRTUAL_PATH="$PATH" +PATH="$VIRTUAL_ENV/bin:$PATH" +export PATH + +# unset PYTHONHOME if set +# this will fail if PYTHONHOME is set to the empty string (which is bad anyway) +# could use `if (set -u; : $PYTHONHOME) ;` in bash +if [ -n "${PYTHONHOME:-}" ] ; then + _OLD_VIRTUAL_PYTHONHOME="${PYTHONHOME:-}" + unset PYTHONHOME +fi + +if [ -z "${VIRTUAL_ENV_DISABLE_PROMPT:-}" ] ; then + _OLD_VIRTUAL_PS1="${PS1:-}" + PS1="(backend) ${PS1:-}" + export PS1 + VIRTUAL_ENV_PROMPT="(backend) " + export VIRTUAL_ENV_PROMPT +fi + +# Call hash to forget past commands. Without forgetting +# past commands the $PATH changes we made may not be respected +hash -r 2> /dev/null diff --git a/backend/bin/activate.csh b/backend/bin/activate.csh new file mode 100644 index 0000000..a938b77 --- /dev/null +++ b/backend/bin/activate.csh @@ -0,0 +1,27 @@ +# This file must be used with "source bin/activate.csh" *from csh*. +# You cannot run it directly. + +# Created by Davide Di Blasi . +# Ported to Python 3.3 venv by Andrew Svetlov + +alias deactivate 'test $?_OLD_VIRTUAL_PATH != 0 && setenv PATH "$_OLD_VIRTUAL_PATH" && unset _OLD_VIRTUAL_PATH; rehash; test $?_OLD_VIRTUAL_PROMPT != 0 && set prompt="$_OLD_VIRTUAL_PROMPT" && unset _OLD_VIRTUAL_PROMPT; unsetenv VIRTUAL_ENV; unsetenv VIRTUAL_ENV_PROMPT; test "\!:*" != "nondestructive" && unalias deactivate' + +# Unset irrelevant variables. +deactivate nondestructive + +setenv VIRTUAL_ENV "/Users/vaibhavgeek/kleo/backend/backend" + +set _OLD_VIRTUAL_PATH="$PATH" +setenv PATH "$VIRTUAL_ENV/bin:$PATH" + + +set _OLD_VIRTUAL_PROMPT="$prompt" + +if (! "$?VIRTUAL_ENV_DISABLE_PROMPT") then + set prompt = "(backend) $prompt" + setenv VIRTUAL_ENV_PROMPT "(backend) " +endif + +alias pydoc python -m pydoc + +rehash diff --git a/backend/bin/activate.fish b/backend/bin/activate.fish new file mode 100644 index 0000000..8605d5b --- /dev/null +++ b/backend/bin/activate.fish @@ -0,0 +1,69 @@ +# This file must be used with "source /bin/activate.fish" *from fish* +# (https://fishshell.com/). You cannot run it directly. + +function deactivate -d "Exit virtual environment and return to normal shell environment" + # reset old environment variables + if test -n "$_OLD_VIRTUAL_PATH" + set -gx PATH $_OLD_VIRTUAL_PATH + set -e _OLD_VIRTUAL_PATH + end + if test -n "$_OLD_VIRTUAL_PYTHONHOME" + set -gx PYTHONHOME $_OLD_VIRTUAL_PYTHONHOME + set -e _OLD_VIRTUAL_PYTHONHOME + end + + if test -n "$_OLD_FISH_PROMPT_OVERRIDE" + set -e _OLD_FISH_PROMPT_OVERRIDE + # prevents error when using nested fish instances (Issue #93858) + if functions -q _old_fish_prompt + functions -e fish_prompt + functions -c _old_fish_prompt fish_prompt + functions -e _old_fish_prompt + end + end + + set -e VIRTUAL_ENV + set -e VIRTUAL_ENV_PROMPT + if test "$argv[1]" != "nondestructive" + # Self-destruct! + functions -e deactivate + end +end + +# Unset irrelevant variables. +deactivate nondestructive + +set -gx VIRTUAL_ENV "/Users/vaibhavgeek/kleo/backend/backend" + +set -gx _OLD_VIRTUAL_PATH $PATH +set -gx PATH "$VIRTUAL_ENV/bin" $PATH + +# Unset PYTHONHOME if set. +if set -q PYTHONHOME + set -gx _OLD_VIRTUAL_PYTHONHOME $PYTHONHOME + set -e PYTHONHOME +end + +if test -z "$VIRTUAL_ENV_DISABLE_PROMPT" + # fish uses a function instead of an env var to generate the prompt. + + # Save the current fish_prompt function as the function _old_fish_prompt. + functions -c fish_prompt _old_fish_prompt + + # With the original prompt function renamed, we can override with our own. + function fish_prompt + # Save the return status of the last command. + set -l old_status $status + + # Output the venv prompt; color taken from the blue of the Python logo. + printf "%s%s%s" (set_color 4B8BBE) "(backend) " (set_color normal) + + # Restore the return status of the previous command. + echo "exit $old_status" | . + # Output the original/"old" prompt. + _old_fish_prompt + end + + set -gx _OLD_FISH_PROMPT_OVERRIDE "$VIRTUAL_ENV" + set -gx VIRTUAL_ENV_PROMPT "(backend) " +end diff --git a/backend/bin/celery b/backend/bin/celery new file mode 100755 index 0000000..f747135 --- /dev/null +++ b/backend/bin/celery @@ -0,0 +1,8 @@ +#!/Users/vaibhavgeek/kleo/backend/backend/bin/python3.12 +# -*- coding: utf-8 -*- +import re +import sys +from celery.__main__ import main +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/backend/bin/convert-caffe2-to-onnx b/backend/bin/convert-caffe2-to-onnx new file mode 100755 index 0000000..261c0d4 --- /dev/null +++ b/backend/bin/convert-caffe2-to-onnx @@ -0,0 +1,8 @@ +#!/Users/vaibhavgeek/kleo/backend/backend/bin/python3.12 +# -*- coding: utf-8 -*- +import re +import sys +from caffe2.python.onnx.bin.conversion import caffe2_to_onnx +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(caffe2_to_onnx()) diff --git a/backend/bin/convert-onnx-to-caffe2 b/backend/bin/convert-onnx-to-caffe2 new file mode 100755 index 0000000..02942ab --- /dev/null +++ b/backend/bin/convert-onnx-to-caffe2 @@ -0,0 +1,8 @@ +#!/Users/vaibhavgeek/kleo/backend/backend/bin/python3.12 +# -*- coding: utf-8 -*- +import re +import sys +from caffe2.python.onnx.bin.conversion import onnx_to_caffe2 +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(onnx_to_caffe2()) diff --git a/backend/bin/dotenv b/backend/bin/dotenv new file mode 100755 index 0000000..ab832a4 --- /dev/null +++ b/backend/bin/dotenv @@ -0,0 +1,8 @@ +#!/Users/vaibhavgeek/kleo/backend/backend/bin/python3.12 +# -*- coding: utf-8 -*- +import re +import sys +from dotenv.__main__ import cli +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(cli()) diff --git a/backend/bin/f2py b/backend/bin/f2py new file mode 100755 index 0000000..6265c88 --- /dev/null +++ b/backend/bin/f2py @@ -0,0 +1,8 @@ +#!/Users/vaibhavgeek/kleo/backend/backend/bin/python3.12 +# -*- coding: utf-8 -*- +import re +import sys +from numpy.f2py.f2py2e import main +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/backend/bin/flask b/backend/bin/flask new file mode 100755 index 0000000..080b2f1 --- /dev/null +++ b/backend/bin/flask @@ -0,0 +1,8 @@ +#!/Users/vaibhavgeek/kleo/backend/backend/bin/python3.12 +# -*- coding: utf-8 -*- +import re +import sys +from flask.cli import main +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/backend/bin/gunicorn b/backend/bin/gunicorn new file mode 100755 index 0000000..36cac4c --- /dev/null +++ b/backend/bin/gunicorn @@ -0,0 +1,8 @@ +#!/Users/vaibhavgeek/kleo/backend/backend/bin/python3.12 +# -*- coding: utf-8 -*- +import re +import sys +from gunicorn.app.wsgiapp import run +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(run()) diff --git a/backend/bin/huggingface-cli b/backend/bin/huggingface-cli new file mode 100755 index 0000000..fddb746 --- /dev/null +++ b/backend/bin/huggingface-cli @@ -0,0 +1,8 @@ +#!/Users/vaibhavgeek/kleo/backend/backend/bin/python3.12 +# -*- coding: utf-8 -*- +import re +import sys +from huggingface_hub.commands.huggingface_cli import main +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/backend/bin/isympy b/backend/bin/isympy new file mode 100755 index 0000000..70674aa --- /dev/null +++ b/backend/bin/isympy @@ -0,0 +1,8 @@ +#!/Users/vaibhavgeek/kleo/backend/backend/bin/python3.12 +# -*- coding: utf-8 -*- +import re +import sys +from isympy import main +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/backend/bin/markdown-it b/backend/bin/markdown-it new file mode 100755 index 0000000..c168b44 --- /dev/null +++ b/backend/bin/markdown-it @@ -0,0 +1,8 @@ +#!/Users/vaibhavgeek/kleo/backend/backend/bin/python3.12 +# -*- coding: utf-8 -*- +import re +import sys +from markdown_it.cli.parse import main +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/backend/bin/nltk b/backend/bin/nltk new file mode 100755 index 0000000..36ed78e --- /dev/null +++ b/backend/bin/nltk @@ -0,0 +1,8 @@ +#!/Users/vaibhavgeek/kleo/backend/backend/bin/python3.12 +# -*- coding: utf-8 -*- +import re +import sys +from nltk.cli import cli +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(cli()) diff --git a/backend/bin/normalizer b/backend/bin/normalizer new file mode 100755 index 0000000..bfd0bf2 --- /dev/null +++ b/backend/bin/normalizer @@ -0,0 +1,8 @@ +#!/Users/vaibhavgeek/kleo/backend/backend/bin/python3.12 +# -*- coding: utf-8 -*- +import re +import sys +from charset_normalizer.cli import cli_detect +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(cli_detect()) diff --git a/backend/bin/numpy-config b/backend/bin/numpy-config new file mode 100755 index 0000000..96e2fa0 --- /dev/null +++ b/backend/bin/numpy-config @@ -0,0 +1,8 @@ +#!/Users/vaibhavgeek/kleo/backend/backend/bin/python3.12 +# -*- coding: utf-8 -*- +import re +import sys +from numpy._configtool import main +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/backend/bin/pip b/backend/bin/pip new file mode 100755 index 0000000..382cf89 --- /dev/null +++ b/backend/bin/pip @@ -0,0 +1,8 @@ +#!/Users/vaibhavgeek/kleo/backend/backend/bin/python3.12 +# -*- coding: utf-8 -*- +import re +import sys +from pip._internal.cli.main import main +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/backend/bin/pip3 b/backend/bin/pip3 new file mode 100755 index 0000000..382cf89 --- /dev/null +++ b/backend/bin/pip3 @@ -0,0 +1,8 @@ +#!/Users/vaibhavgeek/kleo/backend/backend/bin/python3.12 +# -*- coding: utf-8 -*- +import re +import sys +from pip._internal.cli.main import main +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/backend/bin/pip3.12 b/backend/bin/pip3.12 new file mode 100755 index 0000000..382cf89 --- /dev/null +++ b/backend/bin/pip3.12 @@ -0,0 +1,8 @@ +#!/Users/vaibhavgeek/kleo/backend/backend/bin/python3.12 +# -*- coding: utf-8 -*- +import re +import sys +from pip._internal.cli.main import main +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/backend/bin/pygmentize b/backend/bin/pygmentize new file mode 100755 index 0000000..855bf0f --- /dev/null +++ b/backend/bin/pygmentize @@ -0,0 +1,8 @@ +#!/Users/vaibhavgeek/kleo/backend/backend/bin/python3.12 +# -*- coding: utf-8 -*- +import re +import sys +from pygments.cmdline import main +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/backend/bin/python b/backend/bin/python new file mode 120000 index 0000000..11b9d88 --- /dev/null +++ b/backend/bin/python @@ -0,0 +1 @@ +python3.12 \ No newline at end of file diff --git a/backend/bin/python3 b/backend/bin/python3 new file mode 120000 index 0000000..11b9d88 --- /dev/null +++ b/backend/bin/python3 @@ -0,0 +1 @@ +python3.12 \ No newline at end of file diff --git a/backend/bin/python3.12 b/backend/bin/python3.12 new file mode 120000 index 0000000..a3f0508 --- /dev/null +++ b/backend/bin/python3.12 @@ -0,0 +1 @@ +/opt/homebrew/opt/python@3.12/bin/python3.12 \ No newline at end of file diff --git a/backend/bin/spacy b/backend/bin/spacy new file mode 100755 index 0000000..c0bf28a --- /dev/null +++ b/backend/bin/spacy @@ -0,0 +1,8 @@ +#!/Users/vaibhavgeek/kleo/backend/backend/bin/python3.12 +# -*- coding: utf-8 -*- +import re +import sys +from spacy.cli import setup_cli +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(setup_cli()) diff --git a/backend/bin/tldextract b/backend/bin/tldextract new file mode 100755 index 0000000..33bda29 --- /dev/null +++ b/backend/bin/tldextract @@ -0,0 +1,8 @@ +#!/Users/vaibhavgeek/kleo/backend/backend/bin/python3.12 +# -*- coding: utf-8 -*- +import re +import sys +from tldextract.cli import main +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/backend/bin/torchfrtrace b/backend/bin/torchfrtrace new file mode 100755 index 0000000..05e61b0 --- /dev/null +++ b/backend/bin/torchfrtrace @@ -0,0 +1,8 @@ +#!/Users/vaibhavgeek/kleo/backend/backend/bin/python3.12 +# -*- coding: utf-8 -*- +import re +import sys +from tools.flight_recorder.fr_trace import main +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/backend/bin/torchrun b/backend/bin/torchrun new file mode 100755 index 0000000..7ca1c7d --- /dev/null +++ b/backend/bin/torchrun @@ -0,0 +1,8 @@ +#!/Users/vaibhavgeek/kleo/backend/backend/bin/python3.12 +# -*- coding: utf-8 -*- +import re +import sys +from torch.distributed.run import main +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/backend/bin/tqdm b/backend/bin/tqdm new file mode 100755 index 0000000..8e47f23 --- /dev/null +++ b/backend/bin/tqdm @@ -0,0 +1,8 @@ +#!/Users/vaibhavgeek/kleo/backend/backend/bin/python3.12 +# -*- coding: utf-8 -*- +import re +import sys +from tqdm.cli import main +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/backend/bin/transformers-cli b/backend/bin/transformers-cli new file mode 100755 index 0000000..2499a67 --- /dev/null +++ b/backend/bin/transformers-cli @@ -0,0 +1,8 @@ +#!/Users/vaibhavgeek/kleo/backend/backend/bin/python3.12 +# -*- coding: utf-8 -*- +import re +import sys +from transformers.commands.transformers_cli import main +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/backend/bin/typer b/backend/bin/typer new file mode 100755 index 0000000..29ac77b --- /dev/null +++ b/backend/bin/typer @@ -0,0 +1,8 @@ +#!/Users/vaibhavgeek/kleo/backend/backend/bin/python3.12 +# -*- coding: utf-8 -*- +import re +import sys +from typer.cli import main +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(main()) diff --git a/backend/bin/weasel b/backend/bin/weasel new file mode 100755 index 0000000..d6e5ee8 --- /dev/null +++ b/backend/bin/weasel @@ -0,0 +1,8 @@ +#!/Users/vaibhavgeek/kleo/backend/backend/bin/python3.12 +# -*- coding: utf-8 -*- +import re +import sys +from weasel.cli import app +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) + sys.exit(app()) diff --git a/backend/pyvenv.cfg b/backend/pyvenv.cfg new file mode 100644 index 0000000..9861c36 --- /dev/null +++ b/backend/pyvenv.cfg @@ -0,0 +1,5 @@ +home = /opt/homebrew/opt/python@3.12/bin +include-system-site-packages = false +version = 3.12.5 +executable = /opt/homebrew/Cellar/python@3.12/3.12.5/Frameworks/Python.framework/Versions/3.12/bin/python3.12 +command = /opt/homebrew/opt/python@3.12/bin/python3.12 -m venv /Users/vaibhavgeek/kleo/backend/backend diff --git a/backend/share/man/man1/isympy.1 b/backend/share/man/man1/isympy.1 new file mode 100644 index 0000000..0ff9661 --- /dev/null +++ b/backend/share/man/man1/isympy.1 @@ -0,0 +1,188 @@ +'\" -*- coding: us-ascii -*- +.if \n(.g .ds T< \\FC +.if \n(.g .ds T> \\F[\n[.fam]] +.de URL +\\$2 \(la\\$1\(ra\\$3 +.. +.if \n(.g .mso www.tmac +.TH isympy 1 2007-10-8 "" "" +.SH NAME +isympy \- interactive shell for SymPy +.SH SYNOPSIS +'nh +.fi +.ad l +\fBisympy\fR \kx +.if (\nx>(\n(.l/2)) .nr x (\n(.l/5) +'in \n(.iu+\nxu +[\fB-c\fR | \fB--console\fR] [\fB-p\fR ENCODING | \fB--pretty\fR ENCODING] [\fB-t\fR TYPE | \fB--types\fR TYPE] [\fB-o\fR ORDER | \fB--order\fR ORDER] [\fB-q\fR | \fB--quiet\fR] [\fB-d\fR | \fB--doctest\fR] [\fB-C\fR | \fB--no-cache\fR] [\fB-a\fR | \fB--auto\fR] [\fB-D\fR | \fB--debug\fR] [ +-- | PYTHONOPTIONS] +'in \n(.iu-\nxu +.ad b +'hy +'nh +.fi +.ad l +\fBisympy\fR \kx +.if (\nx>(\n(.l/2)) .nr x (\n(.l/5) +'in \n(.iu+\nxu +[ +{\fB-h\fR | \fB--help\fR} +| +{\fB-v\fR | \fB--version\fR} +] +'in \n(.iu-\nxu +.ad b +'hy +.SH DESCRIPTION +isympy is a Python shell for SymPy. It is just a normal python shell +(ipython shell if you have the ipython package installed) that executes +the following commands so that you don't have to: +.PP +.nf +\*(T< +>>> from __future__ import division +>>> from sympy import * +>>> x, y, z = symbols("x,y,z") +>>> k, m, n = symbols("k,m,n", integer=True) + \*(T> +.fi +.PP +So starting isympy is equivalent to starting python (or ipython) and +executing the above commands by hand. It is intended for easy and quick +experimentation with SymPy. For more complicated programs, it is recommended +to write a script and import things explicitly (using the "from sympy +import sin, log, Symbol, ..." idiom). +.SH OPTIONS +.TP +\*(T<\fB\-c \fR\*(T>\fISHELL\fR, \*(T<\fB\-\-console=\fR\*(T>\fISHELL\fR +Use the specified shell (python or ipython) as +console backend instead of the default one (ipython +if present or python otherwise). + +Example: isympy -c python + +\fISHELL\fR could be either +\&'ipython' or 'python' +.TP +\*(T<\fB\-p \fR\*(T>\fIENCODING\fR, \*(T<\fB\-\-pretty=\fR\*(T>\fIENCODING\fR +Setup pretty printing in SymPy. By default, the most pretty, unicode +printing is enabled (if the terminal supports it). You can use less +pretty ASCII printing instead or no pretty printing at all. + +Example: isympy -p no + +\fIENCODING\fR must be one of 'unicode', +\&'ascii' or 'no'. +.TP +\*(T<\fB\-t \fR\*(T>\fITYPE\fR, \*(T<\fB\-\-types=\fR\*(T>\fITYPE\fR +Setup the ground types for the polys. By default, gmpy ground types +are used if gmpy2 or gmpy is installed, otherwise it falls back to python +ground types, which are a little bit slower. You can manually +choose python ground types even if gmpy is installed (e.g., for testing purposes). + +Note that sympy ground types are not supported, and should be used +only for experimental purposes. + +Note that the gmpy1 ground type is primarily intended for testing; it the +use of gmpy even if gmpy2 is available. + +This is the same as setting the environment variable +SYMPY_GROUND_TYPES to the given ground type (e.g., +SYMPY_GROUND_TYPES='gmpy') + +The ground types can be determined interactively from the variable +sympy.polys.domains.GROUND_TYPES inside the isympy shell itself. + +Example: isympy -t python + +\fITYPE\fR must be one of 'gmpy', +\&'gmpy1' or 'python'. +.TP +\*(T<\fB\-o \fR\*(T>\fIORDER\fR, \*(T<\fB\-\-order=\fR\*(T>\fIORDER\fR +Setup the ordering of terms for printing. The default is lex, which +orders terms lexicographically (e.g., x**2 + x + 1). You can choose +other orderings, such as rev-lex, which will use reverse +lexicographic ordering (e.g., 1 + x + x**2). + +Note that for very large expressions, ORDER='none' may speed up +printing considerably, with the tradeoff that the order of the terms +in the printed expression will have no canonical order + +Example: isympy -o rev-lax + +\fIORDER\fR must be one of 'lex', 'rev-lex', 'grlex', +\&'rev-grlex', 'grevlex', 'rev-grevlex', 'old', or 'none'. +.TP +\*(T<\fB\-q\fR\*(T>, \*(T<\fB\-\-quiet\fR\*(T> +Print only Python's and SymPy's versions to stdout at startup, and nothing else. +.TP +\*(T<\fB\-d\fR\*(T>, \*(T<\fB\-\-doctest\fR\*(T> +Use the same format that should be used for doctests. This is +equivalent to '\fIisympy -c python -p no\fR'. +.TP +\*(T<\fB\-C\fR\*(T>, \*(T<\fB\-\-no\-cache\fR\*(T> +Disable the caching mechanism. Disabling the cache may slow certain +operations down considerably. This is useful for testing the cache, +or for benchmarking, as the cache can result in deceptive benchmark timings. + +This is the same as setting the environment variable SYMPY_USE_CACHE +to 'no'. +.TP +\*(T<\fB\-a\fR\*(T>, \*(T<\fB\-\-auto\fR\*(T> +Automatically create missing symbols. Normally, typing a name of a +Symbol that has not been instantiated first would raise NameError, +but with this option enabled, any undefined name will be +automatically created as a Symbol. This only works in IPython 0.11. + +Note that this is intended only for interactive, calculator style +usage. In a script that uses SymPy, Symbols should be instantiated +at the top, so that it's clear what they are. + +This will not override any names that are already defined, which +includes the single character letters represented by the mnemonic +QCOSINE (see the "Gotchas and Pitfalls" document in the +documentation). You can delete existing names by executing "del +name" in the shell itself. You can see if a name is defined by typing +"'name' in globals()". + +The Symbols that are created using this have default assumptions. +If you want to place assumptions on symbols, you should create them +using symbols() or var(). + +Finally, this only works in the top level namespace. So, for +example, if you define a function in isympy with an undefined +Symbol, it will not work. +.TP +\*(T<\fB\-D\fR\*(T>, \*(T<\fB\-\-debug\fR\*(T> +Enable debugging output. This is the same as setting the +environment variable SYMPY_DEBUG to 'True'. The debug status is set +in the variable SYMPY_DEBUG within isympy. +.TP +-- \fIPYTHONOPTIONS\fR +These options will be passed on to \fIipython (1)\fR shell. +Only supported when ipython is being used (standard python shell not supported). + +Two dashes (--) are required to separate \fIPYTHONOPTIONS\fR +from the other isympy options. + +For example, to run iSymPy without startup banner and colors: + +isympy -q -c ipython -- --colors=NoColor +.TP +\*(T<\fB\-h\fR\*(T>, \*(T<\fB\-\-help\fR\*(T> +Print help output and exit. +.TP +\*(T<\fB\-v\fR\*(T>, \*(T<\fB\-\-version\fR\*(T> +Print isympy version information and exit. +.SH FILES +.TP +\*(T<\fI${HOME}/.sympy\-history\fR\*(T> +Saves the history of commands when using the python +shell as backend. +.SH BUGS +The upstreams BTS can be found at \(lahttps://github.com/sympy/sympy/issues\(ra +Please report all bugs that you find in there, this will help improve +the overall quality of SymPy. +.SH "SEE ALSO" +\fBipython\fR(1), \fBpython\fR(1) diff --git a/docker-compose.yml b/docker-compose.yml index 70faf7f..b80faed 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -5,13 +5,7 @@ services: - 6379:6379 api: build: . - command: gunicorn --workers 4 \ - --threads 2 \ - --timeout 30 \ - --keep-alive 5 \ - --max-requests 1000 \ - --max-requests-jitter 50 \ - 'app:create_app()' + command: gunicorn -w 4 --bind 0.0.0.0:5001 run:app ports: - 5001:5001 volumes: diff --git a/requirements.txt b/requirements.txt index af6b1a4..0e8f45c 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,143 +1,78 @@ -aiohttp==3.8.6 -aiosignal==1.3.1 -amqp==5.1.1 -annotated-types==0.6.0 -anyio==4.3.0 -appnope==0.1.3 -asttokens==2.2.1 -async-timeout==4.0.3 -attrs==23.1.0 -autopep8==2.0.2 -backcall==0.2.0 -base58==2.1.1 -beautifulsoup4==4.12.2 -billiard==4.2.0 -bitarray==2.8.2 -blinker==1.6.2 -black -boto3==1.28.55 -botocore==1.31.55 -bs4==0.0.1 -cachetools==5.3.3 +amqp==5.2.0 +annotated-types==0.7.0 +billiard==4.2.1 +blinker==1.8.2 celery==5.4.0 -certifi==2023.7.22 -cffi==1.16.0 -charset-normalizer==3.2.0 -click==8.1.3 -click-didyoumean==0.3.0 +certifi==2024.8.30 +cffi==1.17.1 +charset-normalizer==3.4.0 +click==8.1.7 +click-didyoumean==0.3.1 click-plugins==1.1.1 -click-repl==0.2.0 -cytoolz==0.12.2 -decorator==5.1.1 -distro==1.9.0 -dnspython==2.6.1 -eth-abi==4.2.1 -eth-account==0.9.0 -eth-hash==0.5.2 -eth-keyfile==0.6.1 -eth-keys==0.4.0 -eth-rlp==0.3.0 -eth-typing==3.5.1 -eth-utils==2.3.0 -executing==1.2.0 -filelock==3.12.4 -flake8==6.0.0 -Flask==2.3.2 -Flask-Cors==3.0.10 -flower==2.0.1 -frozenlist==1.4.0 -google-auth==2.6.0 -gunicorn==21.2.0 -h11==0.14.0 -hexbytes==0.3.1 -httpcore==1.0.5 -httpx==0.27.0 -humanize==4.8.0 -idna==3.4 -ipython==8.13.2 -itsdangerous==2.1.2 -jedi==0.18.2 -Jinja2==3.1.2 -jmespath==1.0.1 -jsonschema==4.19.1 -jsonschema-specifications==2023.7.1 -kombu==5.3.7 -lru-dict==1.2.0 -MarkupSafe==2.1.2 -marshmallow==3.20.1 -matplotlib-inline==0.1.6 -mccabe==0.7.0 -mongoengine==0.28.2 -multidict==6.0.4 -openai==1.19.0 -packaging==23.1 -parsimonious==0.9.0 -parso==0.8.3 -pexpect==4.8.0 -pickleshare==0.7.5 -prometheus-client==0.17.1 -prompt-toolkit==3.0.38 -protobuf==4.24.4 -ptyprocess==0.7.0 -pure-eval==0.2.2 -pyasn1==0.6.0 -pyasn1_modules==0.4.0 -pycodestyle==2.10.0 -pycparser==2.21 -pycryptodome==3.19.0 -pycurl==7.45.3 -pydantic==2.7.0 -pydantic-settings==2.2.1 -pydantic_core==2.18.1 -pyflakes==3.0.1 -Pygments==2.15.1 -PyJWT==2.8.0 -pymongo==4.6.3 -pymongo[srv] -PyNaCl==1.5.0 -python-dateutil==2.8.2 -python-dotenv==1.0.0 -pytz==2023.3 -pyunormalize==15.0.0 -redis==4.5.4 -referencing==0.30.2 -regex==2023.10.3 -requests==2.31.0 -requests-file==1.5.1 -rlp==3.0.0 -rpds-py==0.10.6 -rsa==4.9 -s3transfer==0.7.0 +click-repl==0.3.0 +cryptography==43.0.3 +Deprecated==1.2.14 +dnspython==2.7.0 +filelock==3.16.1 +Flask==3.0.3 +Flask-Cors==5.0.0 +Flask-Limiter==3.8.0 +fsspec==2024.10.0 +huggingface-hub==0.26.2 +idna==3.10 +importlib_resources==6.4.5 +itsdangerous==2.2.0 +Jinja2==3.1.4 +joblib==1.4.2 +jwt==1.3.1 +keybert==0.8.5 +kombu==5.4.2 +limits==3.13.0 +markdown-it-py==3.0.0 +MarkupSafe==3.0.2 +mdurl==0.1.2 +mpmath==1.3.0 +networkx==3.4.2 +numpy==2.1.3 +ordered-set==4.1.0 +packaging==24.1 +pillow==11.0.0 +prompt_toolkit==3.0.48 +pycparser==2.22 +pydantic==2.9.2 +pydantic-settings==2.6.1 +pydantic_core==2.23.4 +Pygments==2.18.0 +pymongo==4.10.1 +python-dateutil==2.9.0.post0 +python-dotenv==1.0.1 +PyYAML==6.0.2 +regex==2024.9.11 +requests==2.32.3 +rich==13.9.4 +safetensors==0.4.5 +scikit-learn==1.5.2 +scipy==1.14.1 +sentence-transformers==3.2.1 +setuptools==75.3.0 six==1.16.0 -sniffio==1.3.1 -soupsieve==2.5 -stack-data==0.6.2 -tldextract==3.6.0 -toolz==0.12.0 -tornado==6.3.3 -tqdm==4.66.2 -traitlets==5.9.0 -typing_extensions==4.8.0 -tzdata==2024.1 -urllib3==1.26.16 -uuid +sympy==1.13.1 +threadpoolctl==3.5.0 +tokenizers==0.20.1 +torch==2.5.1 +tqdm==4.66.6 +transformers==4.46.1 +typing_extensions==4.12.2 +tzdata==2024.2 +urllib3==2.2.3 vine==5.1.0 -wcwidth==0.2.6 -web3==6.11.1 -webargs==8.2.0 -websockets==12.0 -Werkzeug==2.3.3 -yarl==1.9.2 -zipp==3.15.0 -google-auth==2.6.0 -pymongo[srv] -openai -uuid -keybert +wcwidth==0.2.13 +Werkzeug==3.1.1 +wrapt==1.16.0 sentence_transformers presidio-analyzer # Detects PII in text presidio-anonymizer # Anonymizes detected PII imgurpython # IMGUR uploading chart images gunicorn -celery -nltk \ No newline at end of file +nltk +redis \ No newline at end of file From a7ebe6e20d976bddee4fffb0727daf3adb1912ca Mon Sep 17 00:00:00 2001 From: Vaibhav Maheshwari Date: Sun, 3 Nov 2024 07:04:52 +0530 Subject: [PATCH 07/12] fix: addPyJWT --- app/core/views/user_v2_views.py | 32 +++++++++++++++++--------------- requirements.txt | 3 ++- 2 files changed, 19 insertions(+), 16 deletions(-) diff --git a/app/core/views/user_v2_views.py b/app/core/views/user_v2_views.py index 83bc0a5..1e72de9 100644 --- a/app/core/views/user_v2_views.py +++ b/app/core/views/user_v2_views.py @@ -97,36 +97,38 @@ def save_history(): @core.route("/create-user", methods=["POST"]) def create_user(): - """ - Create a new user or return existing user information. - If the user exists, return their data along with a JWT token. - If the user doesn't exist, create a new user, allocate Vana points and tokens, - and generate a 5-digit random code. - """ data = request.get_json() - # print("create user hit") wallet_address = data.get("address") + if not wallet_address: + return jsonify({"error": "Address is required"}), 400 + user = find_by_address(wallet_address) - # print(user) if user: - user["token"] = get_jwt_token(wallet_address, wallet_address) + try: + token = get_jwt_token(wallet_address, wallet_address) + except Exception as e: + return jsonify({'error': 'Failed to generate token'}), 500 + + user["token"] = token return jsonify(user), 200 - # Generate a 5-digit random code random_code = str(random.randint(100, 9999999)) - # Create a new user with the random code user = User(address=wallet_address, slug=random_code) response = user.save(signup=True) - # Prepare the response object + try: + token = get_jwt_token(wallet_address, wallet_address) + except Exception as e: + return jsonify({'error': 'Failed to generate token'}), 500 + user_data = { "password": response["slug"], - "token": get_jwt_token(wallet_address, wallet_address), + "token": token, } - # print(user_data) - return jsonify(user_data), 200 # 201 Created + return jsonify(user_data), 201 + @core.route("/upload_activity_chart", methods=["POST"]) diff --git a/requirements.txt b/requirements.txt index 0e8f45c..f4a1032 100644 --- a/requirements.txt +++ b/requirements.txt @@ -75,4 +75,5 @@ presidio-anonymizer # Anonymizes detected PII imgurpython # IMGUR uploading chart images gunicorn nltk -redis \ No newline at end of file +redis +PyJWT \ No newline at end of file From 460ee3577df7907d7952fe2f9c0c1b3cc9b3a10c Mon Sep 17 00:00:00 2001 From: Vaibhav Maheshwari Date: Sun, 3 Nov 2024 10:36:45 +0530 Subject: [PATCH 08/12] feat: fix rate limits --- app/__init__.py | 2 +- app/core/modules/auth.py | 18 +----------------- app/core/views/user_v2_views.py | 9 +++++---- requirements.txt | 1 - 4 files changed, 7 insertions(+), 23 deletions(-) diff --git a/app/__init__.py b/app/__init__.py index 4dace27..bd41367 100755 --- a/app/__init__.py +++ b/app/__init__.py @@ -16,7 +16,7 @@ def create_app(): limiter = Limiter( key_func=get_remote_address, app=app, - default_limits=["200 per day", "50 per hour"] + default_limits=["500 per day", "200 per hour"] ) @app.errorhandler(RateLimitExceeded) def rate_limit_handler(e): diff --git a/app/core/modules/auth.py b/app/core/modules/auth.py index ebcfcde..55b3428 100644 --- a/app/core/modules/auth.py +++ b/app/core/modules/auth.py @@ -1,31 +1,15 @@ import os import jwt -from flask import jsonify -from app.core.models.user import find_by_address def get_jwt_token(wallet, slug): - """Generate a JWT token for a given user identified by slug and email.""" - - # Fetch the user's address using the provided slug - address = find_by_address(wallet) - - # Check if the user exists and if the email matches - if not address: - return jsonify({"error": "User not found"}), 404 - try: - # Retrieve secret and algorithm from environment variables SECRET = os.environ.get("SECRET", "default_secret") ALGORITHM = os.environ.get("ALGORITHM", "HS256") - # Create the payload for the JWT payload = {"payload": {"slug": slug, "publicAddress": wallet}} - # Encode the JWT token access_token = jwt.encode(payload, SECRET, algorithm=ALGORITHM) return access_token except Exception as e: - # Log the exception or return a specific error message - print(f"Error creating JWT token: {str(e)}") - return jsonify({"error": "Could not create token"}), 500 + pass \ No newline at end of file diff --git a/app/core/views/user_v2_views.py b/app/core/views/user_v2_views.py index 1e72de9..83db884 100644 --- a/app/core/views/user_v2_views.py +++ b/app/core/views/user_v2_views.py @@ -109,9 +109,9 @@ def create_user(): token = get_jwt_token(wallet_address, wallet_address) except Exception as e: return jsonify({'error': 'Failed to generate token'}), 500 - - user["token"] = token - return jsonify(user), 200 + + user_data = {"password": user["slug"], "token": token} + return jsonify(user_data), 200 random_code = str(random.randint(100, 9999999)) @@ -127,7 +127,8 @@ def create_user(): "password": response["slug"], "token": token, } - return jsonify(user_data), 201 + print(user_data) + return jsonify(user_data), 200 diff --git a/requirements.txt b/requirements.txt index f4a1032..8713e1c 100644 --- a/requirements.txt +++ b/requirements.txt @@ -24,7 +24,6 @@ importlib_resources==6.4.5 itsdangerous==2.2.0 Jinja2==3.1.4 joblib==1.4.2 -jwt==1.3.1 keybert==0.8.5 kombu==5.4.2 limits==3.13.0 From c84e9b54cb90435405d2e866051148d666dcb0d6 Mon Sep 17 00:00:00 2001 From: princedalsaniya Date: Sun, 3 Nov 2024 18:30:00 +0530 Subject: [PATCH 09/12] refactor: added logs for get-user --- app/core/views/user_v2_views.py | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/app/core/views/user_v2_views.py b/app/core/views/user_v2_views.py index 83db884..6888c6b 100644 --- a/app/core/views/user_v2_views.py +++ b/app/core/views/user_v2_views.py @@ -94,7 +94,6 @@ def save_history(): return jsonify({"status": "error", "message": str(e)}), 500 - @core.route("/create-user", methods=["POST"]) def create_user(): data = request.get_json() @@ -108,8 +107,8 @@ def create_user(): try: token = get_jwt_token(wallet_address, wallet_address) except Exception as e: - return jsonify({'error': 'Failed to generate token'}), 500 - + return jsonify({"error": "Failed to generate token"}), 500 + user_data = {"password": user["slug"], "token": token} return jsonify(user_data), 200 @@ -121,7 +120,7 @@ def create_user(): try: token = get_jwt_token(wallet_address, wallet_address) except Exception as e: - return jsonify({'error': 'Failed to generate token'}), 500 + return jsonify({"error": "Failed to generate token"}), 500 user_data = { "password": response["slug"], @@ -131,7 +130,6 @@ def create_user(): return jsonify(user_data), 200 - @core.route("/upload_activity_chart", methods=["POST"]) def upload_activity_chart(): try: @@ -157,10 +155,11 @@ def get_user(userAddress): """ Fetch user data from MongoDB based on the user's address. """ + print("------------- get-user --------------", userAddress) try: # Query the MongoDB collection using the user's address user_data = find_by_address(userAddress) - + print("------------- userData --------------", user_data) # If user data is not found, return a 404 error if not user_data: return jsonify({"error": "User not found"}), 404 @@ -223,4 +222,4 @@ def get_user_referrals(userAddress): referrals = fetch_users_referrals(userAddress) return referrals except Exception as e: - return jsonify({"error": "An error occurred while fetching user's referrals"}) \ No newline at end of file + return jsonify({"error": "An error occurred while fetching user's referrals"}) From 31af39202555e56778dac93afac5f77bc3bd687f Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Sun, 3 Nov 2024 13:15:34 +0000 Subject: [PATCH 10/12] removed celery tasks --- app/__init__.py | 4 ++-- cleanup.sh | 4 ++-- docker-compose.yml | 9 +-------- 3 files changed, 5 insertions(+), 12 deletions(-) diff --git a/app/__init__.py b/app/__init__.py index bd41367..9baa42b 100755 --- a/app/__init__.py +++ b/app/__init__.py @@ -16,7 +16,7 @@ def create_app(): limiter = Limiter( key_func=get_remote_address, app=app, - default_limits=["500 per day", "200 per hour"] + default_limits=["5000 per day", "2000 per hour"] ) @app.errorhandler(RateLimitExceeded) def rate_limit_handler(e): @@ -34,7 +34,7 @@ def register_blueprints(app, limiter): """ from .core.views.user_v2_views import core as core_user_v2 - limiter.limit("100 per hour")(core_user_v2) + limiter.limit("2000 per hour")(core_user_v2) app.register_blueprint( core_user_v2, name="user_api_v2", url_prefix="/api/v2/core/user" ) diff --git a/cleanup.sh b/cleanup.sh index 2fe49e6..a44d377 100755 --- a/cleanup.sh +++ b/cleanup.sh @@ -18,7 +18,7 @@ docker volume rm $(docker volume ls -q) # Optional: Remove all networks # echo "Removing networks..." -# docker network rm $(docker network ls -q) - +docker network rm $(docker network ls -q) +docker system prune -a --volumes # Your Docker environment is now clean echo "Docker environment has been cleaned up." diff --git a/docker-compose.yml b/docker-compose.yml index b80faed..7f84227 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -11,13 +11,6 @@ services: volumes: - .:/app container_name: development - celery: - build: . - command: celery -A run.celery worker --pool=prefork --concurrency=8 --loglevel=info - depends_on: - - api - volumes: - - .:/app volumes: - app: \ No newline at end of file + app: From e5e24178bbfa7cb061e59291f0f3ca2b69479bd0 Mon Sep 17 00:00:00 2001 From: princedalsaniya Date: Sun, 3 Nov 2024 18:51:01 +0530 Subject: [PATCH 11/12] fix: added cors headers --- app/__init__.py | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/app/__init__.py b/app/__init__.py index 9baa42b..d18948e 100755 --- a/app/__init__.py +++ b/app/__init__.py @@ -1,5 +1,5 @@ from dotenv import load_dotenv -from flask import Flask,jsonify +from flask import Flask, jsonify from flask_cors import CORS from flask_limiter import Limiter @@ -12,18 +12,32 @@ def create_app(): app = Flask("KLEO-NETWORK") - CORS(app, resources={r"/api/*": {"origins": "*"}}) + # Enable Cross-Origin Resource Sharing (CORS) globally for all origins (*) + CORS(app, resources={r"/api/*": {"origins": "*"}}, supports_credentials=True) limiter = Limiter( key_func=get_remote_address, app=app, - default_limits=["5000 per day", "2000 per hour"] + default_limits=["5000 per day", "2000 per hour"], ) + @app.errorhandler(RateLimitExceeded) def rate_limit_handler(e): return jsonify(error="Rate limit exceeded. Please try again later."), 429 register_blueprints(app, limiter) + # Ensure correct headers are sent in the response + @app.after_request + def add_cors_headers(response): + response.headers.add("Access-Control-Allow-Origin", "*") + response.headers.add( + "Access-Control-Allow-Headers", "Content-Type,Authorization" + ) + response.headers.add( + "Access-Control-Allow-Methods", "GET,POST,PUT,DELETE,OPTIONS" + ) + return response + return app @@ -33,7 +47,7 @@ def register_blueprints(app, limiter): Keeps the create_app function clean and modular. """ from .core.views.user_v2_views import core as core_user_v2 - + limiter.limit("2000 per hour")(core_user_v2) app.register_blueprint( core_user_v2, name="user_api_v2", url_prefix="/api/v2/core/user" From 06350275d4503be435c74e0e65726132194143fa Mon Sep 17 00:00:00 2001 From: Vaibhav Maheshwari Date: Mon, 4 Nov 2024 17:16:00 +0530 Subject: [PATCH 12/12] feat: tested celery tasks --- LICENSE | 21 - Pipfile | 85 - Pipfile.lock | 2230 -------------------------- app/__init__.py | 40 - app/config.py | 108 -- app/core/views/user_v2_views.py | 226 --- backend/bin/Activate.ps1 | 247 --- backend/bin/activate | 70 - backend/bin/activate.csh | 27 - backend/bin/activate.fish | 69 - backend/bin/celery | 8 - backend/bin/convert-caffe2-to-onnx | 8 - backend/bin/convert-onnx-to-caffe2 | 8 - backend/bin/dotenv | 8 - backend/bin/f2py | 8 - backend/bin/flask | 8 - backend/bin/gunicorn | 8 - backend/bin/huggingface-cli | 8 - backend/bin/isympy | 8 - backend/bin/markdown-it | 8 - backend/bin/nltk | 8 - backend/bin/normalizer | 8 - backend/bin/numpy-config | 8 - backend/bin/pip | 8 - backend/bin/pip3 | 8 - backend/bin/pip3.12 | 8 - backend/bin/pygmentize | 8 - backend/bin/python | 1 - backend/bin/python3 | 1 - backend/bin/python3.12 | 1 - backend/bin/spacy | 8 - backend/bin/tldextract | 8 - backend/bin/torchfrtrace | 8 - backend/bin/torchrun | 8 - backend/bin/tqdm | 8 - backend/bin/transformers-cli | 8 - backend/bin/typer | 8 - backend/bin/weasel | 8 - backend/pyvenv.cfg | 5 - backend/share/man/man1/isympy.1 | 188 --- celerybeat-schedule.db | Bin 16384 -> 0 bytes docker-compose.yml | 16 +- dump.rdb | Bin 485 -> 0 bytes funding.json | 5 - run.py | 18 - runLocal.sh | 12 - thunder-collection_Kleo Connect.json | 494 ------ 47 files changed, 2 insertions(+), 4062 deletions(-) delete mode 100644 LICENSE delete mode 100644 Pipfile delete mode 100644 Pipfile.lock delete mode 100755 app/__init__.py delete mode 100755 app/config.py delete mode 100644 app/core/views/user_v2_views.py delete mode 100644 backend/bin/Activate.ps1 delete mode 100644 backend/bin/activate delete mode 100644 backend/bin/activate.csh delete mode 100644 backend/bin/activate.fish delete mode 100755 backend/bin/celery delete mode 100755 backend/bin/convert-caffe2-to-onnx delete mode 100755 backend/bin/convert-onnx-to-caffe2 delete mode 100755 backend/bin/dotenv delete mode 100755 backend/bin/f2py delete mode 100755 backend/bin/flask delete mode 100755 backend/bin/gunicorn delete mode 100755 backend/bin/huggingface-cli delete mode 100755 backend/bin/isympy delete mode 100755 backend/bin/markdown-it delete mode 100755 backend/bin/nltk delete mode 100755 backend/bin/normalizer delete mode 100755 backend/bin/numpy-config delete mode 100755 backend/bin/pip delete mode 100755 backend/bin/pip3 delete mode 100755 backend/bin/pip3.12 delete mode 100755 backend/bin/pygmentize delete mode 120000 backend/bin/python delete mode 120000 backend/bin/python3 delete mode 120000 backend/bin/python3.12 delete mode 100755 backend/bin/spacy delete mode 100755 backend/bin/tldextract delete mode 100755 backend/bin/torchfrtrace delete mode 100755 backend/bin/torchrun delete mode 100755 backend/bin/tqdm delete mode 100755 backend/bin/transformers-cli delete mode 100755 backend/bin/typer delete mode 100755 backend/bin/weasel delete mode 100644 backend/pyvenv.cfg delete mode 100644 backend/share/man/man1/isympy.1 delete mode 100644 celerybeat-schedule.db delete mode 100644 dump.rdb delete mode 100644 funding.json delete mode 100755 run.py delete mode 100644 runLocal.sh delete mode 100644 thunder-collection_Kleo Connect.json diff --git a/LICENSE b/LICENSE deleted file mode 100644 index 270573a..0000000 --- a/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2020 Idris Rampurawala - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/Pipfile b/Pipfile deleted file mode 100644 index e1916b1..0000000 --- a/Pipfile +++ /dev/null @@ -1,85 +0,0 @@ -[[source]] -name = "pypi" -url = "https://pypi.org/simple" -verify_ssl = true - -[dev-packages] -autopep8 = "*" -flake8 = "*" -ipython = "*" - -[packages] -flask = "==2.3.2" -celery = "==5.2.7" -redis = "==4.5.4" -flask-cors = "==3.0.10" -python-dotenv = "==1.0.0" -marshmallow = "*" -webargs = "==8.2.0" -amqp = "==5.1.1" -appnope = "==0.1.3" -asttokens = "==2.2.1" -autopep8 = "==2.0.2" -backcall = "==0.2.0" -beautifulsoup4 = "==4.12.2" -billiard = "==3.6.4.0" -blinker = "==1.6.2" -boto3 = "==1.28.55" -botocore = "==1.31.55" -bs4 = "==0.0.1" -certifi = "==2023.7.22" -charset-normalizer = "==3.2.0" -click = "==8.1.3" -click-didyoumean = "==0.3.0" -click-plugins = "==1.1.1" -click-repl = "==0.2.0" -decorator = "==5.1.1" -executing = "==1.2.0" -filelock = "==3.12.4" -flake8 = "==6.0.0" -flower = "==2.0.1" -humanize = "==4.8.0" -idna = "==3.4" -ipython = "==8.13.2" -itsdangerous = "==2.1.2" -jedi = "==0.18.2" -jinja2 = "==3.1.2" -jmespath = "==1.0.1" -kombu = "==5.2.4" -markupsafe = "==2.1.2" -matplotlib-inline = "==0.1.6" -mccabe = "==0.7.0" -packaging = "==23.1" -parso = "==0.8.3" -pexpect = "==4.8.0" -pickleshare = "==0.7.5" -prometheus-client = "==0.17.1" -prompt-toolkit = "==3.0.38" -ptyprocess = "==0.7.0" -pure-eval = "==0.2.2" -pycodestyle = "==2.10.0" -pyflakes = "==3.0.1" -pygments = "==2.15.1" -python-dateutil = "==2.8.2" -pytz = "==2023.3" -requests = "==2.31.0" -requests-file = "==1.5.1" -s3transfer = "==0.7.0" -six = "==1.16.0" -soupsieve = "==2.5" -stack-data = "==0.6.2" -tldextract = "==3.6.0" -tornado = "==6.3.3" -traitlets = "==5.9.0" -urllib3 = "==1.26.16" -vine = "==5.0.0" -wcwidth = "==0.2.6" -werkzeug = "==2.3.3" -zipp = "==3.15.0" -pyjwt = "*" -eth-utils = "*" -eth-account = "*" -web3 = "*" - -[requires] -python_version = "3.11" diff --git a/Pipfile.lock b/Pipfile.lock deleted file mode 100644 index f9de563..0000000 --- a/Pipfile.lock +++ /dev/null @@ -1,2230 +0,0 @@ -{ - "_meta": { - "hash": { - "sha256": "d0399fe3c3183a275cfc178608585d8c8d0ad63eadc6ea003b2378c40efe4338" - }, - "pipfile-spec": 6, - "requires": { - "python_version": "3.11" - }, - "sources": [ - { - "name": "pypi", - "url": "https://pypi.org/simple", - "verify_ssl": true - } - ] - }, - "default": { - "aiohttp": { - "hashes": [ - "sha256:0605cc2c0088fcaae79f01c913a38611ad09ba68ff482402d3410bf59039bfb8", - "sha256:0a158704edf0abcac8ac371fbb54044f3270bdbc93e254a82b6c82be1ef08f3c", - "sha256:0cbf56238f4bbf49dab8c2dc2e6b1b68502b1e88d335bea59b3f5b9f4c001475", - "sha256:1732102949ff6087589408d76cd6dea656b93c896b011ecafff418c9661dc4ed", - "sha256:18f634d540dd099c262e9f887c8bbacc959847cfe5da7a0e2e1cf3f14dbf2daf", - "sha256:239f975589a944eeb1bad26b8b140a59a3a320067fb3cd10b75c3092405a1372", - "sha256:2faa61a904b83142747fc6a6d7ad8fccff898c849123030f8e75d5d967fd4a81", - "sha256:320e8618eda64e19d11bdb3bd04ccc0a816c17eaecb7e4945d01deee2a22f95f", - "sha256:38d80498e2e169bc61418ff36170e0aad0cd268da8b38a17c4cf29d254a8b3f1", - "sha256:3916c8692dbd9d55c523374a3b8213e628424d19116ac4308e434dbf6d95bbdd", - "sha256:393c7aba2b55559ef7ab791c94b44f7482a07bf7640d17b341b79081f5e5cd1a", - "sha256:3b7b30258348082826d274504fbc7c849959f1989d86c29bc355107accec6cfb", - "sha256:3fcb4046d2904378e3aeea1df51f697b0467f2aac55d232c87ba162709478c46", - "sha256:4109adee842b90671f1b689901b948f347325045c15f46b39797ae1bf17019de", - "sha256:4558e5012ee03d2638c681e156461d37b7a113fe13970d438d95d10173d25f78", - "sha256:45731330e754f5811c314901cebdf19dd776a44b31927fa4b4dbecab9e457b0c", - "sha256:4715a9b778f4293b9f8ae7a0a7cef9829f02ff8d6277a39d7f40565c737d3771", - "sha256:471f0ef53ccedec9995287f02caf0c068732f026455f07db3f01a46e49d76bbb", - "sha256:4d3ebb9e1316ec74277d19c5f482f98cc65a73ccd5430540d6d11682cd857430", - "sha256:4ff550491f5492ab5ed3533e76b8567f4b37bd2995e780a1f46bca2024223233", - "sha256:52c27110f3862a1afbcb2af4281fc9fdc40327fa286c4625dfee247c3ba90156", - "sha256:55b39c8684a46e56ef8c8d24faf02de4a2b2ac60d26cee93bc595651ff545de9", - "sha256:5a7ee16aab26e76add4afc45e8f8206c95d1d75540f1039b84a03c3b3800dd59", - "sha256:5ca51eadbd67045396bc92a4345d1790b7301c14d1848feaac1d6a6c9289e888", - "sha256:5d6b3f1fabe465e819aed2c421a6743d8debbde79b6a8600739300630a01bf2c", - "sha256:60cdbd56f4cad9f69c35eaac0fbbdf1f77b0ff9456cebd4902f3dd1cf096464c", - "sha256:6380c039ec52866c06d69b5c7aad5478b24ed11696f0e72f6b807cfb261453da", - "sha256:639d0042b7670222f33b0028de6b4e2fad6451462ce7df2af8aee37dcac55424", - "sha256:66331d00fb28dc90aa606d9a54304af76b335ae204d1836f65797d6fe27f1ca2", - "sha256:67c3119f5ddc7261d47163ed86d760ddf0e625cd6246b4ed852e82159617b5fb", - "sha256:694d828b5c41255e54bc2dddb51a9f5150b4eefa9886e38b52605a05d96566e8", - "sha256:6ae79c1bc12c34082d92bf9422764f799aee4746fd7a392db46b7fd357d4a17a", - "sha256:702e2c7c187c1a498a4e2b03155d52658fdd6fda882d3d7fbb891a5cf108bb10", - "sha256:714d4e5231fed4ba2762ed489b4aec07b2b9953cf4ee31e9871caac895a839c0", - "sha256:7b179eea70833c8dee51ec42f3b4097bd6370892fa93f510f76762105568cf09", - "sha256:7f64cbd44443e80094309875d4f9c71d0401e966d191c3d469cde4642bc2e031", - "sha256:82a6a97d9771cb48ae16979c3a3a9a18b600a8505b1115cfe354dfb2054468b4", - "sha256:84dabd95154f43a2ea80deffec9cb44d2e301e38a0c9d331cc4aa0166fe28ae3", - "sha256:8676e8fd73141ded15ea586de0b7cda1542960a7b9ad89b2b06428e97125d4fa", - "sha256:88e311d98cc0bf45b62fc46c66753a83445f5ab20038bcc1b8a1cc05666f428a", - "sha256:8b4f72fbb66279624bfe83fd5eb6aea0022dad8eec62b71e7bf63ee1caadeafe", - "sha256:8c64a6dc3fe5db7b1b4d2b5cb84c4f677768bdc340611eca673afb7cf416ef5a", - "sha256:8cf142aa6c1a751fcb364158fd710b8a9be874b81889c2bd13aa8893197455e2", - "sha256:8d1964eb7617907c792ca00b341b5ec3e01ae8c280825deadbbd678447b127e1", - "sha256:93e22add827447d2e26d67c9ac0161756007f152fdc5210277d00a85f6c92323", - "sha256:9c69e77370cce2d6df5d12b4e12bdcca60c47ba13d1cbbc8645dd005a20b738b", - "sha256:9dbc053ac75ccc63dc3a3cc547b98c7258ec35a215a92bd9f983e0aac95d3d5b", - "sha256:9e3a1ae66e3d0c17cf65c08968a5ee3180c5a95920ec2731f53343fac9bad106", - "sha256:a6ea1a5b409a85477fd8e5ee6ad8f0e40bf2844c270955e09360418cfd09abac", - "sha256:a81b1143d42b66ffc40a441379387076243ef7b51019204fd3ec36b9f69e77d6", - "sha256:ad7f2919d7dac062f24d6f5fe95d401597fbb015a25771f85e692d043c9d7832", - "sha256:afc52b8d969eff14e069a710057d15ab9ac17cd4b6753042c407dcea0e40bf75", - "sha256:b3df71da99c98534be076196791adca8819761f0bf6e08e07fd7da25127150d6", - "sha256:c088c4d70d21f8ca5c0b8b5403fe84a7bc8e024161febdd4ef04575ef35d474d", - "sha256:c26959ca7b75ff768e2776d8055bf9582a6267e24556bb7f7bd29e677932be72", - "sha256:c413016880e03e69d166efb5a1a95d40f83d5a3a648d16486592c49ffb76d0db", - "sha256:c6021d296318cb6f9414b48e6a439a7f5d1f665464da507e8ff640848ee2a58a", - "sha256:c671dc117c2c21a1ca10c116cfcd6e3e44da7fcde37bf83b2be485ab377b25da", - "sha256:c7a4b7a6cf5b6eb11e109a9755fd4fda7d57395f8c575e166d363b9fc3ec4678", - "sha256:c8a02fbeca6f63cb1f0475c799679057fc9268b77075ab7cf3f1c600e81dd46b", - "sha256:cd2adf5c87ff6d8b277814a28a535b59e20bfea40a101db6b3bdca7e9926bc24", - "sha256:d1469f228cd9ffddd396d9948b8c9cd8022b6d1bf1e40c6f25b0fb90b4f893ed", - "sha256:d153f652a687a8e95ad367a86a61e8d53d528b0530ef382ec5aaf533140ed00f", - "sha256:d5ab8e1f6bee051a4bf6195e38a5c13e5e161cb7bad83d8854524798bd9fcd6e", - "sha256:da00da442a0e31f1c69d26d224e1efd3a1ca5bcbf210978a2ca7426dfcae9f58", - "sha256:da22dab31d7180f8c3ac7c7635f3bcd53808f374f6aa333fe0b0b9e14b01f91a", - "sha256:e0ae53e33ee7476dd3d1132f932eeb39bf6125083820049d06edcdca4381f342", - "sha256:e7a6a8354f1b62e15d48e04350f13e726fa08b62c3d7b8401c0a1314f02e3558", - "sha256:e9a3d838441bebcf5cf442700e3963f58b5c33f015341f9ea86dcd7d503c07e2", - "sha256:edea7d15772ceeb29db4aff55e482d4bcfb6ae160ce144f2682de02f6d693551", - "sha256:f22eb3a6c1080d862befa0a89c380b4dafce29dc6cd56083f630073d102eb595", - "sha256:f26383adb94da5e7fb388d441bf09c61e5e35f455a3217bfd790c6b6bc64b2ee", - "sha256:f3c2890ca8c59ee683fd09adf32321a40fe1cf164e3387799efb2acebf090c11", - "sha256:f64fd07515dad67f24b6ea4a66ae2876c01031de91c93075b8093f07c0a2d93d", - "sha256:fcde4c397f673fdec23e6b05ebf8d4751314fa7c24f93334bf1f1364c1c69ac7", - "sha256:ff84aeb864e0fac81f676be9f4685f0527b660f1efdc40dcede3c251ef1e867f" - ], - "markers": "python_version >= '3.8'", - "version": "==3.9.5" - }, - "aiosignal": { - "hashes": [ - "sha256:54cd96e15e1649b75d6c87526a6ff0b6c1b0dd3459f43d9ca11d48c339b68cfc", - "sha256:f8376fb07dd1e86a584e4fcdec80b36b7f81aac666ebc724e2c090300dd83b17" - ], - "markers": "python_version >= '3.7'", - "version": "==1.3.1" - }, - "amqp": { - "hashes": [ - "sha256:2c1b13fecc0893e946c65cbd5f36427861cffa4ea2201d8f6fca22e2a373b5e2", - "sha256:6f0956d2c23d8fa6e7691934d8c3930eadb44972cbbd1a7ae3a520f735d43359" - ], - "index": "pypi", - "markers": "python_version >= '3.6'", - "version": "==5.1.1" - }, - "appnope": { - "hashes": [ - "sha256:02bd91c4de869fbb1e1c50aafc4098827a7a54ab2f39d9dcba6c9547ed920e24", - "sha256:265a455292d0bd8a72453494fa24df5a11eb18373a60c7c0430889f22548605e" - ], - "index": "pypi", - "version": "==0.1.3" - }, - "asttokens": { - "hashes": [ - "sha256:4622110b2a6f30b77e1473affaa97e711bc2f07d3f10848420ff1898edbe94f3", - "sha256:6b0ac9e93fb0335014d382b8fa9b3afa7df546984258005da0b9e7095b3deb1c" - ], - "index": "pypi", - "version": "==2.2.1" - }, - "async-timeout": { - "hashes": [ - "sha256:4640d96be84d82d02ed59ea2b7105a0f7b33abe8703703cd0ab0bf87c427522f", - "sha256:7405140ff1230c310e51dc27b3145b9092d659ce68ff733fb0cefe3ee42be028" - ], - "markers": "python_full_version <= '3.11.2'", - "version": "==4.0.3" - }, - "attrs": { - "hashes": [ - "sha256:935dc3b529c262f6cf76e50877d35a4bd3c1de194fd41f47a2b7ae8f19971f30", - "sha256:99b87a485a5820b23b879f04c2305b44b951b502fd64be915879d77a7e8fc6f1" - ], - "markers": "python_version >= '3.7'", - "version": "==23.2.0" - }, - "autopep8": { - "hashes": [ - "sha256:86e9303b5e5c8160872b2f5ef611161b2893e9bfe8ccc7e2f76385947d57a2f1", - "sha256:f9849cdd62108cb739dbcdbfb7fdcc9a30d1b63c4cc3e1c1f893b5360941b61c" - ], - "index": "pypi", - "markers": "python_version >= '3.6'", - "version": "==2.0.2" - }, - "backcall": { - "hashes": [ - "sha256:5cbdbf27be5e7cfadb448baf0aa95508f91f2bbc6c6437cd9cd06e2a4c215e1e", - "sha256:fbbce6a29f263178a1f7915c1940bde0ec2b2a967566fe1c65c1dfb7422bd255" - ], - "index": "pypi", - "version": "==0.2.0" - }, - "beautifulsoup4": { - "hashes": [ - "sha256:492bbc69dca35d12daac71c4db1bfff0c876c00ef4a2ffacce226d4638eb72da", - "sha256:bd2520ca0d9d7d12694a53d44ac482d181b4ec1888909b035a3dbf40d0f57d4a" - ], - "index": "pypi", - "markers": "python_full_version >= '3.6.0'", - "version": "==4.12.2" - }, - "billiard": { - "hashes": [ - "sha256:299de5a8da28a783d51b197d496bef4f1595dd023a93a4f59dde1886ae905547", - "sha256:87103ea78fa6ab4d5c751c4909bcff74617d985de7fa8b672cf8618afd5a875b" - ], - "index": "pypi", - "version": "==3.6.4.0" - }, - "bitarray": { - "hashes": [ - "sha256:03adaacb79e2fb8f483ab3a67665eec53bb3fd0cd5dbd7358741aef124688db3", - "sha256:052c5073bdcaa9dd10628d99d37a2f33ec09364b86dd1f6281e2d9f8d3db3060", - "sha256:0a99b23ac845a9ea3157782c97465e6ae026fe0c7c4c1ed1d88f759fd6ea52d9", - "sha256:0b3543c8a1cb286ad105f11c25d8d0f712f41c5c55f90be39f0e5a1376c7d0b0", - "sha256:128cc3488176145b9b137fdcf54c1c201809bbb8dd30b260ee40afe915843b43", - "sha256:1bb33673e7f7190a65f0a940c1ef63266abdb391f4a3e544a47542d40a81f536", - "sha256:1e0b63a565e8a311cc8348ff1262d5784df0f79d64031d546411afd5dd7ef67d", - "sha256:1e497c535f2a9b68c69d36631bf2dba243e05eb343b00b9c7bbdc8c601c6802d", - "sha256:1ff9e38356cc803e06134cf8ae9758e836ccd1b793135ef3db53c7c5d71e93bc", - "sha256:21f21e7f56206be346bdbda2a6bdb2165a5e6a11821f88fd4911c5a6bbbdc7e2", - "sha256:2c6be1b651fad8f3adb7a5aa12c65b612cd9b89530969af941844ae680f7d981", - "sha256:2f32948c86e0d230a296686db28191b67ed229756f84728847daa0c7ab7406e3", - "sha256:321841cdad1dd0f58fe62e80e9c9c7531f8ebf8be93f047401e930dc47425b1e", - "sha256:345c76b349ff145549652436235c5532e5bfe9db690db6f0a6ad301c62b9ef21", - "sha256:393cb27fd859af5fd9c16eb26b1c59b17b390ff66b3ae5d0dd258270191baf13", - "sha256:3c4344e96642e2211fb3a50558feff682c31563a4c64529a931769d40832ca79", - "sha256:3fa909cfd675004aed8b4cc9df352415933656e0155a6209d878b7cb615c787e", - "sha256:405b83bed28efaae6d86b6ab287c75712ead0adbfab2a1075a1b7ab47dad4d62", - "sha256:43847799461d8ba71deb4d97b47250c2c2fb66d82cd3cb8b4caf52bb97c03034", - "sha256:461a3dafb9d5fda0bb3385dc507d78b1984b49da3fe4c6d56c869a54373b7008", - "sha256:48a30d718d1a6dfc22a49547450107abe8f4afdf2abdcbe76eb9ed88edc49498", - "sha256:4a22266fb416a3b6c258bf7f83c9fe531ba0b755a56986a81ad69dc0f3bcc070", - "sha256:4b558ce85579b51a2e38703877d1e93b7728a7af664dd45a34e833534f0b755d", - "sha256:4d0e32530f941c41eddfc77600ec89b65184cb909c549336463a738fab3ed285", - "sha256:4da73ebd537d75fa7bccfc2228fcaedea0803f21dd9d0bf0d3b67fef3c4af294", - "sha256:4e2936f090bf3f4d1771f44f9077ebccdbc0415d2b598d51a969afcb519df505", - "sha256:508069a04f658210fdeee85a7a0ca84db4bcc110cbb1d21f692caa13210f24a7", - "sha256:5361413fd2ecfdf44dc8f065177dc6aba97fa80a91b815586cb388763acf7f8d", - "sha256:54e16e32e60973bb83c315de9975bc1bcfc9bd50bb13001c31da159bc49b0ca1", - "sha256:5b7b09489b71f9f1f64c0fa0977e250ec24500767dab7383ba9912495849cadf", - "sha256:5cb378eaa65cd43098f11ff5d27e48ee3b956d2c00d2d6b5bfc2a09fe183be47", - "sha256:5d6fb422772e75385b76ad1c52f45a68bd4efafd8be8d0061c11877be74c4d43", - "sha256:5f4dd3af86dd8a617eb6464622fb64ca86e61ce99b59b5c35d8cd33f9c30603d", - "sha256:603e7d640e54ad764d2b4da6b61e126259af84f253a20f512dd10689566e5478", - "sha256:6067f2f07a7121749858c7daa93c8774325c91590b3e81a299621e347740c2ae", - "sha256:60df43e868a615c7e15117a1e1c2e5e11f48f6457280eba6ddf8fbefbec7da99", - "sha256:64115ccabbdbe279c24c367b629c6b1d3da9ed36c7420129e27c338a3971bfee", - "sha256:6465de861aff7a2559f226b37982007417eab8c3557543879987f58b453519bd", - "sha256:648d2f2685590b0103c67a937c2fb9e09bcc8dfb166f0c7c77bd341902a6f5b3", - "sha256:64b433e26993127732ac7b66a7821b2537c3044355798de7c5fcb0af34b8296f", - "sha256:677e67f50e2559efc677a4366707070933ad5418b8347a603a49a070890b19bc", - "sha256:6ab0f1dbfe5070db98771a56aa14797595acd45a1af9eadfb193851a270e7996", - "sha256:6d70b1579da7fb71be5a841a1f965d19aca0ef27f629cfc07d06b09aafd0a333", - "sha256:6ec84668dd7b937874a2b2c293cd14ba84f37be0d196dead852e0ada9815d807", - "sha256:6f71d92f533770fb027388b35b6e11988ab89242b883f48a6fe7202d238c61f8", - "sha256:76b76a07d4ee611405045c6950a1e24c4362b6b44808d4ad6eea75e0dbc59af4", - "sha256:79a9b8b05f2876c7195a2b698c47528e86a73c61ea203394ff8e7a4434bda5c8", - "sha256:7c1f4bf6ea8eb9d7f30808c2e9894237a96650adfecbf5f3643862dc5982f89e", - "sha256:7dfefdcb0dc6a3ba9936063cec65a74595571b375beabe18742b3d91d087eefd", - "sha256:7e913098de169c7fc890638ce5e171387363eb812579e637c44261460ac00aa2", - "sha256:7eb8be687c50da0b397d5e0ab7ca200b5ebb639e79a9f5e285851d1944c94be9", - "sha256:7eea9318293bc0ea6447e9ebfba600a62f3428bea7e9c6d42170ae4f481dbab3", - "sha256:852e202875dd6dfd6139ce7ec4e98dac2b17d8d25934dc99900831e81c3adaef", - "sha256:856bbe1616425f71c0df5ef2e8755e878d9504d5a531acba58ab4273c52c117a", - "sha256:87580c7f7d14f7ec401eda7adac1e2a25e95153e9c339872c8ae61b3208819a1", - "sha256:87abb7f80c0a042f3fe8e5264da1a2756267450bb602110d5327b8eaff7682e7", - "sha256:90e3a281ffe3897991091b7c46fca38c2675bfd4399ffe79dfeded6c52715436", - "sha256:917905de565d9576eb20f53c797c15ba88b9f4f19728acabec8d01eee1d3756a", - "sha256:9521f49ae121a17c0a41e5112249e6fa7f6a571245b1118de81fb86e7c1bc1ce", - "sha256:962892646599529917ef26266091e4cb3077c88b93c3833a909d68dcc971c4e3", - "sha256:9ae5b0657380d2581e13e46864d147a52c1e2bbac9f59b59c576e42fa7d10cf0", - "sha256:9bbcfc7c279e8d74b076e514e669b683f77b4a2a328585b3f16d4c5259c91222", - "sha256:a035da89c959d98afc813e3c62f052690d67cfd55a36592f25d734b70de7d4b0", - "sha256:a09c4f81635408e3387348f415521d4b94198c562c23330f560596a6aaa26eaf", - "sha256:a23397da092ef0a8cfe729571da64c2fc30ac18243caa82ac7c4f965087506ff", - "sha256:a484061616fb4b158b80789bd3cb511f399d2116525a8b29b6334c68abc2310f", - "sha256:a5cc9381fd54f3c23ae1039f977bfd6d041a5c3c1518104f616643c3a5a73b15", - "sha256:a620d8ce4ea2f1c73c6b6b1399e14cb68c6915e2be3fad5808c2998ed55b4acf", - "sha256:a6cc6545d6d76542aee3d18c1c9485fb7b9812b8df4ebe52c4535ec42081b48f", - "sha256:a8873089be2aa15494c0f81af1209f6e1237d762c5065bc4766c1b84321e1b50", - "sha256:a8f286a51a32323715d77755ed959f94bef13972e9a2fe71b609e40e6d27957e", - "sha256:aeb60962ec4813c539a59fbd4f383509c7222b62c3fb1faa76b54943a613e33a", - "sha256:b069ca9bf728e0c5c5b60e00a89df9af34cc170c695c3bfa3b372d8f40288efb", - "sha256:b0ef2d0a6f1502d38d911d25609b44c6cc27bee0a4363dd295df78b075041b60", - "sha256:b306c4cf66912511422060f7f5e1149c8bdb404f8e00e600561b0749fdd45659", - "sha256:b35bfcb08b7693ab4bf9059111a6e9f14e07d57ac93cd967c420db58ab9b71e1", - "sha256:b44105792fbdcfbda3e26ee88786790fda409da4c71f6c2b73888108cf8f062f", - "sha256:b76ffec27c7450b8a334f967366a9ebadaea66ee43f5b530c12861b1a991f503", - "sha256:ba0734aa300757c924f3faf8148e1b8c247176a0ac8e16aefdf9c1eb19e868f7", - "sha256:bb198c6ed1edbcdaf3d1fa3c9c9d1cdb7e179a5134ef5ee660b53cdec43b34e7", - "sha256:bb6b86cfdfc503e92cb71c68766a24565359136961642504a7cc9faf936d9c88", - "sha256:be94e5a685e60f9d24532af8fe5c268002e9016fa80272a94727f435de3d1003", - "sha256:bed637b674db5e6c8a97a4a321e3e4d73e72d50b5c6b29950008a93069cc64cd", - "sha256:c5b399ae6ab975257ec359f03b48fc00b1c1cd109471e41903548469b8feae5c", - "sha256:c71d1cabdeee0cdda4669168618f0e46b7dace207b29da7b63aaa1adc2b54081", - "sha256:c7d16beeaaab15b075990cd26963d6b5b22e8c5becd131781514a00b8bdd04bd", - "sha256:c8919fdbd3bb596b104388b56ae4b266eb28da1f2f7dff2e1f9334a21840fe96", - "sha256:c9b87baa7bfff9a5878fcc1bffe49ecde6e647a72a64b39a69cd8a2992a43a34", - "sha256:cd56b8ae87ebc71bcacbd73615098e8a8de952ecbb5785b6b4e2b07da8a06e1f", - "sha256:cd926e8ae4d1ed1ac4a8f37212a62886292f692bc1739fde98013bf210c2d175", - "sha256:cf0620da2b81946d28c0b16f3e3704d38e9837d85ee4f0652816e2609aaa4fed", - "sha256:d14c790b91f6cbcd9b718f88ed737c78939980c69ac8c7f03dd7e60040c12951", - "sha256:d4bba8042ea6ab331ade91bc435d81ad72fddb098e49108610b0ce7780c14e68", - "sha256:d527172919cdea1e13994a66d9708a80c3d33dedcf2f0548e4925e600fef3a3a", - "sha256:d656ad38c942e38a470ddbce26b5020e08e1a7ea86b8fd413bb9024b5189993a", - "sha256:d6fe315355cdfe3ed22ef355b8bdc81a805ca4d0949d921576560e5b227a1112", - "sha256:d91406f413ccbf4af6ab5ae7bc78f772a95609f9ddd14123db36ef8c37116d95", - "sha256:dac2399ee2889fbdd3472bfc2ede74c34cceb1ccf29a339964281a16eb1d3188", - "sha256:dbaf2bb71d6027152d603f1d5f31e0dfd5e50173d06f877bec484e5396d4594b", - "sha256:e064caa55a6ed493aca1eda06f8b3f689778bc780a75e6ad7724642ba5dc62f7", - "sha256:e40b3cb9fa1edb4e0175d7c06345c49c7925fe93e39ef55ecb0bc40c906b0c09", - "sha256:e49066d251dbbe4e6e3a5c3937d85b589e40e2669ad0eef41a00f82ec17d844b", - "sha256:e6ec283d4741befb86e8c3ea2e9ac1d17416c956d392107e45263e736954b1f7", - "sha256:e788608ed7767b7b3bbde6d49058bccdf94df0de9ca75d13aa99020cc7e68095", - "sha256:e8a9475d415ef1eaae7942df6f780fa4dcd48fce32825eda591a17abba869299", - "sha256:e8da5355d7d75a52df5b84750989e34e39919ec7e59fafc4c104cc1607ab2d31", - "sha256:ea1923d2e7880f9e1959e035da661767b5a2e16a45dfd57d6aa831e8b65ee1bf", - "sha256:ea816dc8f8e65841a8bbdd30e921edffeeb6f76efe6a1eb0da147b60d539d1cf", - "sha256:eb7a9d8a2e400a1026de341ad48e21670a6261a75b06df162c5c39b0d0e7c8f4", - "sha256:eceb551dfeaf19c609003a69a0cf8264b0efd7abc3791a11dfabf4788daf0d19", - "sha256:ed0f7982f10581bb16553719e5e8f933e003f5b22f7d25a68bdb30fac630a6ff", - "sha256:f00079f8e69d75c2a417de7961a77612bb77ef46c09bc74607d86de4740771ef", - "sha256:f0b84fc50b6dbeced4fa390688c07c10a73222810fb0e08392bd1a1b8259de36", - "sha256:f135e804986b12bf14f2cd1eb86674c47dea86c4c5f0fa13c88978876b97ebe6", - "sha256:f2de9a31c34e543ae089fd2a5ced01292f725190e379921384f695e2d7184bd3", - "sha256:f2f8692f95c9e377eb19ca519d30d1f884b02feb7e115f798de47570a359e43f", - "sha256:f4dcadb7b8034aa3491ee8f5a69b3d9ba9d7d1e55c3cc1fc45be313e708277f8", - "sha256:f4f44381b0a4bdf64416082f4f0e7140377ae962c0ced6f983c6d7bbfc034040", - "sha256:f708e91fdbe443f3bec2df394ed42328fb9b0446dff5cb4199023ac6499e09fd", - "sha256:f9346e98fc2abcef90b942973087e2462af6d3e3710e82938078d3493f7fef52", - "sha256:fc6d3e80dd8239850f2604833ff3168b28909c8a9357abfed95632cccd17e3e7", - "sha256:fe71fd4b76380c2772f96f1e53a524da7063645d647a4fcd3b651bdd80ca0f2e" - ], - "version": "==2.9.2" - }, - "blinker": { - "hashes": [ - "sha256:4afd3de66ef3a9f8067559fb7a1cbe555c17dcbe15971b05d1b625c3e7abe213", - "sha256:c3d739772abb7bc2860abf5f2ec284223d9ad5c76da018234f6f50d6f31ab1f0" - ], - "index": "pypi", - "markers": "python_version >= '3.7'", - "version": "==1.6.2" - }, - "boto3": { - "hashes": [ - "sha256:2680c0e36167e672777110ccef5303d59fa4a6a4f10086f9c14158c5cb008d5c", - "sha256:2ceb644b1df7c3c8907913ab367a9900af79e271b4cfca37b542ec1fa142faf8" - ], - "index": "pypi", - "markers": "python_version >= '3.7'", - "version": "==1.28.55" - }, - "botocore": { - "hashes": [ - "sha256:21ba89c4df083338ec463d9c2a8cffca42a99f9ad5f24bcac1870393b216c5a7", - "sha256:5ec27caa440257619712af0a71524cc2e56110fc502853c3e4046f87b65e42e9" - ], - "index": "pypi", - "markers": "python_version >= '3.7'", - "version": "==1.31.55" - }, - "bs4": { - "hashes": [ - "sha256:36ecea1fd7cc5c0c6e4a1ff075df26d50da647b75376626cc186e2212886dd3a" - ], - "index": "pypi", - "version": "==0.0.1" - }, - "celery": { - "hashes": [ - "sha256:138420c020cd58d6707e6257b6beda91fd39af7afde5d36c6334d175302c0e14", - "sha256:fafbd82934d30f8a004f81e8f7a062e31413a23d444be8ee3326553915958c6d" - ], - "index": "pypi", - "markers": "python_version >= '3.7'", - "version": "==5.2.7" - }, - "certifi": { - "hashes": [ - "sha256:539cc1d13202e33ca466e88b2807e29f4c13049d6d87031a3c110744495cb082", - "sha256:92d6037539857d8206b8f6ae472e8b77db8058fec5937a1ef3f54304089edbb9" - ], - "index": "pypi", - "markers": "python_version >= '3.6'", - "version": "==2023.7.22" - }, - "charset-normalizer": { - "hashes": [ - "sha256:04e57ab9fbf9607b77f7d057974694b4f6b142da9ed4a199859d9d4d5c63fe96", - "sha256:09393e1b2a9461950b1c9a45d5fd251dc7c6f228acab64da1c9c0165d9c7765c", - "sha256:0b87549028f680ca955556e3bd57013ab47474c3124dc069faa0b6545b6c9710", - "sha256:1000fba1057b92a65daec275aec30586c3de2401ccdcd41f8a5c1e2c87078706", - "sha256:1249cbbf3d3b04902ff081ffbb33ce3377fa6e4c7356f759f3cd076cc138d020", - "sha256:1920d4ff15ce893210c1f0c0e9d19bfbecb7983c76b33f046c13a8ffbd570252", - "sha256:193cbc708ea3aca45e7221ae58f0fd63f933753a9bfb498a3b474878f12caaad", - "sha256:1a100c6d595a7f316f1b6f01d20815d916e75ff98c27a01ae817439ea7726329", - "sha256:1f30b48dd7fa1474554b0b0f3fdfdd4c13b5c737a3c6284d3cdc424ec0ffff3a", - "sha256:203f0c8871d5a7987be20c72442488a0b8cfd0f43b7973771640fc593f56321f", - "sha256:246de67b99b6851627d945db38147d1b209a899311b1305dd84916f2b88526c6", - "sha256:2dee8e57f052ef5353cf608e0b4c871aee320dd1b87d351c28764fc0ca55f9f4", - "sha256:2efb1bd13885392adfda4614c33d3b68dee4921fd0ac1d3988f8cbb7d589e72a", - "sha256:2f4ac36d8e2b4cc1aa71df3dd84ff8efbe3bfb97ac41242fbcfc053c67434f46", - "sha256:3170c9399da12c9dc66366e9d14da8bf7147e1e9d9ea566067bbce7bb74bd9c2", - "sha256:3b1613dd5aee995ec6d4c69f00378bbd07614702a315a2cf6c1d21461fe17c23", - "sha256:3bb3d25a8e6c0aedd251753a79ae98a093c7e7b471faa3aa9a93a81431987ace", - "sha256:3bb7fda7260735efe66d5107fb7e6af6a7c04c7fce9b2514e04b7a74b06bf5dd", - "sha256:41b25eaa7d15909cf3ac4c96088c1f266a9a93ec44f87f1d13d4a0e86c81b982", - "sha256:45de3f87179c1823e6d9e32156fb14c1927fcc9aba21433f088fdfb555b77c10", - "sha256:46fb8c61d794b78ec7134a715a3e564aafc8f6b5e338417cb19fe9f57a5a9bf2", - "sha256:48021783bdf96e3d6de03a6e39a1171ed5bd7e8bb93fc84cc649d11490f87cea", - "sha256:4957669ef390f0e6719db3613ab3a7631e68424604a7b448f079bee145da6e09", - "sha256:5e86d77b090dbddbe78867a0275cb4df08ea195e660f1f7f13435a4649e954e5", - "sha256:6339d047dab2780cc6220f46306628e04d9750f02f983ddb37439ca47ced7149", - "sha256:681eb3d7e02e3c3655d1b16059fbfb605ac464c834a0c629048a30fad2b27489", - "sha256:6c409c0deba34f147f77efaa67b8e4bb83d2f11c8806405f76397ae5b8c0d1c9", - "sha256:7095f6fbfaa55defb6b733cfeb14efaae7a29f0b59d8cf213be4e7ca0b857b80", - "sha256:70c610f6cbe4b9fce272c407dd9d07e33e6bf7b4aa1b7ffb6f6ded8e634e3592", - "sha256:72814c01533f51d68702802d74f77ea026b5ec52793c791e2da806a3844a46c3", - "sha256:7a4826ad2bd6b07ca615c74ab91f32f6c96d08f6fcc3902ceeedaec8cdc3bcd6", - "sha256:7c70087bfee18a42b4040bb9ec1ca15a08242cf5867c58726530bdf3945672ed", - "sha256:855eafa5d5a2034b4621c74925d89c5efef61418570e5ef9b37717d9c796419c", - "sha256:8700f06d0ce6f128de3ccdbc1acaea1ee264d2caa9ca05daaf492fde7c2a7200", - "sha256:89f1b185a01fe560bc8ae5f619e924407efca2191b56ce749ec84982fc59a32a", - "sha256:8b2c760cfc7042b27ebdb4a43a4453bd829a5742503599144d54a032c5dc7e9e", - "sha256:8c2f5e83493748286002f9369f3e6607c565a6a90425a3a1fef5ae32a36d749d", - "sha256:8e098148dd37b4ce3baca71fb394c81dc5d9c7728c95df695d2dca218edf40e6", - "sha256:94aea8eff76ee6d1cdacb07dd2123a68283cb5569e0250feab1240058f53b623", - "sha256:95eb302ff792e12aba9a8b8f8474ab229a83c103d74a750ec0bd1c1eea32e669", - "sha256:9bd9b3b31adcb054116447ea22caa61a285d92e94d710aa5ec97992ff5eb7cf3", - "sha256:9e608aafdb55eb9f255034709e20d5a83b6d60c054df0802fa9c9883d0a937aa", - "sha256:a103b3a7069b62f5d4890ae1b8f0597618f628b286b03d4bc9195230b154bfa9", - "sha256:a386ebe437176aab38c041de1260cd3ea459c6ce5263594399880bbc398225b2", - "sha256:a38856a971c602f98472050165cea2cdc97709240373041b69030be15047691f", - "sha256:a401b4598e5d3f4a9a811f3daf42ee2291790c7f9d74b18d75d6e21dda98a1a1", - "sha256:a7647ebdfb9682b7bb97e2a5e7cb6ae735b1c25008a70b906aecca294ee96cf4", - "sha256:aaf63899c94de41fe3cf934601b0f7ccb6b428c6e4eeb80da72c58eab077b19a", - "sha256:b0dac0ff919ba34d4df1b6131f59ce95b08b9065233446be7e459f95554c0dc8", - "sha256:baacc6aee0b2ef6f3d308e197b5d7a81c0e70b06beae1f1fcacffdbd124fe0e3", - "sha256:bf420121d4c8dce6b889f0e8e4ec0ca34b7f40186203f06a946fa0276ba54029", - "sha256:c04a46716adde8d927adb9457bbe39cf473e1e2c2f5d0a16ceb837e5d841ad4f", - "sha256:c0b21078a4b56965e2b12f247467b234734491897e99c1d51cee628da9786959", - "sha256:c1c76a1743432b4b60ab3358c937a3fe1341c828ae6194108a94c69028247f22", - "sha256:c4983bf937209c57240cff65906b18bb35e64ae872da6a0db937d7b4af845dd7", - "sha256:c4fb39a81950ec280984b3a44f5bd12819953dc5fa3a7e6fa7a80db5ee853952", - "sha256:c57921cda3a80d0f2b8aec7e25c8aa14479ea92b5b51b6876d975d925a2ea346", - "sha256:c8063cf17b19661471ecbdb3df1c84f24ad2e389e326ccaf89e3fb2484d8dd7e", - "sha256:ccd16eb18a849fd8dcb23e23380e2f0a354e8daa0c984b8a732d9cfaba3a776d", - "sha256:cd6dbe0238f7743d0efe563ab46294f54f9bc8f4b9bcf57c3c666cc5bc9d1299", - "sha256:d62e51710986674142526ab9f78663ca2b0726066ae26b78b22e0f5e571238dd", - "sha256:db901e2ac34c931d73054d9797383d0f8009991e723dab15109740a63e7f902a", - "sha256:e03b8895a6990c9ab2cdcd0f2fe44088ca1c65ae592b8f795c3294af00a461c3", - "sha256:e1c8a2f4c69e08e89632defbfabec2feb8a8d99edc9f89ce33c4b9e36ab63037", - "sha256:e4b749b9cc6ee664a3300bb3a273c1ca8068c46be705b6c31cf5d276f8628a94", - "sha256:e6a5bf2cba5ae1bb80b154ed68a3cfa2fa00fde979a7f50d6598d3e17d9ac20c", - "sha256:e857a2232ba53ae940d3456f7533ce6ca98b81917d47adc3c7fd55dad8fab858", - "sha256:ee4006268ed33370957f55bf2e6f4d263eaf4dc3cfc473d1d90baff6ed36ce4a", - "sha256:eef9df1eefada2c09a5e7a40991b9fc6ac6ef20b1372abd48d2794a316dc0449", - "sha256:f058f6963fd82eb143c692cecdc89e075fa0828db2e5b291070485390b2f1c9c", - "sha256:f25c229a6ba38a35ae6e25ca1264621cc25d4d38dca2942a7fce0b67a4efe918", - "sha256:f2a1d0fd4242bd8643ce6f98927cf9c04540af6efa92323e9d3124f57727bfc1", - "sha256:f7560358a6811e52e9c4d142d497f1a6e10103d3a6881f18d04dbce3729c0e2c", - "sha256:f779d3ad205f108d14e99bb3859aa7dd8e9c68874617c72354d7ecaec2a054ac", - "sha256:f87f746ee241d30d6ed93969de31e5ffd09a2961a051e60ae6bddde9ec3583aa" - ], - "index": "pypi", - "markers": "python_full_version >= '3.7.0'", - "version": "==3.2.0" - }, - "ckzg": { - "hashes": [ - "sha256:02f9cc3e38b3702ec5895a1ebf927fd02b8f5c2f93c7cb9e438581b5b74472c8", - "sha256:052d302058d72431acc9dd4a9c76854c8dfce10c698deef5252884e32a1ac7bf", - "sha256:071dc7fc179316ce1bfabaa056156e4e84f312c4560ab7b9529a3b9a84019df3", - "sha256:09043738b029bdf4fdc82041b395cfc6f5b5cf63435e5d4d685d24fd14c834d3", - "sha256:0d7600ce7a73ac41d348712d0c1fe5e4cb6caa329377064cfa3a6fd8fbffb410", - "sha256:0e816af31951b5e94e6bc069f21fe783427c190526e0437e16c4488a34ddcacc", - "sha256:13a8cccf0070a29bc01493179db2e61220ee1a6cb17f8ea41c68a2f043ace87f", - "sha256:145ae31c3d499d1950567bd636dc5b24292b600296b9deb5523bc20d8f7b51c3", - "sha256:155eacc237cb28c9eafda1c47a89e6e4550f1c2e711f2eee21e0bb2f4df75546", - "sha256:19893ee7bd7da8688382cb134cb9ee7bce5c38e3a9386e3ed99bb010487d2d17", - "sha256:1ca8a256cdd56d06bc5ef24caac64845240dbabca402c5a1966d519b2514b4ec", - "sha256:1ec775649daade1b93041aac9c1660c2ad9828b57ccd2eeb5a3074d8f05e544a", - "sha256:1ed8c99cd3d9af596470e0481fd58931007288951719bad026f0dd486dd0ec11", - "sha256:2433a89af4158beddebbdd66fae95b34d40f2467bee8dc40df0333de5e616b5f", - "sha256:27261672154cbd477d84d289845b0022fbdbe2ba45b7a2a2051c345fa04c8334", - "sha256:272adfe471380d10e4a0e1639d877e504555079a60233dd82249c799b15be81e", - "sha256:27be65c88d5d773a30e6f198719cefede7e25cad807384c3d65a09c11616fc9d", - "sha256:283a40c625222560fda3dcb912b666f7d50f9502587b73c4358979f519f1c961", - "sha256:331d49bc72430a3f85ea6ecb55a0d0d65f66a21d61af5783b465906a741366d5", - "sha256:3594470134eda7adf2813ad3f1da55ced98c8a393262f47ce3890c5afa05b23e", - "sha256:3c0afa232d2312e3101aaddb6971b486b0038a0f9171500bc23143f5749eff55", - "sha256:3cdaad2745425d7708e76e8e56a52fdaf5c5cc1cfefd5129d24ff8dbe06a012d", - "sha256:3d2ccd68b0743e20e853e31a08da490a8d38c7f12b9a0c4ee63ef5afa0dc2427", - "sha256:4295acc380f8d42ebea4a4a0a68c424a322bb335a33bad05c72ead8cbb28d118", - "sha256:489763ad92e2175fb6ab455411f03ec104c630470d483e11578bf2e00608f283", - "sha256:4f86cef801d7b0838e17b6ee2f2c9e747447d91ad1220a701baccdf7ef11a3c8", - "sha256:50ca4af4e2f1a1e8b0a7e97b3aef39dedbb0d52d90866ece424f13f8df1b5972", - "sha256:54d71e5ca416bd51c543f9f51e426e6792f8a0280b83aef92faad1b826f401ea", - "sha256:5b29889f5bc5db530f766871c0ff4133e7270ecf63aaa3ca756d3b2731980802", - "sha256:5e86627bc33bc63b8de869d7d5bfa9868619a4f3e4e7082103935c52f56c66b5", - "sha256:5f029822d27c52b9c3dbe5706408b099da779f10929be0422a09a34aa026a872", - "sha256:611c03a170f0f746180eeb0cc28cdc6f954561b8eb9013605a046de86520ee6b", - "sha256:633110a9431231664be2ad32baf10971547f18289d33967654581b9ae9c94a7e", - "sha256:651ba33ee2d7fefff14ca519a72996b733402f8b043fbfef12d5fe2a442d86d8", - "sha256:65311e72780105f239d1d66512629a9f468b7c9f2609b8567fc68963ac638ef9", - "sha256:69e1376284e9a5094d7c4d3e552202d6b32a67c5acc461b0b35718d8ec5c7363", - "sha256:6ea91b0236384f93ad1df01d530672f09e254bd8c3cf097ebf486aebb97f6c8c", - "sha256:74d87eafe561d4bfb544a4f3419d26c56ad7de00f39789ef0fdb09515544d12e", - "sha256:75b2f0ab341f3c33702ce64e1c101116c7462a25686d0b1a0193ca654ad4f96e", - "sha256:7e8d534ddbe785c44cf1cd62ee32d78b4310d66dd70e42851f5468af655b81f5", - "sha256:7e9dc671b0a307ea65d0a216ca496c272dd3c1ed890ddc2a306da49b0d8ffc83", - "sha256:88728fbd410d61bd5d655ac50b842714c38bc34ff717f73592132d28911fc88e", - "sha256:895044069de7010be6c7ee703f03fd7548267a0823cf60b9dd26ec50267dd9e8", - "sha256:8bca5e7c38d913fabc24ad09545f78ba23cfc13e1ac8250644231729ca908549", - "sha256:94f7eb080c00c0ccbd4fafad69f0b35b624a6a229a28e11d365b60b58a072832", - "sha256:96e8281b6d58cf91b9559e1bd38132161d63467500838753364c68e825df2e2c", - "sha256:97c27153fab853f017fed159333b27beeb2e0da834c92c9ecdc26d0e5c3983b3", - "sha256:99694917eb6decefc0d330d9887a89ea770824b2fa76eb830bab5fe57ea5c20c", - "sha256:9d3d049186c9966e9140de39a9979d7adcfe22f8b02d2852c94d3c363235cc18", - "sha256:a2f59da9cb82b6a4be615f2561a255731eededa7ecd6ba4b2f2dedfc918ef137", - "sha256:a66a690d3d1801085d11de6825df47a99b465ff32dbe90be4a3c9f43c577da96", - "sha256:a9ac729c5c6f3d2c030c0bc8c9e10edc253e36f002cfe227292035009965d349", - "sha256:ab29fc61fbd32096b82b02e6b18ae0d7423048d3540b7b90805b16ae10bdb769", - "sha256:ab6a2ba2706b5eaa1ce6bc7c4e72970bf9587e2e0e482e5fb4df1996bccb7a40", - "sha256:abc5a27284db479ead4c053ff086d6e222914f1b0aa08b80eabfa116dbed4f7a", - "sha256:b26799907257c39471cb3665f66f7630797140131606085c2c94a7094ab6ddf2", - "sha256:b874167de1d6de72890a2ad5bd9aa7adbddc41c3409923b59cf4ef27f83f79da", - "sha256:bcc0d2031fcabc4be37e9e602c926ef9347238d2f58c1b07e0c147f60b9e760b", - "sha256:bdd082bc0f2a595e3546658ecbe1ff78fe65b0ab7e619a8197a62d94f46b5b46", - "sha256:bfcc70fb76b3d36125d646110d5001f2aa89c1c09ff5537a4550cdb7951f44d4", - "sha256:c1528bc2b95aac6d184a90b023602c40d7b11b577235848c1b5593c00cf51d37", - "sha256:c16d5ee1ddbbbad0367ff970b3ec9f6d1879e9f928023beda59ae9e16ad99e4c", - "sha256:c3e1a9a72695e777497e95bb2213316a1138f82d1bb5d67b9c029a522d24908e", - "sha256:c49d5dc0918ad912777720035f9820bdbb6c7e7d1898e12506d44ab3c938d525", - "sha256:c67064bbbeba1a6892c9c80b3d0c2a540ff48a5ca5356fdb2a8d998b264e43e6", - "sha256:c732cda00c76b326f39ae97edfc6773dd231b7c77288b38282584a7aee77c3a7", - "sha256:c7e039800e50592580171830e788ef4a1d6bb54300d074ae9f9119e92aefc568", - "sha256:c915e1f2ef51657c3255d8b1e2aea6e0b93348ae316b2b79eaadfb17ad8f514e", - "sha256:d31d7fbe396a51f43375e38c31bc3a96c7996882582f95f3fcfd54acfa7b3ce6", - "sha256:d81e68e84d80084da298471ad5eaddfcc1cf73545cb24e9453550c8186870982", - "sha256:d87a121ace8feb6c9386f247e7e36ef55e584fc8a6b1bc2c60757a59c1efe364", - "sha256:d95e97a0d0f7758119bb905fb5688222b1556de465035614883c42fe4a047d1f", - "sha256:d9e030af7d6acdcb356fddfb095048bc8e880fe4cd70ff2206c64f33bf384a0d", - "sha256:da2d9988781a09a4577ee7ea8f51fe4a94b4422789a523164f5ba3118566ad41", - "sha256:e3cb2f8c767aee57e88944f90848e8689ce43993b9ff21589cfb97a562208fe7", - "sha256:e43741e7453262aa3ba1754623d7864250b33751bd850dd548e3ed6bd1911093", - "sha256:e6bd5006cb3e802744309450183087a6594d50554814eee19065f7064dff7b05", - "sha256:edaea8fb50b01c6c19768d9305ad365639a8cd804754277d5108dcae4808f00b", - "sha256:f37be0054ebb4b8ac6e6d5267290b239b09e7ddc611776051b4c3c4032d161ba", - "sha256:f439c9e5297ae29a700f6d55de1525e2e295dbbb7366f0974c8702fca9e536b9", - "sha256:f769eb2e1056ca396462460079f6849c778f58884bb24b638ff7028dd2120b65", - "sha256:f876783ec654b7b9525503c2a0a1b086e5d4f52ff65cac7e8747769b0c2e5468", - "sha256:fb9d0b09ca1bdb5955b626d6645f811424ae0fcab47699a1a938a3ce0438c25f", - "sha256:fca227ce0ce3427254a113fdb3aed5ecd99c1fc670cb0c60cc8a2154793678e4", - "sha256:fea56f39e48b60c1ff6f751c47489e353d1bd95cae65c429cf5f87735d794431" - ], - "version": "==1.0.2" - }, - "click": { - "hashes": [ - "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e", - "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48" - ], - "index": "pypi", - "markers": "python_version >= '3.7'", - "version": "==8.1.3" - }, - "click-didyoumean": { - "hashes": [ - "sha256:a0713dc7a1de3f06bc0df5a9567ad19ead2d3d5689b434768a6145bff77c0667", - "sha256:f184f0d851d96b6d29297354ed981b7dd71df7ff500d82fa6d11f0856bee8035" - ], - "index": "pypi", - "markers": "python_full_version >= '3.6.2' and python_full_version < '4.0.0'", - "version": "==0.3.0" - }, - "click-plugins": { - "hashes": [ - "sha256:46ab999744a9d831159c3411bb0c79346d94a444df9a3a3742e9ed63645f264b", - "sha256:5d262006d3222f5057fd81e1623d4443e41dcda5dc815c06b442aa3c02889fc8" - ], - "index": "pypi", - "version": "==1.1.1" - }, - "click-repl": { - "hashes": [ - "sha256:94b3fbbc9406a236f176e0506524b2937e4b23b6f4c0c0b2a0a83f8a64e9194b", - "sha256:cd12f68d745bf6151210790540b4cb064c7b13e571bc64b6957d98d120dacfd8" - ], - "index": "pypi", - "version": "==0.2.0" - }, - "colorama": { - "hashes": [ - "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", - "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6" - ], - "markers": "platform_system == 'Windows'", - "version": "==0.4.6" - }, - "cytoolz": { - "hashes": [ - "sha256:01cfb8518828c1189200c02a5010ea404407fb18fd5589e29c126e84bbeadd36", - "sha256:04afa90d9d9d18394c40d9bed48c51433d08b57c042e0e50c8c0f9799735dcbd", - "sha256:08a438701c6141dd34eaf92e9e9a1f66e23a22f7840ef8a371eba274477de85d", - "sha256:0a79d72b08048a0980a59457c239555f111ac0c8bdc140c91a025f124104dbb4", - "sha256:0ba1cbc4d9cd7571c917f88f4a069568e5121646eb5d82b2393b2cf84712cf2a", - "sha256:0cf1e1e96dd86829a0539baf514a9c8473a58fbb415f92401a68e8e52a34ecd5", - "sha256:0d8edfbc694af6c9bda4db56643fb8ed3d14e47bec358c2f1417de9a12d6d1fb", - "sha256:0e9199c9e3fbf380a92b8042c677eb9e7ed4bccb126de5e9c0d26f5888d96788", - "sha256:0fbad1fb9bb47e827d00e01992a099b0ba79facf5e5aa453be066033232ac4b5", - "sha256:131ff4820e5d64a25d7ad3c3556f2d8aa65c66b3f021b03f8a8e98e4180dd808", - "sha256:1651a9bd591a8326329ce1d6336f3129161a36d7061a4d5ea9e5377e033364cf", - "sha256:18cd61e078bd6bffe088e40f1ed02001387c29174750abce79499d26fa57f5eb", - "sha256:1c18e351956f70db9e2d04ff02f28e9a41839250d3f936a4c8a1eabd1c3094d2", - "sha256:1dd70141b32b717696a72b8876e86bc9c6f8eff995c1808e299db3541213ff82", - "sha256:1f501ae1353071fa5d6677437bbeb1aeb5622067dce0977cedc2c5ec5843b202", - "sha256:20d36430d8ac809186736fda735ee7d595b6242bdb35f69b598ef809ebfa5605", - "sha256:27513a5d5b6624372d63313574381d3217a66e7a2626b056c695179623a5cb1a", - "sha256:2905fdccacc64b4beba37f95cab9d792289c80f4d70830b70de2fc66c007ec01", - "sha256:2c6dd75dae3d84fa8988861ab8b1189d2488cb8a9b8653828f9cd6126b5e7abd", - "sha256:33c63186f3bf9d7ef1347bc0537bb9a0b4111a0d7d6e619623cabc18fef0dc3b", - "sha256:37441bf4a2a4e2e0fe9c3b0ea5e72db352f5cca03903977ffc42f6f6c5467be9", - "sha256:3ac4f2fb38bbc67ff1875b7d2f0f162a247f43bd28eb7c9d15e6175a982e558d", - "sha256:4503dc59f4ced53a54643272c61dc305d1dbbfbd7d6bdf296948de9f34c3a282", - "sha256:456395d7aec01db32bf9e6db191d667347c78d8d48e77234521fa1078f60dabb", - "sha256:46f505d4c6eb79585c8ad0b9dc140ef30a138c880e4e3b40230d642690e36366", - "sha256:47feb089506fc66e1593cd9ade3945693a9d089a445fbe9a11385cab200b9f22", - "sha256:4fba0616fcd487e34b8beec1ad9911d192c62e758baa12fcb44448b9b6feae22", - "sha256:534fa66db8564d9b13872d81d54b6b09ae592c585eb826aac235bd6f1830f8ad", - "sha256:55f9bd1ae6c2a27eda5abe2a0b65a83029d2385c5a1da7b8ef47af5905d7e905", - "sha256:56f899758146a52e2f8cfb3fb6f4ca19c1e5814178c3d584de35f9e4d7166d91", - "sha256:581f1ce479769fe7eeb9ae6d87eadb230df8c7c5fff32138162cdd99d7fb8fc3", - "sha256:582c22f97a380211fb36a7b65b1beeb84ea11d82015fa84b054be78580390082", - "sha256:59276021619b432a5c21c01cda8320b9cc7dbc40351ffc478b440bfccd5bbdd3", - "sha256:59b19223e7f7bd7a73ec3aa6fdfb73b579ff09c2bc0b7d26857eec2d01a58c76", - "sha256:6986632d8a969ea1e720990c818dace1a24c11015fd7c59b9fea0b65ef71f726", - "sha256:6c2875bcd1397d0627a09a4f9172fa513185ad302c63758efc15b8eb33cc2a98", - "sha256:6d3bfe45173cc8e6c76206be3a916d8bfd2214fb2965563e288088012f1dabfc", - "sha256:6f6e8207d732651e0204779e1ba5a4925c93081834570411f959b80681f8d333", - "sha256:71b6eb97f6695f7ba8ce69c49b707a351c5f46fd97f5aeb5f6f2fb0d6e72b887", - "sha256:727b01a2004ddb513496507a695e19b5c0cfebcdfcc68349d3efd92a1c297bf4", - "sha256:765b8381d4003ceb1a07896a854eee2c31ebc950a4ae17d1e7a17c2a8feb2a68", - "sha256:780c06110f383344d537f48d9010d79fa4f75070d214fc47f389357dd4f010b6", - "sha256:7ad1331cb68afeec58469c31d944a2100cee14eac221553f0d5218ace1a0b25d", - "sha256:7d267ffc9a36c0a9a58c7e0adc9fa82620f22e4a72533e15dd1361f57fc9accf", - "sha256:800f0526adf9e53d3c6acda748f4def1f048adaa780752f154da5cf22aa488a2", - "sha256:8119bf5961091cfe644784d0bae214e273b3b3a479f93ee3baab97bbd995ccfe", - "sha256:8587c3c3dbe78af90c5025288766ac10dc2240c1e76eb0a93a4e244c265ccefd", - "sha256:86923d823bd19ce35805953b018d436f6b862edd6a7c8b747a13d52b39ed5716", - "sha256:8893223b87c2782bd59f9c4bd5c7bf733edd8728b523c93efb91d7468b486528", - "sha256:8e21932d6d260996f7109f2a40b2586070cb0a0cf1d65781e156326d5ebcc329", - "sha256:921e6d2440ac758c4945c587b1d1d9b781b72737ac0c0ca5d5e02ca1db8bded2", - "sha256:92b6f43f086e5a965d33d62a145ae121b4ccb6e0789ac0acc895ce084fec8c65", - "sha256:92c53d508fb8a4463acc85b322fa24734efdc66933a5c8661bdc862103a3373d", - "sha256:95e878868a172a41fbf6c505a4b967309e6870e22adc7b1c3b19653d062711fa", - "sha256:96a5a0292575c3697121f97cc605baf2fd125120c7dcdf39edd1a135798482ca", - "sha256:96c715404a3825e37fe3966fe84c5f8a1f036e7640b2a02dbed96cac0c933451", - "sha256:99462abd8323c52204a2a0ce62454ce8fa0f4e94b9af397945c12830de73f27e", - "sha256:9bac0adffc1b6b6a4c5f1fd1dd2161afb720bcc771a91016dc6bdba59af0a5d3", - "sha256:9e04d22049233394e0b08193aca9737200b4a2afa28659d957327aa780ddddf2", - "sha256:9e45803d9e75ef90a2f859ef8f7f77614730f4a8ce1b9244375734567299d239", - "sha256:9eef0d23035fa4dcfa21e570961e86c375153a7ee605cdd11a8b088c24f707f6", - "sha256:a1445c91009eb775d479e88954c51d0b4cf9a1e8ce3c503c2672d17252882647", - "sha256:a3e61acfd029bfb81c2c596249b508dfd2b4f72e31b7b53b62e5fb0507dd7293", - "sha256:a447247ed312dd64e3a8d9483841ecc5338ee26d6e6fbd29cd373ed030db0240", - "sha256:a7fde09384d23048a7b4ac889063761e44b89a0b64015393e2d1d21d5c1f534a", - "sha256:a83f4532707963ae1a5108e51fdfe1278cc8724e3301fee48b9e73e1316de64f", - "sha256:b4a52dd2a36b0a91f7aa50ca6c8509057acc481a24255f6cb07b15d339a34e0f", - "sha256:b76f2f50a789c44d6fd7f773ec43d2a8686781cd52236da03f7f7d7998989bee", - "sha256:ba3f843aa89f35467b38c398ae5b980a824fdbdb94065adc6ec7c47a0a22f4c7", - "sha256:ba9002d2f043943744a9dc8e50a47362bcb6e6f360dc0a1abcb19642584d87bb", - "sha256:bbe58e26c84b163beba0fbeacf6b065feabc8f75c6d3fe305550d33f24a2d346", - "sha256:be6feb903d2a08a4ba2e70e950e862fd3be9be9a588b7c38cee4728150a52918", - "sha256:bfa3f8e01bc423a933f2e1c510cbb0632c6787865b5242857cc955cae220d1bf", - "sha256:c51b66ada9bfdb88cf711bf350fcc46f82b83a4683cf2413e633c31a64df6201", - "sha256:c64f8e60c1dd69e4d5e615481f2d57937746f4a6be2d0f86e9e7e3b9e2243b5e", - "sha256:c6b6f11b0d7ed91be53166aeef2a23a799e636625675bb30818f47f41ad31821", - "sha256:c835eab01466cb67d0ce6290601ebef2d82d8d0d0a285ed0d6e46989e4a7a71a", - "sha256:ca6a9a9300d5bda417d9090107c6d2b007683efc59d63cc09aca0e7930a08a85", - "sha256:caf07a97b5220e6334dd32c8b6d8b2bd255ca694eca5dfe914bb5b880ee66cdb", - "sha256:cd88028bb897fba99ddd84f253ca6bef73ecb7bdf3f3cf25bc493f8f97d3c7c5", - "sha256:cee3de65584e915053412cd178729ff510ad5f8f585c21c5890e91028283518f", - "sha256:d028044524ee2e815f36210a793c414551b689d4f4eda28f8bbb0883ad78bf5f", - "sha256:d0976a3fcb81d065473173e9005848218ce03ddb2ec7d40dd6a8d2dba7f1c3ae", - "sha256:d294e5e81ff094fe920fd545052ff30838ea49f9e91227a55ecd9f3ca19774a0", - "sha256:d2d271393c378282727f1231d40391ae93b93ddc0997448acc21dd0cb6a1e56d", - "sha256:d9a38332cfad2a91e89405b7c18b3f00e2edc951c225accbc217597d3e4e9fde", - "sha256:da125221b1fa25c690fcd030a54344cecec80074df018d906fc6a99f46c1e3a6", - "sha256:dc1ca9c610425f9854323669a671fc163300b873731584e258975adf50931164", - "sha256:dd728f4e6051af6af234651df49319da1d813f47894d4c3c8ab7455e01703a37", - "sha256:de74ef266e2679c3bf8b5fc20cee4fc0271ba13ae0d9097b1491c7a9bcadb389", - "sha256:e44f4c25e1e7cf6149b499c74945a14649c8866d36371a2c2d2164e4649e7755", - "sha256:e4d2961644153c5ae186db964aa9f6109da81b12df0f1d3494b4e5cf2c332ee2", - "sha256:e70d9c615e5c9dc10d279d1e32e846085fe1fd6f08d623ddd059a92861f4e3dd", - "sha256:ec9be3e4b6f86ea8b294d34c990c99d2ba6c526ef1e8f46f1d52c263d4f32cd7", - "sha256:ed0cfb9326747759e2ad81cb6e45f20086a273b67ac3a4c00b19efcbab007c60", - "sha256:ee98968d6a66ee83a8ceabf31182189ab5d8598998c8ce69b6d5843daeb2db60", - "sha256:f04037302049cb30033f7fa4e1d0e44afe35ed6bfcf9b380fc11f2a27d3ed697", - "sha256:f1ebe23028eac51251f22ba01dba6587d30aa9c320372ca0c14eeab67118ec3f", - "sha256:f37b60e66378e7a116931d7220f5352186abfcc950d64856038aa2c01944929c", - "sha256:f702e295dddef5f8af4a456db93f114539b8dc2a7a9bc4de7c7e41d169aa6ec3", - "sha256:fdddb9d988405f24035234f1e8d1653ab2e48cc2404226d21b49a129aefd1d25", - "sha256:fe1e1779a39dbe83f13886d2b4b02f8c4b10755e3c8d9a89b630395f49f4f406", - "sha256:fe8c6267caa7ec67bcc37e360f0d8a26bc3bdce510b15b97f2f2e0143bdd3673", - "sha256:fea649f979def23150680de1bd1d09682da3b54932800a0f90f29fc2a6c98ba8" - ], - "markers": "implementation_name == 'cpython'", - "version": "==0.12.3" - }, - "decorator": { - "hashes": [ - "sha256:637996211036b6385ef91435e4fae22989472f9d571faba8927ba8253acbc330", - "sha256:b8c3f85900b9dc423225913c5aace94729fe1fa9763b38939a95226f02d37186" - ], - "index": "pypi", - "markers": "python_version >= '3.5'", - "version": "==5.1.1" - }, - "eth-abi": { - "hashes": [ - "sha256:33ddd756206e90f7ddff1330cc8cac4aa411a824fe779314a0a52abea2c8fc14", - "sha256:84cac2626a7db8b7d9ebe62b0fdca676ab1014cc7f777189e3c0cd721a4c16d8" - ], - "markers": "python_version >= '3.8' and python_version < '4'", - "version": "==5.1.0" - }, - "eth-account": { - "hashes": [ - "sha256:95157c262a9823c1e08be826d4bc304bf32f0c32e80afb38c126a325a64f651a", - "sha256:b43daf2c0ae43f2a24ba754d66889f043fae4d3511559cb26eb0122bae9afbbd" - ], - "index": "pypi", - "markers": "python_version >= '3.8' and python_version < '4'", - "version": "==0.11.2" - }, - "eth-hash": { - "extras": [ - "pycryptodome" - ], - "hashes": [ - "sha256:b8d5a230a2b251f4a291e3164a23a14057c4a6de4b0aa4a16fa4dc9161b57e2f", - "sha256:bacdc705bfd85dadd055ecd35fd1b4f846b671add101427e089a4ca2e8db310a" - ], - "markers": "python_version >= '3.8' and python_version < '4'", - "version": "==0.7.0" - }, - "eth-keyfile": { - "hashes": [ - "sha256:65387378b82fe7e86d7cb9f8d98e6d639142661b2f6f490629da09fddbef6d64", - "sha256:9708bc31f386b52cca0969238ff35b1ac72bd7a7186f2a84b86110d3c973bec1" - ], - "markers": "python_version >= '3.8' and python_version < '4'", - "version": "==0.8.1" - }, - "eth-keys": { - "hashes": [ - "sha256:2b587e4bbb9ac2195215a7ab0c0fb16042b17d4ec50240ed670bbb8f53da7a48", - "sha256:ad13d920a2217a49bed3a1a7f54fb0980f53caf86d3bbab2139fd3330a17b97e" - ], - "markers": "python_version >= '3.8' and python_version < '4'", - "version": "==0.5.1" - }, - "eth-rlp": { - "hashes": [ - "sha256:d61dbda892ee1220f28fb3663c08f6383c305db9f1f5624dc585c9cd05115027", - "sha256:dd76515d71654277377d48876b88e839d61553aaf56952e580bb7cebef2b1517" - ], - "markers": "python_version >= '3.8' and python_version < '4'", - "version": "==1.0.1" - }, - "eth-typing": { - "hashes": [ - "sha256:3f4eface387eefa68761b23743baab8d413d609b4201c4086c64a006be5dbf53", - "sha256:718f8ef8180ac1a15e476f072e4522e7bd4429bdabc71499e3ca79e2219d775c" - ], - "markers": "python_version >= '3.8' and python_version < '4'", - "version": "==4.3.0" - }, - "eth-utils": { - "hashes": [ - "sha256:71c8d10dec7494aeed20fa7a4d52ec2ce4a2e52fdce80aab4f5c3c19f3648b25", - "sha256:ccbbac68a6d65cb6e294c5bcb6c6a5cec79a241c56dc5d9c345ed788c30f8534" - ], - "index": "pypi", - "markers": "python_version >= '3.8' and python_version < '4'", - "version": "==4.1.1" - }, - "executing": { - "hashes": [ - "sha256:0314a69e37426e3608aada02473b4161d4caf5a4b244d1d0c48072b8fee7bacc", - "sha256:19da64c18d2d851112f09c287f8d3dbbdf725ab0e569077efb6cdcbd3497c107" - ], - "index": "pypi", - "version": "==1.2.0" - }, - "filelock": { - "hashes": [ - "sha256:08c21d87ded6e2b9da6728c3dff51baf1dcecf973b768ef35bcbc3447edb9ad4", - "sha256:2e6f249f1f3654291606e046b09f1fd5eac39b360664c27f5aad072012f8bcbd" - ], - "index": "pypi", - "markers": "python_version >= '3.8'", - "version": "==3.12.4" - }, - "flake8": { - "hashes": [ - "sha256:3833794e27ff64ea4e9cf5d410082a8b97ff1a06c16aa3d2027339cd0f1195c7", - "sha256:c61007e76655af75e6785a931f452915b371dc48f56efd765247c8fe68f2b181" - ], - "index": "pypi", - "markers": "python_full_version >= '3.8.1'", - "version": "==6.0.0" - }, - "flask": { - "hashes": [ - "sha256:77fd4e1249d8c9923de34907236b747ced06e5467ecac1a7bb7115ae0e9670b0", - "sha256:8c2f9abd47a9e8df7f0c3f091ce9497d011dc3b31effcf4c85a6e2b50f4114ef" - ], - "index": "pypi", - "markers": "python_version >= '3.8'", - "version": "==2.3.2" - }, - "flask-cors": { - "hashes": [ - "sha256:74efc975af1194fc7891ff5cd85b0f7478be4f7f59fe158102e91abb72bb4438", - "sha256:b60839393f3b84a0f3746f6cdca56c1ad7426aa738b70d6c61375857823181de" - ], - "index": "pypi", - "version": "==3.0.10" - }, - "flower": { - "hashes": [ - "sha256:5ab717b979530770c16afb48b50d2a98d23c3e9fe39851dcf6bc4d01845a02a0", - "sha256:9db2c621eeefbc844c8dd88be64aef61e84e2deb29b271e02ab2b5b9f01068e2" - ], - "index": "pypi", - "markers": "python_version >= '3.7'", - "version": "==2.0.1" - }, - "frozenlist": { - "hashes": [ - "sha256:04ced3e6a46b4cfffe20f9ae482818e34eba9b5fb0ce4056e4cc9b6e212d09b7", - "sha256:0633c8d5337cb5c77acbccc6357ac49a1770b8c487e5b3505c57b949b4b82e98", - "sha256:068b63f23b17df8569b7fdca5517edef76171cf3897eb68beb01341131fbd2ad", - "sha256:0c250a29735d4f15321007fb02865f0e6b6a41a6b88f1f523ca1596ab5f50bd5", - "sha256:1979bc0aeb89b33b588c51c54ab0161791149f2461ea7c7c946d95d5f93b56ae", - "sha256:1a4471094e146b6790f61b98616ab8e44f72661879cc63fa1049d13ef711e71e", - "sha256:1b280e6507ea8a4fa0c0a7150b4e526a8d113989e28eaaef946cc77ffd7efc0a", - "sha256:1d0ce09d36d53bbbe566fe296965b23b961764c0bcf3ce2fa45f463745c04701", - "sha256:20b51fa3f588ff2fe658663db52a41a4f7aa6c04f6201449c6c7c476bd255c0d", - "sha256:23b2d7679b73fe0e5a4560b672a39f98dfc6f60df63823b0a9970525325b95f6", - "sha256:23b701e65c7b36e4bf15546a89279bd4d8675faabc287d06bbcfac7d3c33e1e6", - "sha256:2471c201b70d58a0f0c1f91261542a03d9a5e088ed3dc6c160d614c01649c106", - "sha256:27657df69e8801be6c3638054e202a135c7f299267f1a55ed3a598934f6c0d75", - "sha256:29acab3f66f0f24674b7dc4736477bcd4bc3ad4b896f5f45379a67bce8b96868", - "sha256:32453c1de775c889eb4e22f1197fe3bdfe457d16476ea407472b9442e6295f7a", - "sha256:3a670dc61eb0d0eb7080890c13de3066790f9049b47b0de04007090807c776b0", - "sha256:3e0153a805a98f5ada7e09826255ba99fb4f7524bb81bf6b47fb702666484ae1", - "sha256:410478a0c562d1a5bcc2f7ea448359fcb050ed48b3c6f6f4f18c313a9bdb1826", - "sha256:442acde1e068288a4ba7acfe05f5f343e19fac87bfc96d89eb886b0363e977ec", - "sha256:48f6a4533887e189dae092f1cf981f2e3885175f7a0f33c91fb5b7b682b6bab6", - "sha256:4f57dab5fe3407b6c0c1cc907ac98e8a189f9e418f3b6e54d65a718aaafe3950", - "sha256:4f9c515e7914626b2a2e1e311794b4c35720a0be87af52b79ff8e1429fc25f19", - "sha256:55fdc093b5a3cb41d420884cdaf37a1e74c3c37a31f46e66286d9145d2063bd0", - "sha256:5667ed53d68d91920defdf4035d1cdaa3c3121dc0b113255124bcfada1cfa1b8", - "sha256:590344787a90ae57d62511dd7c736ed56b428f04cd8c161fcc5e7232c130c69a", - "sha256:5a7d70357e7cee13f470c7883a063aae5fe209a493c57d86eb7f5a6f910fae09", - "sha256:5c3894db91f5a489fc8fa6a9991820f368f0b3cbdb9cd8849547ccfab3392d86", - "sha256:5c849d495bf5154cd8da18a9eb15db127d4dba2968d88831aff6f0331ea9bd4c", - "sha256:64536573d0a2cb6e625cf309984e2d873979709f2cf22839bf2d61790b448ad5", - "sha256:693945278a31f2086d9bf3df0fe8254bbeaef1fe71e1351c3bd730aa7d31c41b", - "sha256:6db4667b187a6742b33afbbaf05a7bc551ffcf1ced0000a571aedbb4aa42fc7b", - "sha256:6eb73fa5426ea69ee0e012fb59cdc76a15b1283d6e32e4f8dc4482ec67d1194d", - "sha256:722e1124aec435320ae01ee3ac7bec11a5d47f25d0ed6328f2273d287bc3abb0", - "sha256:7268252af60904bf52c26173cbadc3a071cece75f873705419c8681f24d3edea", - "sha256:74fb4bee6880b529a0c6560885fce4dc95936920f9f20f53d99a213f7bf66776", - "sha256:780d3a35680ced9ce682fbcf4cb9c2bad3136eeff760ab33707b71db84664e3a", - "sha256:82e8211d69a4f4bc360ea22cd6555f8e61a1bd211d1d5d39d3d228b48c83a897", - "sha256:89aa2c2eeb20957be2d950b85974b30a01a762f3308cd02bb15e1ad632e22dc7", - "sha256:8aefbba5f69d42246543407ed2461db31006b0f76c4e32dfd6f42215a2c41d09", - "sha256:96ec70beabbd3b10e8bfe52616a13561e58fe84c0101dd031dc78f250d5128b9", - "sha256:9750cc7fe1ae3b1611bb8cfc3f9ec11d532244235d75901fb6b8e42ce9229dfe", - "sha256:9acbb16f06fe7f52f441bb6f413ebae6c37baa6ef9edd49cdd567216da8600cd", - "sha256:9d3e0c25a2350080e9319724dede4f31f43a6c9779be48021a7f4ebde8b2d742", - "sha256:a06339f38e9ed3a64e4c4e43aec7f59084033647f908e4259d279a52d3757d09", - "sha256:a0cb6f11204443f27a1628b0e460f37fb30f624be6051d490fa7d7e26d4af3d0", - "sha256:a7496bfe1da7fb1a4e1cc23bb67c58fab69311cc7d32b5a99c2007b4b2a0e932", - "sha256:a828c57f00f729620a442881cc60e57cfcec6842ba38e1b19fd3e47ac0ff8dc1", - "sha256:a9b2de4cf0cdd5bd2dee4c4f63a653c61d2408055ab77b151c1957f221cabf2a", - "sha256:b46c8ae3a8f1f41a0d2ef350c0b6e65822d80772fe46b653ab6b6274f61d4a49", - "sha256:b7e3ed87d4138356775346e6845cccbe66cd9e207f3cd11d2f0b9fd13681359d", - "sha256:b7f2f9f912dca3934c1baec2e4585a674ef16fe00218d833856408c48d5beee7", - "sha256:ba60bb19387e13597fb059f32cd4d59445d7b18b69a745b8f8e5db0346f33480", - "sha256:beee944ae828747fd7cb216a70f120767fc9f4f00bacae8543c14a6831673f89", - "sha256:bfa4a17e17ce9abf47a74ae02f32d014c5e9404b6d9ac7f729e01562bbee601e", - "sha256:c037a86e8513059a2613aaba4d817bb90b9d9b6b69aace3ce9c877e8c8ed402b", - "sha256:c302220494f5c1ebeb0912ea782bcd5e2f8308037b3c7553fad0e48ebad6ad82", - "sha256:c6321c9efe29975232da3bd0af0ad216800a47e93d763ce64f291917a381b8eb", - "sha256:c757a9dd70d72b076d6f68efdbb9bc943665ae954dad2801b874c8c69e185068", - "sha256:c99169d4ff810155ca50b4da3b075cbde79752443117d89429595c2e8e37fed8", - "sha256:c9c92be9fd329ac801cc420e08452b70e7aeab94ea4233a4804f0915c14eba9b", - "sha256:cc7b01b3754ea68a62bd77ce6020afaffb44a590c2289089289363472d13aedb", - "sha256:db9e724bebd621d9beca794f2a4ff1d26eed5965b004a97f1f1685a173b869c2", - "sha256:dca69045298ce5c11fd539682cff879cc1e664c245d1c64da929813e54241d11", - "sha256:dd9b1baec094d91bf36ec729445f7769d0d0cf6b64d04d86e45baf89e2b9059b", - "sha256:e02a0e11cf6597299b9f3bbd3f93d79217cb90cfd1411aec33848b13f5c656cc", - "sha256:e6a20a581f9ce92d389a8c7d7c3dd47c81fd5d6e655c8dddf341e14aa48659d0", - "sha256:e7004be74cbb7d9f34553a5ce5fb08be14fb33bc86f332fb71cbe5216362a497", - "sha256:e774d53b1a477a67838a904131c4b0eef6b3d8a651f8b138b04f748fccfefe17", - "sha256:edb678da49d9f72c9f6c609fbe41a5dfb9a9282f9e6a2253d5a91e0fc382d7c0", - "sha256:f146e0911cb2f1da549fc58fc7bcd2b836a44b79ef871980d605ec392ff6b0d2", - "sha256:f56e2333dda1fe0f909e7cc59f021eba0d2307bc6f012a1ccf2beca6ba362439", - "sha256:f9a3ea26252bd92f570600098783d1371354d89d5f6b7dfd87359d669f2109b5", - "sha256:f9aa1878d1083b276b0196f2dfbe00c9b7e752475ed3b682025ff20c1c1f51ac", - "sha256:fb3c2db03683b5767dedb5769b8a40ebb47d6f7f45b1b3e3b4b51ec8ad9d9825", - "sha256:fbeb989b5cc29e8daf7f976b421c220f1b8c731cbf22b9130d8815418ea45887", - "sha256:fde5bd59ab5357e3853313127f4d3565fc7dad314a74d7b5d43c22c6a5ed2ced", - "sha256:fe1a06da377e3a1062ae5fe0926e12b84eceb8a50b350ddca72dc85015873f74" - ], - "markers": "python_version >= '3.8'", - "version": "==1.4.1" - }, - "hexbytes": { - "hashes": [ - "sha256:383595ad75026cf00abd570f44b368c6cdac0c6becfae5c39ff88829877f8a59", - "sha256:a3fe35c6831ee8fafd048c4c086b986075fc14fd46258fa24ecb8d65745f9a9d" - ], - "markers": "python_version >= '3.7' and python_version < '4'", - "version": "==0.3.1" - }, - "humanize": { - "hashes": [ - "sha256:8bc9e2bb9315e61ec06bf690151ae35aeb65651ab091266941edf97c90836404", - "sha256:9783373bf1eec713a770ecaa7c2d7a7902c98398009dfa3d8a2df91eec9311e8" - ], - "index": "pypi", - "markers": "python_version >= '3.8'", - "version": "==4.8.0" - }, - "idna": { - "hashes": [ - "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4", - "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2" - ], - "index": "pypi", - "markers": "python_version >= '3.5'", - "version": "==3.4" - }, - "ipython": { - "hashes": [ - "sha256:7dff3fad32b97f6488e02f87b970f309d082f758d7b7fc252e3b19ee0e432dbb", - "sha256:ffca270240fbd21b06b2974e14a86494d6d29290184e788275f55e0b55914926" - ], - "index": "pypi", - "markers": "python_version >= '3.9'", - "version": "==8.13.2" - }, - "itsdangerous": { - "hashes": [ - "sha256:2c2349112351b88699d8d4b6b075022c0808887cb7ad10069318a8b0bc88db44", - "sha256:5dbbc68b317e5e42f327f9021763545dc3fc3bfe22e6deb96aaf1fc38874156a" - ], - "index": "pypi", - "markers": "python_version >= '3.7'", - "version": "==2.1.2" - }, - "jedi": { - "hashes": [ - "sha256:203c1fd9d969ab8f2119ec0a3342e0b49910045abe6af0a3ae83a5764d54639e", - "sha256:bae794c30d07f6d910d32a7048af09b5a39ed740918da923c6b780790ebac612" - ], - "index": "pypi", - "markers": "python_version >= '3.6'", - "version": "==0.18.2" - }, - "jinja2": { - "hashes": [ - "sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852", - "sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61" - ], - "index": "pypi", - "markers": "python_version >= '3.7'", - "version": "==3.1.2" - }, - "jmespath": { - "hashes": [ - "sha256:02e2e4cc71b5bcab88332eebf907519190dd9e6e82107fa7f83b1003a6252980", - "sha256:90261b206d6defd58fdd5e85f478bf633a2901798906be2ad389150c5c60edbe" - ], - "index": "pypi", - "markers": "python_version >= '3.7'", - "version": "==1.0.1" - }, - "jsonschema": { - "hashes": [ - "sha256:5b22d434a45935119af990552c862e5d6d564e8f6601206b305a61fdf661a2b7", - "sha256:ff4cfd6b1367a40e7bc6411caec72effadd3db0bbe5017de188f2d6108335802" - ], - "markers": "python_version >= '3.8'", - "version": "==4.22.0" - }, - "jsonschema-specifications": { - "hashes": [ - "sha256:48a76787b3e70f5ed53f1160d2b81f586e4ca6d1548c5de7085d1682674764cc", - "sha256:87e4fdf3a94858b8a2ba2778d9ba57d8a9cafca7c7489c46ba0d30a8bc6a9c3c" - ], - "markers": "python_version >= '3.8'", - "version": "==2023.12.1" - }, - "kombu": { - "hashes": [ - "sha256:37cee3ee725f94ea8bb173eaab7c1760203ea53bbebae226328600f9d2799610", - "sha256:8b213b24293d3417bcf0d2f5537b7f756079e3ea232a8386dcc89a59fd2361a4" - ], - "index": "pypi", - "markers": "python_version >= '3.7'", - "version": "==5.2.4" - }, - "lru-dict": { - "hashes": [ - "sha256:00f6e8a3fc91481b40395316a14c94daa0f0a5de62e7e01a7d589f8d29224052", - "sha256:020b93870f8c7195774cbd94f033b96c14f51c57537969965c3af300331724fe", - "sha256:05fb8744f91f58479cbe07ed80ada6696ec7df21ea1740891d4107a8dd99a970", - "sha256:086ce993414f0b28530ded7e004c77dc57c5748fa6da488602aa6e7f79e6210e", - "sha256:0c316dfa3897fabaa1fe08aae89352a3b109e5f88b25529bc01e98ac029bf878", - "sha256:0facf49b053bf4926d92d8d5a46fe07eecd2af0441add0182c7432d53d6da667", - "sha256:1171ad3bff32aa8086778be4a3bdff595cc2692e78685bcce9cb06b96b22dcc2", - "sha256:1184d91cfebd5d1e659d47f17a60185bbf621635ca56dcdc46c6a1745d25df5c", - "sha256:13c56782f19d68ddf4d8db0170041192859616514c706b126d0df2ec72a11bd7", - "sha256:18ee88ada65bd2ffd483023be0fa1c0a6a051ef666d1cd89e921dcce134149f2", - "sha256:203b3e78d03d88f491fa134f85a42919020686b6e6f2d09759b2f5517260c651", - "sha256:20f5f411f7751ad9a2c02e80287cedf69ae032edd321fe696e310d32dd30a1f8", - "sha256:21b3090928c7b6cec509e755cc3ab742154b33660a9b433923bd12c37c448e3e", - "sha256:22147367b296be31cc858bf167c448af02435cac44806b228c9be8117f1bfce4", - "sha256:231d7608f029dda42f9610e5723614a35b1fff035a8060cf7d2be19f1711ace8", - "sha256:25f9e0bc2fe8f41c2711ccefd2871f8a5f50a39e6293b68c3dec576112937aad", - "sha256:287c2115a59c1c9ed0d5d8ae7671e594b1206c36ea9df2fca6b17b86c468ff99", - "sha256:291d13f85224551913a78fe695cde04cbca9dcb1d84c540167c443eb913603c9", - "sha256:312b6b2a30188586fe71358f0f33e4bac882d33f5e5019b26f084363f42f986f", - "sha256:34a3091abeb95e707f381a8b5b7dc8e4ee016316c659c49b726857b0d6d1bd7a", - "sha256:35a142a7d1a4fd5d5799cc4f8ab2fff50a598d8cee1d1c611f50722b3e27874f", - "sha256:3838e33710935da2ade1dd404a8b936d571e29268a70ff4ca5ba758abb3850df", - "sha256:5345bf50e127bd2767e9fd42393635bbc0146eac01f6baf6ef12c332d1a6a329", - "sha256:5919dd04446bc1ee8d6ecda2187deeebfff5903538ae71083e069bc678599446", - "sha256:59f3df78e94e07959f17764e7fa7ca6b54e9296953d2626a112eab08e1beb2db", - "sha256:5b172fce0a0ffc0fa6d282c14256d5a68b5db1e64719c2915e69084c4b6bf555", - "sha256:5c6acbd097b15bead4de8e83e8a1030bb4d8257723669097eac643a301a952f0", - "sha256:5d90a70c53b0566084447c3ef9374cc5a9be886e867b36f89495f211baabd322", - "sha256:604d07c7604b20b3130405d137cae61579578b0e8377daae4125098feebcb970", - "sha256:6b7a031e47421d4b7aa626b8c91c180a9f037f89e5d0a71c4bb7afcf4036c774", - "sha256:6da5b8099766c4da3bf1ed6e7d7f5eff1681aff6b5987d1258a13bd2ed54f0c9", - "sha256:712e71b64da181e1c0a2eaa76cd860265980cd15cb0e0498602b8aa35d5db9f8", - "sha256:71da89e134747e20ed5b8ad5b4ee93fc5b31022c2b71e8176e73c5a44699061b", - "sha256:756230c22257597b7557eaef7f90484c489e9ba78e5bb6ab5a5bcfb6b03cb075", - "sha256:7d3336e901acec897bcd318c42c2b93d5f1d038e67688f497045fc6bad2c0be7", - "sha256:7e51fa6a203fa91d415f3b2900e5748ec8e06ad75777c98cc3aeb3983ca416d7", - "sha256:877801a20f05c467126b55338a4e9fa30e2a141eb7b0b740794571b7d619ee11", - "sha256:87bbad3f5c3de8897b8c1263a9af73bbb6469fb90e7b57225dad89b8ef62cd8d", - "sha256:8bda3a9afd241ee0181661decaae25e5336ce513ac268ab57da737eacaa7871f", - "sha256:8dafc481d2defb381f19b22cc51837e8a42631e98e34b9e0892245cc96593deb", - "sha256:91d577a11b84387013815b1ad0bb6e604558d646003b44c92b3ddf886ad0f879", - "sha256:981ef3edc82da38d39eb60eae225b88a538d47b90cce2e5808846fd2cf64384b", - "sha256:987b73a06bcf5a95d7dc296241c6b1f9bc6cda42586948c9dabf386dc2bef1cd", - "sha256:9e4c85aa8844bdca3c8abac3b7f78da1531c74e9f8b3e4890c6e6d86a5a3f6c0", - "sha256:a3ea7571b6bf2090a85ff037e6593bbafe1a8598d5c3b4560eb56187bcccb4dc", - "sha256:a87bdc291718bbdf9ea4be12ae7af26cbf0706fa62c2ac332748e3116c5510a7", - "sha256:aaecd7085212d0aa4cd855f38b9d61803d6509731138bf798a9594745953245b", - "sha256:ae301c282a499dc1968dd633cfef8771dd84228ae9d40002a3ea990e4ff0c469", - "sha256:afdadd73304c9befaed02eb42f5f09fdc16288de0a08b32b8080f0f0f6350aa6", - "sha256:b20b7c9beb481e92e07368ebfaa363ed7ef61e65ffe6e0edbdbaceb33e134124", - "sha256:b30122e098c80e36d0117810d46459a46313421ce3298709170b687dc1240b02", - "sha256:b55753ee23028ba8644fd22e50de7b8f85fa60b562a0fafaad788701d6131ff8", - "sha256:b5ccfd2291c93746a286c87c3f895165b697399969d24c54804ec3ec559d4e43", - "sha256:b6613daa851745dd22b860651de930275be9d3e9373283a2164992abacb75b62", - "sha256:b710f0f4d7ec4f9fa89dfde7002f80bcd77de8024017e70706b0911ea086e2ef", - "sha256:b9ec7a4a0d6b8297102aa56758434fb1fca276a82ed7362e37817407185c3abb", - "sha256:bb12f19cdf9c4f2d9aa259562e19b188ff34afab28dd9509ff32a3f1c2c29326", - "sha256:bd2cd1b998ea4c8c1dad829fc4fa88aeed4dee555b5e03c132fc618e6123f168", - "sha256:c4da599af36618881748b5db457d937955bb2b4800db891647d46767d636c408", - "sha256:c53b12b89bd7a6c79f0536ff0d0a84fdf4ab5f6252d94b24b9b753bd9ada2ddf", - "sha256:c9617583173a29048e11397f165501edc5ae223504a404b2532a212a71ecc9ed", - "sha256:cd46c94966f631a81ffe33eee928db58e9fbee15baba5923d284aeadc0e0fa76", - "sha256:cd6806313606559e6c7adfa0dbeb30fc5ab625f00958c3d93f84831e7a32b71e", - "sha256:d0dd4cd58220351233002f910e35cc01d30337696b55c6578f71318b137770f9", - "sha256:d0f7ec902a0097ac39f1922c89be9eaccf00eb87751e28915320b4f72912d057", - "sha256:d5bb41bc74b321789803d45b124fc2145c1b3353b4ad43296d9d1d242574969b", - "sha256:d7ab0c10c4fa99dc9e26b04e6b62ac32d2bcaea3aad9b81ec8ce9a7aa32b7b1b", - "sha256:de24b47159e07833aeab517d9cb1c3c5c2d6445cc378b1c2f1d8d15fb4841d63", - "sha256:de906e5486b5c053d15b7731583c25e3c9147c288ac8152a6d1f9bccdec72641", - "sha256:df25a426446197488a6702954dcc1de511deee20c9db730499a2aa83fddf0df1", - "sha256:e25b2e90a032dc248213af7f3f3e975e1934b204f3b16aeeaeaff27a3b65e128", - "sha256:e707d93bae8f0a14e6df1ae8b0f076532b35f00e691995f33132d806a88e5c18", - "sha256:ea2ac3f7a7a2f32f194c84d82a034e66780057fd908b421becd2f173504d040e", - "sha256:ead83ac59a29d6439ddff46e205ce32f8b7f71a6bd8062347f77e232825e3d0a", - "sha256:edad398d5d402c43d2adada390dd83c74e46e020945ff4df801166047013617e", - "sha256:f010cfad3ab10676e44dc72a813c968cd586f37b466d27cde73d1f7f1ba158c2", - "sha256:f404dcc8172da1f28da9b1f0087009578e608a4899b96d244925c4f463201f2a", - "sha256:f54908bf91280a9b8fa6a8c8f3c2f65850ce6acae2852bbe292391628ebca42f", - "sha256:f5d5a5f976b39af73324f2b793862859902ccb9542621856d51a5993064f25e4", - "sha256:f9484016e6765bd295708cccc9def49f708ce07ac003808f69efa386633affb9", - "sha256:fbf36c5a220a85187cacc1fcb7dd87070e04b5fc28df7a43f6842f7c8224a388", - "sha256:fc42882b554a86e564e0b662da47b8a4b32fa966920bd165e27bb8079a323bc1" - ], - "version": "==1.2.0" - }, - "markupsafe": { - "hashes": [ - "sha256:0576fe974b40a400449768941d5d0858cc624e3249dfd1e0c33674e5c7ca7aed", - "sha256:085fd3201e7b12809f9e6e9bc1e5c96a368c8523fad5afb02afe3c051ae4afcc", - "sha256:090376d812fb6ac5f171e5938e82e7f2d7adc2b629101cec0db8b267815c85e2", - "sha256:0b462104ba25f1ac006fdab8b6a01ebbfbce9ed37fd37fd4acd70c67c973e460", - "sha256:137678c63c977754abe9086a3ec011e8fd985ab90631145dfb9294ad09c102a7", - "sha256:1bea30e9bf331f3fef67e0a3877b2288593c98a21ccb2cf29b74c581a4eb3af0", - "sha256:22152d00bf4a9c7c83960521fc558f55a1adbc0631fbb00a9471e097b19d72e1", - "sha256:22731d79ed2eb25059ae3df1dfc9cb1546691cc41f4e3130fe6bfbc3ecbbecfa", - "sha256:2298c859cfc5463f1b64bd55cb3e602528db6fa0f3cfd568d3605c50678f8f03", - "sha256:28057e985dace2f478e042eaa15606c7efccb700797660629da387eb289b9323", - "sha256:2e7821bffe00aa6bd07a23913b7f4e01328c3d5cc0b40b36c0bd81d362faeb65", - "sha256:2ec4f2d48ae59bbb9d1f9d7efb9236ab81429a764dedca114f5fdabbc3788013", - "sha256:340bea174e9761308703ae988e982005aedf427de816d1afe98147668cc03036", - "sha256:40627dcf047dadb22cd25ea7ecfe9cbf3bbbad0482ee5920b582f3809c97654f", - "sha256:40dfd3fefbef579ee058f139733ac336312663c6706d1163b82b3003fb1925c4", - "sha256:4cf06cdc1dda95223e9d2d3c58d3b178aa5dacb35ee7e3bbac10e4e1faacb419", - "sha256:50c42830a633fa0cf9e7d27664637532791bfc31c731a87b202d2d8ac40c3ea2", - "sha256:55f44b440d491028addb3b88f72207d71eeebfb7b5dbf0643f7c023ae1fba619", - "sha256:608e7073dfa9e38a85d38474c082d4281f4ce276ac0010224eaba11e929dd53a", - "sha256:63ba06c9941e46fa389d389644e2d8225e0e3e5ebcc4ff1ea8506dce646f8c8a", - "sha256:65608c35bfb8a76763f37036547f7adfd09270fbdbf96608be2bead319728fcd", - "sha256:665a36ae6f8f20a4676b53224e33d456a6f5a72657d9c83c2aa00765072f31f7", - "sha256:6d6607f98fcf17e534162f0709aaad3ab7a96032723d8ac8750ffe17ae5a0666", - "sha256:7313ce6a199651c4ed9d7e4cfb4aa56fe923b1adf9af3b420ee14e6d9a73df65", - "sha256:7668b52e102d0ed87cb082380a7e2e1e78737ddecdde129acadb0eccc5423859", - "sha256:7df70907e00c970c60b9ef2938d894a9381f38e6b9db73c5be35e59d92e06625", - "sha256:7e007132af78ea9df29495dbf7b5824cb71648d7133cf7848a2a5dd00d36f9ff", - "sha256:835fb5e38fd89328e9c81067fd642b3593c33e1e17e2fdbf77f5676abb14a156", - "sha256:8bca7e26c1dd751236cfb0c6c72d4ad61d986e9a41bbf76cb445f69488b2a2bd", - "sha256:8db032bf0ce9022a8e41a22598eefc802314e81b879ae093f36ce9ddf39ab1ba", - "sha256:99625a92da8229df6d44335e6fcc558a5037dd0a760e11d84be2260e6f37002f", - "sha256:9cad97ab29dfc3f0249b483412c85c8ef4766d96cdf9dcf5a1e3caa3f3661cf1", - "sha256:a4abaec6ca3ad8660690236d11bfe28dfd707778e2442b45addd2f086d6ef094", - "sha256:a6e40afa7f45939ca356f348c8e23048e02cb109ced1eb8420961b2f40fb373a", - "sha256:a6f2fcca746e8d5910e18782f976489939d54a91f9411c32051b4aab2bd7c513", - "sha256:a806db027852538d2ad7555b203300173dd1b77ba116de92da9afbc3a3be3eed", - "sha256:abcabc8c2b26036d62d4c746381a6f7cf60aafcc653198ad678306986b09450d", - "sha256:b8526c6d437855442cdd3d87eede9c425c4445ea011ca38d937db299382e6fa3", - "sha256:bb06feb762bade6bf3c8b844462274db0c76acc95c52abe8dbed28ae3d44a147", - "sha256:c0a33bc9f02c2b17c3ea382f91b4db0e6cde90b63b296422a939886a7a80de1c", - "sha256:c4a549890a45f57f1ebf99c067a4ad0cb423a05544accaf2b065246827ed9603", - "sha256:ca244fa73f50a800cf8c3ebf7fd93149ec37f5cb9596aa8873ae2c1d23498601", - "sha256:cf877ab4ed6e302ec1d04952ca358b381a882fbd9d1b07cccbfd61783561f98a", - "sha256:d9d971ec1e79906046aa3ca266de79eac42f1dbf3612a05dc9368125952bd1a1", - "sha256:da25303d91526aac3672ee6d49a2f3db2d9502a4a60b55519feb1a4c7714e07d", - "sha256:e55e40ff0cc8cc5c07996915ad367fa47da6b3fc091fdadca7f5403239c5fec3", - "sha256:f03a532d7dee1bed20bc4884194a16160a2de9ffc6354b3878ec9682bb623c54", - "sha256:f1cd098434e83e656abf198f103a8207a8187c0fc110306691a2e94a78d0abb2", - "sha256:f2bfb563d0211ce16b63c7cb9395d2c682a23187f54c3d79bfec33e6705473c6", - "sha256:f8ffb705ffcf5ddd0e80b65ddf7bed7ee4f5a441ea7d3419e861a12eaf41af58" - ], - "index": "pypi", - "markers": "python_version >= '3.7'", - "version": "==2.1.2" - }, - "marshmallow": { - "hashes": [ - "sha256:4f57c5e050a54d66361e826f94fba213eb10b67b2fdb02c3e0343ce207ba1662", - "sha256:86ce7fb914aa865001a4b2092c4c2872d13bc347f3d42673272cabfdbad386f1" - ], - "index": "pypi", - "markers": "python_version >= '3.8'", - "version": "==3.21.3" - }, - "matplotlib-inline": { - "hashes": [ - "sha256:f1f41aab5328aa5aaea9b16d083b128102f8712542f819fe7e6a420ff581b311", - "sha256:f887e5f10ba98e8d2b150ddcf4702c1e5f8b3a20005eb0f74bfdbd360ee6f304" - ], - "index": "pypi", - "markers": "python_version >= '3.5'", - "version": "==0.1.6" - }, - "mccabe": { - "hashes": [ - "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325", - "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e" - ], - "index": "pypi", - "markers": "python_version >= '3.6'", - "version": "==0.7.0" - }, - "multidict": { - "hashes": [ - "sha256:01265f5e40f5a17f8241d52656ed27192be03bfa8764d88e8220141d1e4b3556", - "sha256:0275e35209c27a3f7951e1ce7aaf93ce0d163b28948444bec61dd7badc6d3f8c", - "sha256:04bde7a7b3de05732a4eb39c94574db1ec99abb56162d6c520ad26f83267de29", - "sha256:04da1bb8c8dbadf2a18a452639771951c662c5ad03aefe4884775454be322c9b", - "sha256:09a892e4a9fb47331da06948690ae38eaa2426de97b4ccbfafbdcbe5c8f37ff8", - "sha256:0d63c74e3d7ab26de115c49bffc92cc77ed23395303d496eae515d4204a625e7", - "sha256:107c0cdefe028703fb5dafe640a409cb146d44a6ae201e55b35a4af8e95457dd", - "sha256:141b43360bfd3bdd75f15ed811850763555a251e38b2405967f8e25fb43f7d40", - "sha256:14c2976aa9038c2629efa2c148022ed5eb4cb939e15ec7aace7ca932f48f9ba6", - "sha256:19fe01cea168585ba0f678cad6f58133db2aa14eccaf22f88e4a6dccadfad8b3", - "sha256:1d147090048129ce3c453f0292e7697d333db95e52616b3793922945804a433c", - "sha256:1d9ea7a7e779d7a3561aade7d596649fbecfa5c08a7674b11b423783217933f9", - "sha256:215ed703caf15f578dca76ee6f6b21b7603791ae090fbf1ef9d865571039ade5", - "sha256:21fd81c4ebdb4f214161be351eb5bcf385426bf023041da2fd9e60681f3cebae", - "sha256:220dd781e3f7af2c2c1053da9fa96d9cf3072ca58f057f4c5adaaa1cab8fc442", - "sha256:228b644ae063c10e7f324ab1ab6b548bdf6f8b47f3ec234fef1093bc2735e5f9", - "sha256:29bfeb0dff5cb5fdab2023a7a9947b3b4af63e9c47cae2a10ad58394b517fddc", - "sha256:2f4848aa3baa109e6ab81fe2006c77ed4d3cd1e0ac2c1fbddb7b1277c168788c", - "sha256:2faa5ae9376faba05f630d7e5e6be05be22913782b927b19d12b8145968a85ea", - "sha256:2ffc42c922dbfddb4a4c3b438eb056828719f07608af27d163191cb3e3aa6cc5", - "sha256:37b15024f864916b4951adb95d3a80c9431299080341ab9544ed148091b53f50", - "sha256:3cc2ad10255f903656017363cd59436f2111443a76f996584d1077e43ee51182", - "sha256:3d25f19500588cbc47dc19081d78131c32637c25804df8414463ec908631e453", - "sha256:403c0911cd5d5791605808b942c88a8155c2592e05332d2bf78f18697a5fa15e", - "sha256:411bf8515f3be9813d06004cac41ccf7d1cd46dfe233705933dd163b60e37600", - "sha256:425bf820055005bfc8aa9a0b99ccb52cc2f4070153e34b701acc98d201693733", - "sha256:435a0984199d81ca178b9ae2c26ec3d49692d20ee29bc4c11a2a8d4514c67eda", - "sha256:4a6a4f196f08c58c59e0b8ef8ec441d12aee4125a7d4f4fef000ccb22f8d7241", - "sha256:4cc0ef8b962ac7a5e62b9e826bd0cd5040e7d401bc45a6835910ed699037a461", - "sha256:51d035609b86722963404f711db441cf7134f1889107fb171a970c9701f92e1e", - "sha256:53689bb4e102200a4fafa9de9c7c3c212ab40a7ab2c8e474491914d2305f187e", - "sha256:55205d03e8a598cfc688c71ca8ea5f66447164efff8869517f175ea632c7cb7b", - "sha256:5c0631926c4f58e9a5ccce555ad7747d9a9f8b10619621f22f9635f069f6233e", - "sha256:5cb241881eefd96b46f89b1a056187ea8e9ba14ab88ba632e68d7a2ecb7aadf7", - "sha256:60d698e8179a42ec85172d12f50b1668254628425a6bd611aba022257cac1386", - "sha256:612d1156111ae11d14afaf3a0669ebf6c170dbb735e510a7438ffe2369a847fd", - "sha256:6214c5a5571802c33f80e6c84713b2c79e024995b9c5897f794b43e714daeec9", - "sha256:6939c95381e003f54cd4c5516740faba40cf5ad3eeff460c3ad1d3e0ea2549bf", - "sha256:69db76c09796b313331bb7048229e3bee7928eb62bab5e071e9f7fcc4879caee", - "sha256:6bf7a982604375a8d49b6cc1b781c1747f243d91b81035a9b43a2126c04766f5", - "sha256:766c8f7511df26d9f11cd3a8be623e59cca73d44643abab3f8c8c07620524e4a", - "sha256:76c0de87358b192de7ea9649beb392f107dcad9ad27276324c24c91774ca5271", - "sha256:76f067f5121dcecf0d63a67f29080b26c43c71a98b10c701b0677e4a065fbd54", - "sha256:7901c05ead4b3fb75113fb1dd33eb1253c6d3ee37ce93305acd9d38e0b5f21a4", - "sha256:79660376075cfd4b2c80f295528aa6beb2058fd289f4c9252f986751a4cd0496", - "sha256:79a6d2ba910adb2cbafc95dad936f8b9386e77c84c35bc0add315b856d7c3abb", - "sha256:7afcdd1fc07befad18ec4523a782cde4e93e0a2bf71239894b8d61ee578c1319", - "sha256:7be7047bd08accdb7487737631d25735c9a04327911de89ff1b26b81745bd4e3", - "sha256:7c6390cf87ff6234643428991b7359b5f59cc15155695deb4eda5c777d2b880f", - "sha256:7df704ca8cf4a073334e0427ae2345323613e4df18cc224f647f251e5e75a527", - "sha256:85f67aed7bb647f93e7520633d8f51d3cbc6ab96957c71272b286b2f30dc70ed", - "sha256:896ebdcf62683551312c30e20614305f53125750803b614e9e6ce74a96232604", - "sha256:92d16a3e275e38293623ebf639c471d3e03bb20b8ebb845237e0d3664914caef", - "sha256:99f60d34c048c5c2fabc766108c103612344c46e35d4ed9ae0673d33c8fb26e8", - "sha256:9fe7b0653ba3d9d65cbe7698cca585bf0f8c83dbbcc710db9c90f478e175f2d5", - "sha256:a3145cb08d8625b2d3fee1b2d596a8766352979c9bffe5d7833e0503d0f0b5e5", - "sha256:aeaf541ddbad8311a87dd695ed9642401131ea39ad7bc8cf3ef3967fd093b626", - "sha256:b55358304d7a73d7bdf5de62494aaf70bd33015831ffd98bc498b433dfe5b10c", - "sha256:b82cc8ace10ab5bd93235dfaab2021c70637005e1ac787031f4d1da63d493c1d", - "sha256:c0868d64af83169e4d4152ec612637a543f7a336e4a307b119e98042e852ad9c", - "sha256:c1c1496e73051918fcd4f58ff2e0f2f3066d1c76a0c6aeffd9b45d53243702cc", - "sha256:c9bf56195c6bbd293340ea82eafd0071cb3d450c703d2c93afb89f93b8386ccc", - "sha256:cbebcd5bcaf1eaf302617c114aa67569dd3f090dd0ce8ba9e35e9985b41ac35b", - "sha256:cd6c8fca38178e12c00418de737aef1261576bd1b6e8c6134d3e729a4e858b38", - "sha256:ceb3b7e6a0135e092de86110c5a74e46bda4bd4fbfeeb3a3bcec79c0f861e450", - "sha256:cf590b134eb70629e350691ecca88eac3e3b8b3c86992042fb82e3cb1830d5e1", - "sha256:d3eb1ceec286eba8220c26f3b0096cf189aea7057b6e7b7a2e60ed36b373b77f", - "sha256:d65f25da8e248202bd47445cec78e0025c0fe7582b23ec69c3b27a640dd7a8e3", - "sha256:d6f6d4f185481c9669b9447bf9d9cf3b95a0e9df9d169bbc17e363b7d5487755", - "sha256:d84a5c3a5f7ce6db1f999fb9438f686bc2e09d38143f2d93d8406ed2dd6b9226", - "sha256:d946b0a9eb8aaa590df1fe082cee553ceab173e6cb5b03239716338629c50c7a", - "sha256:dce1c6912ab9ff5f179eaf6efe7365c1f425ed690b03341911bf4939ef2f3046", - "sha256:de170c7b4fe6859beb8926e84f7d7d6c693dfe8e27372ce3b76f01c46e489fcf", - "sha256:e02021f87a5b6932fa6ce916ca004c4d441509d33bbdbeca70d05dff5e9d2479", - "sha256:e030047e85cbcedbfc073f71836d62dd5dadfbe7531cae27789ff66bc551bd5e", - "sha256:e0e79d91e71b9867c73323a3444724d496c037e578a0e1755ae159ba14f4f3d1", - "sha256:e4428b29611e989719874670fd152b6625500ad6c686d464e99f5aaeeaca175a", - "sha256:e4972624066095e52b569e02b5ca97dbd7a7ddd4294bf4e7247d52635630dd83", - "sha256:e7be68734bd8c9a513f2b0cfd508802d6609da068f40dc57d4e3494cefc92929", - "sha256:e8e94e6912639a02ce173341ff62cc1201232ab86b8a8fcc05572741a5dc7d93", - "sha256:ea1456df2a27c73ce51120fa2f519f1bea2f4a03a917f4a43c8707cf4cbbae1a", - "sha256:ebd8d160f91a764652d3e51ce0d2956b38efe37c9231cd82cfc0bed2e40b581c", - "sha256:eca2e9d0cc5a889850e9bbd68e98314ada174ff6ccd1129500103df7a94a7a44", - "sha256:edd08e6f2f1a390bf137080507e44ccc086353c8e98c657e666c017718561b89", - "sha256:f285e862d2f153a70586579c15c44656f888806ed0e5b56b64489afe4a2dbfba", - "sha256:f2a1dee728b52b33eebff5072817176c172050d44d67befd681609b4746e1c2e", - "sha256:f7e301075edaf50500f0b341543c41194d8df3ae5caf4702f2095f3ca73dd8da", - "sha256:fb616be3538599e797a2017cccca78e354c767165e8858ab5116813146041a24", - "sha256:fce28b3c8a81b6b36dfac9feb1de115bab619b3c13905b419ec71d03a3fc1423", - "sha256:fe5d7785250541f7f5019ab9cba2c71169dc7d74d0f45253f8313f436458a4ef" - ], - "markers": "python_version >= '3.7'", - "version": "==6.0.5" - }, - "packaging": { - "hashes": [ - "sha256:994793af429502c4ea2ebf6bf664629d07c1a9fe974af92966e4b8d2df7edc61", - "sha256:a392980d2b6cffa644431898be54b0045151319d1e7ec34f0cfed48767dd334f" - ], - "index": "pypi", - "markers": "python_version >= '3.7'", - "version": "==23.1" - }, - "parsimonious": { - "hashes": [ - "sha256:8281600da180ec8ae35427a4ab4f7b82bfec1e3d1e52f80cb60ea82b9512501c", - "sha256:982ab435fabe86519b57f6b35610aa4e4e977e9f02a14353edf4bbc75369fc0f" - ], - "version": "==0.10.0" - }, - "parso": { - "hashes": [ - "sha256:8c07be290bb59f03588915921e29e8a50002acaf2cdc5fa0e0114f91709fafa0", - "sha256:c001d4636cd3aecdaf33cbb40aebb59b094be2a74c556778ef5576c175e19e75" - ], - "index": "pypi", - "markers": "python_version >= '3.6'", - "version": "==0.8.3" - }, - "pexpect": { - "hashes": [ - "sha256:0b48a55dcb3c05f3329815901ea4fc1537514d6ba867a152b581d69ae3710937", - "sha256:fc65a43959d153d0114afe13997d439c22823a27cefceb5ff35c2178c6784c0c" - ], - "index": "pypi", - "version": "==4.8.0" - }, - "pickleshare": { - "hashes": [ - "sha256:87683d47965c1da65cdacaf31c8441d12b8044cdec9aca500cd78fc2c683afca", - "sha256:9649af414d74d4df115d5d718f82acb59c9d418196b7b4290ed47a12ce62df56" - ], - "index": "pypi", - "version": "==0.7.5" - }, - "prometheus-client": { - "hashes": [ - "sha256:21e674f39831ae3f8acde238afd9a27a37d0d2fb5a28ea094f0ce25d2cbf2091", - "sha256:e537f37160f6807b8202a6fc4764cdd19bac5480ddd3e0d463c3002b34462101" - ], - "index": "pypi", - "markers": "python_version >= '3.6'", - "version": "==0.17.1" - }, - "prompt-toolkit": { - "hashes": [ - "sha256:23ac5d50538a9a38c8bde05fecb47d0b403ecd0662857a86f886f798563d5b9b", - "sha256:45ea77a2f7c60418850331366c81cf6b5b9cf4c7fd34616f733c5427e6abbb1f" - ], - "index": "pypi", - "markers": "python_full_version >= '3.7.0'", - "version": "==3.0.38" - }, - "protobuf": { - "hashes": [ - "sha256:25236b69ab4ce1bec413fd4b68a15ef8141794427e0b4dc173e9d5d9dffc3bcd", - "sha256:39309898b912ca6febb0084ea912e976482834f401be35840a008da12d189340", - "sha256:3adc15ec0ff35c5b2d0992f9345b04a540c1e73bfee3ff1643db43cc1d734333", - "sha256:4ac7249a1530a2ed50e24201d6630125ced04b30619262f06224616e0030b6cf", - "sha256:4e38fc29d7df32e01a41cf118b5a968b1efd46b9c41ff515234e794011c78b17", - "sha256:7a97b9c5aed86b9ca289eb5148df6c208ab5bb6906930590961e08f097258107", - "sha256:917ed03c3eb8a2d51c3496359f5b53b4e4b7e40edfbdd3d3f34336e0eef6825a", - "sha256:df5e5b8e39b7d1c25b186ffdf9f44f40f810bbcc9d2b71d9d3156fee5a9adf15", - "sha256:dfddb7537f789002cc4eb00752c92e67885badcc7005566f2c5de9d969d3282d", - "sha256:ee52874a9e69a30271649be88ecbe69d374232e8fd0b4e4b0aaaa87f429f1631", - "sha256:f6abd0f69968792da7460d3c2cfa7d94fd74e1c21df321eb6345b963f9ec3d8d" - ], - "markers": "python_version >= '3.8'", - "version": "==5.27.1" - }, - "ptyprocess": { - "hashes": [ - "sha256:4b41f3967fce3af57cc7e94b888626c18bf37a083e3651ca8feeb66d492fef35", - "sha256:5c5d0a3b48ceee0b48485e0c26037c0acd7d29765ca3fbb5cb3831d347423220" - ], - "index": "pypi", - "version": "==0.7.0" - }, - "pure-eval": { - "hashes": [ - "sha256:01eaab343580944bc56080ebe0a674b39ec44a945e6d09ba7db3cb8cec289350", - "sha256:2b45320af6dfaa1750f543d714b6d1c520a1688dec6fd24d339063ce0aaa9ac3" - ], - "index": "pypi", - "version": "==0.2.2" - }, - "pycodestyle": { - "hashes": [ - "sha256:347187bdb476329d98f695c213d7295a846d1152ff4fe9bacb8a9590b8ee7053", - "sha256:8a4eaf0d0495c7395bdab3589ac2db602797d76207242c17d470186815706610" - ], - "index": "pypi", - "markers": "python_version >= '3.6'", - "version": "==2.10.0" - }, - "pycryptodome": { - "hashes": [ - "sha256:06d6de87c19f967f03b4cf9b34e538ef46e99a337e9a61a77dbe44b2cbcf0690", - "sha256:09609209ed7de61c2b560cc5c8c4fbf892f8b15b1faf7e4cbffac97db1fffda7", - "sha256:210ba1b647837bfc42dd5a813cdecb5b86193ae11a3f5d972b9a0ae2c7e9e4b4", - "sha256:2a1250b7ea809f752b68e3e6f3fd946b5939a52eaeea18c73bdab53e9ba3c2dd", - "sha256:2ab6ab0cb755154ad14e507d1df72de9897e99fd2d4922851a276ccc14f4f1a5", - "sha256:3427d9e5310af6680678f4cce149f54e0bb4af60101c7f2c16fdf878b39ccccc", - "sha256:3cd3ef3aee1079ae44afaeee13393cf68b1058f70576b11439483e34f93cf818", - "sha256:405002eafad114a2f9a930f5db65feef7b53c4784495dd8758069b89baf68eab", - "sha256:417a276aaa9cb3be91f9014e9d18d10e840a7a9b9a9be64a42f553c5b50b4d1d", - "sha256:4401564ebf37dfde45d096974c7a159b52eeabd9969135f0426907db367a652a", - "sha256:49a4c4dc60b78ec41d2afa392491d788c2e06edf48580fbfb0dd0f828af49d25", - "sha256:5601c934c498cd267640b57569e73793cb9a83506f7c73a8ec57a516f5b0b091", - "sha256:6e0e4a987d38cfc2e71b4a1b591bae4891eeabe5fa0f56154f576e26287bfdea", - "sha256:76658f0d942051d12a9bd08ca1b6b34fd762a8ee4240984f7c06ddfb55eaf15a", - "sha256:76cb39afede7055127e35a444c1c041d2e8d2f1f9c121ecef573757ba4cd2c3c", - "sha256:8d6b98d0d83d21fb757a182d52940d028564efe8147baa9ce0f38d057104ae72", - "sha256:9b3ae153c89a480a0ec402e23db8d8d84a3833b65fa4b15b81b83be9d637aab9", - "sha256:a60fedd2b37b4cb11ccb5d0399efe26db9e0dd149016c1cc6c8161974ceac2d6", - "sha256:ac1c7c0624a862f2e53438a15c9259d1655325fc2ec4392e66dc46cdae24d044", - "sha256:acae12b9ede49f38eb0ef76fdec2df2e94aad85ae46ec85be3648a57f0a7db04", - "sha256:acc2614e2e5346a4a4eab6e199203034924313626f9620b7b4b38e9ad74b7e0c", - "sha256:acf6e43fa75aca2d33e93409f2dafe386fe051818ee79ee8a3e21de9caa2ac9e", - "sha256:baee115a9ba6c5d2709a1e88ffe62b73ecc044852a925dcb67713a288c4ec70f", - "sha256:c18b381553638414b38705f07d1ef0a7cf301bc78a5f9bc17a957eb19446834b", - "sha256:d29daa681517f4bc318cd8a23af87e1f2a7bad2fe361e8aa29c77d652a065de4", - "sha256:d5954acfe9e00bc83ed9f5cb082ed22c592fbbef86dc48b907238be64ead5c33", - "sha256:ec0bb1188c1d13426039af8ffcb4dbe3aad1d7680c35a62d8eaf2a529b5d3d4f", - "sha256:ec1f93feb3bb93380ab0ebf8b859e8e5678c0f010d2d78367cf6bc30bfeb148e", - "sha256:f0e6d631bae3f231d3634f91ae4da7a960f7ff87f2865b2d2b831af1dfb04e9a", - "sha256:f35d6cee81fa145333137009d9c8ba90951d7d77b67c79cbe5f03c7eb74d8fe2", - "sha256:f47888542a0633baff535a04726948e876bf1ed880fddb7c10a736fa99146ab3", - "sha256:fb3b87461fa35afa19c971b0a2b7456a7b1db7b4eba9a8424666104925b78128" - ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", - "version": "==3.20.0" - }, - "pyflakes": { - "hashes": [ - "sha256:ec55bf7fe21fff7f1ad2f7da62363d749e2a470500eab1b555334b67aa1ef8cf", - "sha256:ec8b276a6b60bd80defed25add7e439881c19e64850afd9b346283d4165fd0fd" - ], - "index": "pypi", - "markers": "python_version >= '3.6'", - "version": "==3.0.1" - }, - "pygments": { - "hashes": [ - "sha256:8ace4d3c1dd481894b2005f560ead0f9f19ee64fe983366be1a21e171d12775c", - "sha256:db2db3deb4b4179f399a09054b023b6a586b76499d36965813c71aa8ed7b5fd1" - ], - "index": "pypi", - "markers": "python_version >= '3.7'", - "version": "==2.15.1" - }, - "pyjwt": { - "hashes": [ - "sha256:57e28d156e3d5c10088e0c68abb90bfac3df82b40a71bd0daa20c65ccd5c23de", - "sha256:59127c392cc44c2da5bb3192169a91f429924e17aff6534d70fdc02ab3e04320" - ], - "index": "pypi", - "markers": "python_version >= '3.7'", - "version": "==2.8.0" - }, - "python-dateutil": { - "hashes": [ - "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86", - "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9" - ], - "index": "pypi", - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", - "version": "==2.8.2" - }, - "python-dotenv": { - "hashes": [ - "sha256:a8df96034aae6d2d50a4ebe8216326c61c3eb64836776504fcca410e5937a3ba", - "sha256:f5971a9226b701070a4bf2c38c89e5a3f0d64de8debda981d1db98583009122a" - ], - "index": "pypi", - "markers": "python_version >= '3.8'", - "version": "==1.0.0" - }, - "pytz": { - "hashes": [ - "sha256:1d8ce29db189191fb55338ee6d0387d82ab59f3d00eac103412d64e0ebd0c588", - "sha256:a151b3abb88eda1d4e34a9814df37de2a80e301e68ba0fd856fb9b46bfbbbffb" - ], - "index": "pypi", - "version": "==2023.3" - }, - "pyunormalize": { - "hashes": [ - "sha256:cf4a87451a0f1cb76911aa97f432f4579e1f564a2f0c84ce488c73a73901b6c1" - ], - "markers": "python_version >= '3.6'", - "version": "==15.1.0" - }, - "pywin32": { - "hashes": [ - "sha256:06d3420a5155ba65f0b72f2699b5bacf3109f36acbe8923765c22938a69dfc8d", - "sha256:1c73ea9a0d2283d889001998059f5eaaba3b6238f767c9cf2833b13e6a685f65", - "sha256:37257794c1ad39ee9be652da0462dc2e394c8159dfd913a8a4e8eb6fd346da0e", - "sha256:383229d515657f4e3ed1343da8be101000562bf514591ff383ae940cad65458b", - "sha256:39b61c15272833b5c329a2989999dcae836b1eed650252ab1b7bfbe1d59f30f4", - "sha256:5821ec52f6d321aa59e2db7e0a35b997de60c201943557d108af9d4ae1ec7040", - "sha256:70dba0c913d19f942a2db25217d9a1b726c278f483a919f1abfed79c9cf64d3a", - "sha256:72c5f621542d7bdd4fdb716227be0dd3f8565c11b280be6315b06ace35487d36", - "sha256:84f4471dbca1887ea3803d8848a1616429ac94a4a8d05f4bc9c5dcfd42ca99c8", - "sha256:a7639f51c184c0272e93f244eb24dafca9b1855707d94c192d4a0b4c01e1100e", - "sha256:e25fd5b485b55ac9c057f67d94bc203f3f6595078d1fb3b458c9c28b7153a802", - "sha256:e4c092e2589b5cf0d365849e73e02c391c1349958c5ac3e9d5ccb9a28e017b3a", - "sha256:e65028133d15b64d2ed8f06dd9fbc268352478d4f9289e69c190ecd6818b6407", - "sha256:e8ac1ae3601bee6ca9f7cb4b5363bf1c0badb935ef243c4733ff9a393b1690c0" - ], - "markers": "platform_system == 'Windows'", - "version": "==306" - }, - "redis": { - "hashes": [ - "sha256:2c19e6767c474f2e85167909061d525ed65bea9301c0770bb151e041b7ac89a2", - "sha256:73ec35da4da267d6847e47f68730fdd5f62e2ca69e3ef5885c6a78a9374c3893" - ], - "index": "pypi", - "markers": "python_version >= '3.7'", - "version": "==4.5.4" - }, - "referencing": { - "hashes": [ - "sha256:25b42124a6c8b632a425174f24087783efb348a6f1e0008e63cd4466fedf703c", - "sha256:eda6d3234d62814d1c64e305c1331c9a3a6132da475ab6382eaa997b21ee75de" - ], - "markers": "python_version >= '3.8'", - "version": "==0.35.1" - }, - "regex": { - "hashes": [ - "sha256:0721931ad5fe0dda45d07f9820b90b2148ccdd8e45bb9e9b42a146cb4f695649", - "sha256:10002e86e6068d9e1c91eae8295ef690f02f913c57db120b58fdd35a6bb1af35", - "sha256:10e4ce0dca9ae7a66e6089bb29355d4432caed736acae36fef0fdd7879f0b0cb", - "sha256:119af6e56dce35e8dfb5222573b50c89e5508d94d55713c75126b753f834de68", - "sha256:1337b7dbef9b2f71121cdbf1e97e40de33ff114801263b275aafd75303bd62b5", - "sha256:13cdaf31bed30a1e1c2453ef6015aa0983e1366fad2667657dbcac7b02f67133", - "sha256:1595f2d10dff3d805e054ebdc41c124753631b6a471b976963c7b28543cf13b0", - "sha256:16093f563098448ff6b1fa68170e4acbef94e6b6a4e25e10eae8598bb1694b5d", - "sha256:1878b8301ed011704aea4c806a3cadbd76f84dece1ec09cc9e4dc934cfa5d4da", - "sha256:19068a6a79cf99a19ccefa44610491e9ca02c2be3305c7760d3831d38a467a6f", - "sha256:19dfb1c504781a136a80ecd1fff9f16dddf5bb43cec6871778c8a907a085bb3d", - "sha256:1b5269484f6126eee5e687785e83c6b60aad7663dafe842b34691157e5083e53", - "sha256:1c1c174d6ec38d6c8a7504087358ce9213d4332f6293a94fbf5249992ba54efa", - "sha256:2431b9e263af1953c55abbd3e2efca67ca80a3de8a0437cb58e2421f8184717a", - "sha256:287eb7f54fc81546346207c533ad3c2c51a8d61075127d7f6d79aaf96cdee890", - "sha256:2b4c884767504c0e2401babe8b5b7aea9148680d2e157fa28f01529d1f7fcf67", - "sha256:35cb514e137cb3488bce23352af3e12fb0dbedd1ee6e60da053c69fb1b29cc6c", - "sha256:391d7f7f1e409d192dba8bcd42d3e4cf9e598f3979cdaed6ab11288da88cb9f2", - "sha256:3ad070b823ca5890cab606c940522d05d3d22395d432f4aaaf9d5b1653e47ced", - "sha256:3cd7874d57f13bf70078f1ff02b8b0aa48d5b9ed25fc48547516c6aba36f5741", - "sha256:3e507ff1e74373c4d3038195fdd2af30d297b4f0950eeda6f515ae3d84a1770f", - "sha256:455705d34b4154a80ead722f4f185b04c4237e8e8e33f265cd0798d0e44825fa", - "sha256:4a605586358893b483976cffc1723fb0f83e526e8f14c6e6614e75919d9862cf", - "sha256:4babf07ad476aaf7830d77000874d7611704a7fcf68c9c2ad151f5d94ae4bfc4", - "sha256:4eee78a04e6c67e8391edd4dad3279828dd66ac4b79570ec998e2155d2e59fd5", - "sha256:5397de3219a8b08ae9540c48f602996aa6b0b65d5a61683e233af8605c42b0f2", - "sha256:5b5467acbfc153847d5adb21e21e29847bcb5870e65c94c9206d20eb4e99a384", - "sha256:5eaa7ddaf517aa095fa8da0b5015c44d03da83f5bd49c87961e3c997daed0de7", - "sha256:632b01153e5248c134007209b5c6348a544ce96c46005d8456de1d552455b014", - "sha256:64c65783e96e563103d641760664125e91bd85d8e49566ee560ded4da0d3e704", - "sha256:64f18a9a3513a99c4bef0e3efd4c4a5b11228b48aa80743be822b71e132ae4f5", - "sha256:673b5a6da4557b975c6c90198588181029c60793835ce02f497ea817ff647cb2", - "sha256:68811ab14087b2f6e0fc0c2bae9ad689ea3584cad6917fc57be6a48bbd012c49", - "sha256:6e8d717bca3a6e2064fc3a08df5cbe366369f4b052dcd21b7416e6d71620dca1", - "sha256:71a455a3c584a88f654b64feccc1e25876066c4f5ef26cd6dd711308aa538694", - "sha256:72d7a99cd6b8f958e85fc6ca5b37c4303294954eac1376535b03c2a43eb72629", - "sha256:7b59138b219ffa8979013be7bc85bb60c6f7b7575df3d56dc1e403a438c7a3f6", - "sha256:7dbe2467273b875ea2de38ded4eba86cbcbc9a1a6d0aa11dcf7bd2e67859c435", - "sha256:833616ddc75ad595dee848ad984d067f2f31be645d603e4d158bba656bbf516c", - "sha256:87e2a9c29e672fc65523fb47a90d429b70ef72b901b4e4b1bd42387caf0d6835", - "sha256:8fe45aa3f4aa57faabbc9cb46a93363edd6197cbc43523daea044e9ff2fea83e", - "sha256:9e717956dcfd656f5055cc70996ee2cc82ac5149517fc8e1b60261b907740201", - "sha256:9efa1a32ad3a3ea112224897cdaeb6aa00381627f567179c0314f7b65d354c62", - "sha256:9ff11639a8d98969c863d4617595eb5425fd12f7c5ef6621a4b74b71ed8726d5", - "sha256:a094801d379ab20c2135529948cb84d417a2169b9bdceda2a36f5f10977ebc16", - "sha256:a0981022dccabca811e8171f913de05720590c915b033b7e601f35ce4ea7019f", - "sha256:a0bd000c6e266927cb7a1bc39d55be95c4b4f65c5be53e659537537e019232b1", - "sha256:a32b96f15c8ab2e7d27655969a23895eb799de3665fa94349f3b2fbfd547236f", - "sha256:a81e3cfbae20378d75185171587cbf756015ccb14840702944f014e0d93ea09f", - "sha256:ac394ff680fc46b97487941f5e6ae49a9f30ea41c6c6804832063f14b2a5a145", - "sha256:ada150c5adfa8fbcbf321c30c751dc67d2f12f15bd183ffe4ec7cde351d945b3", - "sha256:b2b6f1b3bb6f640c1a92be3bbfbcb18657b125b99ecf141fb3310b5282c7d4ed", - "sha256:b802512f3e1f480f41ab5f2cfc0e2f761f08a1f41092d6718868082fc0d27143", - "sha256:ba68168daedb2c0bab7fd7e00ced5ba90aebf91024dea3c88ad5063c2a562cca", - "sha256:bfc4f82cabe54f1e7f206fd3d30fda143f84a63fe7d64a81558d6e5f2e5aaba9", - "sha256:c0c18345010870e58238790a6779a1219b4d97bd2e77e1140e8ee5d14df071aa", - "sha256:c3bea0ba8b73b71b37ac833a7f3fd53825924165da6a924aec78c13032f20850", - "sha256:c486b4106066d502495b3025a0a7251bf37ea9540433940a23419461ab9f2a80", - "sha256:c49e15eac7c149f3670b3e27f1f28a2c1ddeccd3a2812cba953e01be2ab9b5fe", - "sha256:c6a2b494a76983df8e3d3feea9b9ffdd558b247e60b92f877f93a1ff43d26656", - "sha256:cab12877a9bdafde5500206d1020a584355a97884dfd388af3699e9137bf7388", - "sha256:cac27dcaa821ca271855a32188aa61d12decb6fe45ffe3e722401fe61e323cd1", - "sha256:cdd09d47c0b2efee9378679f8510ee6955d329424c659ab3c5e3a6edea696294", - "sha256:cf2430df4148b08fb4324b848672514b1385ae3807651f3567871f130a728cc3", - "sha256:d0a3d8d6acf0c78a1fff0e210d224b821081330b8524e3e2bc5a68ef6ab5803d", - "sha256:d0c0c0003c10f54a591d220997dd27d953cd9ccc1a7294b40a4be5312be8797b", - "sha256:d1f059a4d795e646e1c37665b9d06062c62d0e8cc3c511fe01315973a6542e40", - "sha256:d347a741ea871c2e278fde6c48f85136c96b8659b632fb57a7d1ce1872547600", - "sha256:d3ee02d9e5f482cc8309134a91eeaacbdd2261ba111b0fef3748eeb4913e6a2c", - "sha256:d99ceffa25ac45d150e30bd9ed14ec6039f2aad0ffa6bb87a5936f5782fc1569", - "sha256:e38a7d4e8f633a33b4c7350fbd8bad3b70bf81439ac67ac38916c4a86b465456", - "sha256:e4682f5ba31f475d58884045c1a97a860a007d44938c4c0895f41d64481edbc9", - "sha256:e5bb9425fe881d578aeca0b2b4b3d314ec88738706f66f219c194d67179337cb", - "sha256:e64198f6b856d48192bf921421fdd8ad8eb35e179086e99e99f711957ffedd6e", - "sha256:e6662686aeb633ad65be2a42b4cb00178b3fbf7b91878f9446075c404ada552f", - "sha256:ec54d5afa89c19c6dd8541a133be51ee1017a38b412b1321ccb8d6ddbeb4cf7d", - "sha256:f5b1dff3ad008dccf18e652283f5e5339d70bf8ba7c98bf848ac33db10f7bc7a", - "sha256:f8ec0c2fea1e886a19c3bee0cd19d862b3aa75dcdfb42ebe8ed30708df64687a", - "sha256:f9ebd0a36102fcad2f03696e8af4ae682793a5d30b46c647eaf280d6cfb32796" - ], - "markers": "python_version >= '3.8'", - "version": "==2024.5.15" - }, - "requests": { - "hashes": [ - "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f", - "sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1" - ], - "index": "pypi", - "markers": "python_version >= '3.7'", - "version": "==2.31.0" - }, - "requests-file": { - "hashes": [ - "sha256:07d74208d3389d01c38ab89ef403af0cfec63957d53a0081d8eca738d0247d8e", - "sha256:dfe5dae75c12481f68ba353183c53a65e6044c923e64c24b2209f6c7570ca953" - ], - "index": "pypi", - "version": "==1.5.1" - }, - "rlp": { - "hashes": [ - "sha256:bcefb11013dfadf8902642337923bd0c786dc8a27cb4c21da6e154e52869ecb1", - "sha256:ff6846c3c27b97ee0492373aa074a7c3046aadd973320f4fffa7ac45564b0258" - ], - "markers": "python_version >= '3.8' and python_version < '4'", - "version": "==4.0.1" - }, - "rpds-py": { - "hashes": [ - "sha256:05f3d615099bd9b13ecf2fc9cf2d839ad3f20239c678f461c753e93755d629ee", - "sha256:06d218939e1bf2ca50e6b0ec700ffe755e5216a8230ab3e87c059ebb4ea06afc", - "sha256:07f2139741e5deb2c5154a7b9629bc5aa48c766b643c1a6750d16f865a82c5fc", - "sha256:08d74b184f9ab6289b87b19fe6a6d1a97fbfea84b8a3e745e87a5de3029bf944", - "sha256:0abeee75434e2ee2d142d650d1e54ac1f8b01e6e6abdde8ffd6eeac6e9c38e20", - "sha256:154bf5c93d79558b44e5b50cc354aa0459e518e83677791e6adb0b039b7aa6a7", - "sha256:17c6d2155e2423f7e79e3bb18151c686d40db42d8645e7977442170c360194d4", - "sha256:1805d5901779662d599d0e2e4159d8a82c0b05faa86ef9222bf974572286b2b6", - "sha256:19ba472b9606c36716062c023afa2484d1e4220548751bda14f725a7de17b4f6", - "sha256:19e515b78c3fc1039dd7da0a33c28c3154458f947f4dc198d3c72db2b6b5dc93", - "sha256:1d54f74f40b1f7aaa595a02ff42ef38ca654b1469bef7d52867da474243cc633", - "sha256:207c82978115baa1fd8d706d720b4a4d2b0913df1c78c85ba73fe6c5804505f0", - "sha256:2625f03b105328729f9450c8badda34d5243231eef6535f80064d57035738360", - "sha256:27bba383e8c5231cd559affe169ca0b96ec78d39909ffd817f28b166d7ddd4d8", - "sha256:2c3caec4ec5cd1d18e5dd6ae5194d24ed12785212a90b37f5f7f06b8bedd7139", - "sha256:2cc7c1a47f3a63282ab0f422d90ddac4aa3034e39fc66a559ab93041e6505da7", - "sha256:2fc24a329a717f9e2448f8cd1f960f9dac4e45b6224d60734edeb67499bab03a", - "sha256:312fe69b4fe1ffbe76520a7676b1e5ac06ddf7826d764cc10265c3b53f96dbe9", - "sha256:32b7daaa3e9389db3695964ce8e566e3413b0c43e3394c05e4b243a4cd7bef26", - "sha256:338dee44b0cef8b70fd2ef54b4e09bb1b97fc6c3a58fea5db6cc083fd9fc2724", - "sha256:352a88dc7892f1da66b6027af06a2e7e5d53fe05924cc2cfc56495b586a10b72", - "sha256:35b2b771b13eee8729a5049c976197ff58a27a3829c018a04341bcf1ae409b2b", - "sha256:38e14fb4e370885c4ecd734f093a2225ee52dc384b86fa55fe3f74638b2cfb09", - "sha256:3c20f05e8e3d4fc76875fc9cb8cf24b90a63f5a1b4c5b9273f0e8225e169b100", - "sha256:3dd3cd86e1db5aadd334e011eba4e29d37a104b403e8ca24dcd6703c68ca55b3", - "sha256:489bdfe1abd0406eba6b3bb4fdc87c7fa40f1031de073d0cfb744634cc8fa261", - "sha256:48c2faaa8adfacefcbfdb5f2e2e7bdad081e5ace8d182e5f4ade971f128e6bb3", - "sha256:4a98a1f0552b5f227a3d6422dbd61bc6f30db170939bd87ed14f3c339aa6c7c9", - "sha256:4adec039b8e2928983f885c53b7cc4cda8965b62b6596501a0308d2703f8af1b", - "sha256:4e0ee01ad8260184db21468a6e1c37afa0529acc12c3a697ee498d3c2c4dcaf3", - "sha256:51584acc5916212e1bf45edd17f3a6b05fe0cbb40482d25e619f824dccb679de", - "sha256:531796fb842b53f2695e94dc338929e9f9dbf473b64710c28af5a160b2a8927d", - "sha256:5463c47c08630007dc0fe99fb480ea4f34a89712410592380425a9b4e1611d8e", - "sha256:5c45a639e93a0c5d4b788b2613bd637468edd62f8f95ebc6fcc303d58ab3f0a8", - "sha256:6031b25fb1b06327b43d841f33842b383beba399884f8228a6bb3df3088485ff", - "sha256:607345bd5912aacc0c5a63d45a1f73fef29e697884f7e861094e443187c02be5", - "sha256:618916f5535784960f3ecf8111581f4ad31d347c3de66d02e728de460a46303c", - "sha256:636a15acc588f70fda1661234761f9ed9ad79ebed3f2125d44be0862708b666e", - "sha256:673fdbbf668dd958eff750e500495ef3f611e2ecc209464f661bc82e9838991e", - "sha256:6afd80f6c79893cfc0574956f78a0add8c76e3696f2d6a15bca2c66c415cf2d4", - "sha256:6b5ff7e1d63a8281654b5e2896d7f08799378e594f09cf3674e832ecaf396ce8", - "sha256:6c4c4c3f878df21faf5fac86eda32671c27889e13570645a9eea0a1abdd50922", - "sha256:6cd8098517c64a85e790657e7b1e509b9fe07487fd358e19431cb120f7d96338", - "sha256:6d1e42d2735d437e7e80bab4d78eb2e459af48c0a46e686ea35f690b93db792d", - "sha256:6e30ac5e329098903262dc5bdd7e2086e0256aa762cc8b744f9e7bf2a427d3f8", - "sha256:70a838f7754483bcdc830444952fd89645569e7452e3226de4a613a4c1793fb2", - "sha256:720edcb916df872d80f80a1cc5ea9058300b97721efda8651efcd938a9c70a72", - "sha256:732672fbc449bab754e0b15356c077cc31566df874964d4801ab14f71951ea80", - "sha256:740884bc62a5e2bbb31e584f5d23b32320fd75d79f916f15a788d527a5e83644", - "sha256:7700936ef9d006b7ef605dc53aa364da2de5a3aa65516a1f3ce73bf82ecfc7ae", - "sha256:7732770412bab81c5a9f6d20aeb60ae943a9b36dcd990d876a773526468e7163", - "sha256:7750569d9526199c5b97e5a9f8d96a13300950d910cf04a861d96f4273d5b104", - "sha256:7f1944ce16401aad1e3f7d312247b3d5de7981f634dc9dfe90da72b87d37887d", - "sha256:81c5196a790032e0fc2464c0b4ab95f8610f96f1f2fa3d4deacce6a79852da60", - "sha256:8352f48d511de5f973e4f2f9412736d7dea76c69faa6d36bcf885b50c758ab9a", - "sha256:8927638a4d4137a289e41d0fd631551e89fa346d6dbcfc31ad627557d03ceb6d", - "sha256:8c7672e9fba7425f79019db9945b16e308ed8bc89348c23d955c8c0540da0a07", - "sha256:8d2e182c9ee01135e11e9676e9a62dfad791a7a467738f06726872374a83db49", - "sha256:910e71711d1055b2768181efa0a17537b2622afeb0424116619817007f8a2b10", - "sha256:942695a206a58d2575033ff1e42b12b2aece98d6003c6bc739fbf33d1773b12f", - "sha256:9437ca26784120a279f3137ee080b0e717012c42921eb07861b412340f85bae2", - "sha256:967342e045564cef76dfcf1edb700b1e20838d83b1aa02ab313e6a497cf923b8", - "sha256:998125738de0158f088aef3cb264a34251908dd2e5d9966774fdab7402edfab7", - "sha256:9e6934d70dc50f9f8ea47081ceafdec09245fd9f6032669c3b45705dea096b88", - "sha256:a3d456ff2a6a4d2adcdf3c1c960a36f4fd2fec6e3b4902a42a384d17cf4e7a65", - "sha256:a7b28c5b066bca9a4eb4e2f2663012debe680f097979d880657f00e1c30875a0", - "sha256:a888e8bdb45916234b99da2d859566f1e8a1d2275a801bb8e4a9644e3c7e7909", - "sha256:aa3679e751408d75a0b4d8d26d6647b6d9326f5e35c00a7ccd82b78ef64f65f8", - "sha256:aaa71ee43a703c321906813bb252f69524f02aa05bf4eec85f0c41d5d62d0f4c", - "sha256:b646bf655b135ccf4522ed43d6902af37d3f5dbcf0da66c769a2b3938b9d8184", - "sha256:b906b5f58892813e5ba5c6056d6a5ad08f358ba49f046d910ad992196ea61397", - "sha256:b9bb1f182a97880f6078283b3505a707057c42bf55d8fca604f70dedfdc0772a", - "sha256:bd1105b50ede37461c1d51b9698c4f4be6e13e69a908ab7751e3807985fc0346", - "sha256:bf18932d0003c8c4d51a39f244231986ab23ee057d235a12b2684ea26a353590", - "sha256:c273e795e7a0f1fddd46e1e3cb8be15634c29ae8ff31c196debb620e1edb9333", - "sha256:c69882964516dc143083d3795cb508e806b09fc3800fd0d4cddc1df6c36e76bb", - "sha256:c827576e2fa017a081346dce87d532a5310241648eb3700af9a571a6e9fc7e74", - "sha256:cbfbea39ba64f5e53ae2915de36f130588bba71245b418060ec3330ebf85678e", - "sha256:ce0bb20e3a11bd04461324a6a798af34d503f8d6f1aa3d2aa8901ceaf039176d", - "sha256:d0cee71bc618cd93716f3c1bf56653740d2d13ddbd47673efa8bf41435a60daa", - "sha256:d21be4770ff4e08698e1e8e0bce06edb6ea0626e7c8f560bc08222880aca6a6f", - "sha256:d31dea506d718693b6b2cffc0648a8929bdc51c70a311b2770f09611caa10d53", - "sha256:d44607f98caa2961bab4fa3c4309724b185b464cdc3ba6f3d7340bac3ec97cc1", - "sha256:d58ad6317d188c43750cb76e9deacf6051d0f884d87dc6518e0280438648a9ac", - "sha256:d70129cef4a8d979caa37e7fe957202e7eee8ea02c5e16455bc9808a59c6b2f0", - "sha256:d85164315bd68c0806768dc6bb0429c6f95c354f87485ee3593c4f6b14def2bd", - "sha256:d960de62227635d2e61068f42a6cb6aae91a7fe00fca0e3aeed17667c8a34611", - "sha256:dc48b479d540770c811fbd1eb9ba2bb66951863e448efec2e2c102625328e92f", - "sha256:e1735502458621921cee039c47318cb90b51d532c2766593be6207eec53e5c4c", - "sha256:e2be6e9dd4111d5b31ba3b74d17da54a8319d8168890fbaea4b9e5c3de630ae5", - "sha256:e4c39ad2f512b4041343ea3c7894339e4ca7839ac38ca83d68a832fc8b3748ab", - "sha256:ed402d6153c5d519a0faf1bb69898e97fb31613b49da27a84a13935ea9164dfc", - "sha256:ee17cd26b97d537af8f33635ef38be873073d516fd425e80559f4585a7b90c43", - "sha256:f3027be483868c99b4985fda802a57a67fdf30c5d9a50338d9db646d590198da", - "sha256:f5bab211605d91db0e2995a17b5c6ee5edec1270e46223e513eaa20da20076ac", - "sha256:f6f8e3fecca256fefc91bb6765a693d96692459d7d4c644660a9fff32e517843", - "sha256:f7afbfee1157e0f9376c00bb232e80a60e59ed716e3211a80cb8506550671e6e", - "sha256:fa242ac1ff583e4ec7771141606aafc92b361cd90a05c30d93e343a0c2d82a89", - "sha256:fab6ce90574645a0d6c58890e9bcaac8d94dff54fb51c69e5522a7358b80ab64" - ], - "markers": "python_version >= '3.8'", - "version": "==0.18.1" - }, - "s3transfer": { - "hashes": [ - "sha256:10d6923c6359175f264811ef4bf6161a3156ce8e350e705396a7557d6293c33a", - "sha256:fd3889a66f5fe17299fe75b82eae6cf722554edca744ca5d5fe308b104883d2e" - ], - "index": "pypi", - "markers": "python_version >= '3.7'", - "version": "==0.7.0" - }, - "six": { - "hashes": [ - "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926", - "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254" - ], - "index": "pypi", - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", - "version": "==1.16.0" - }, - "soupsieve": { - "hashes": [ - "sha256:5663d5a7b3bfaeee0bc4372e7fc48f9cff4940b3eec54a6451cc5299f1097690", - "sha256:eaa337ff55a1579b6549dc679565eac1e3d000563bcb1c8ab0d0fefbc0c2cdc7" - ], - "index": "pypi", - "markers": "python_version >= '3.8'", - "version": "==2.5" - }, - "stack-data": { - "hashes": [ - "sha256:32d2dd0376772d01b6cb9fc996f3c8b57a357089dec328ed4b6553d037eaf815", - "sha256:cbb2a53eb64e5785878201a97ed7c7b94883f48b87bfb0bbe8b623c74679e4a8" - ], - "index": "pypi", - "version": "==0.6.2" - }, - "tldextract": { - "hashes": [ - "sha256:30a492de80f4de215aa998588ba5c2e625ee74ace3a2705cfb52b0021053bcbe", - "sha256:a5d8b6583791daca268a7592ebcf764152fa49617983c49916ee9de99b366222" - ], - "index": "pypi", - "markers": "python_version >= '3.7'", - "version": "==3.6.0" - }, - "toolz": { - "hashes": [ - "sha256:d22731364c07d72eea0a0ad45bafb2c2937ab6fd38a3507bf55eae8744aa7d85", - "sha256:ecca342664893f177a13dac0e6b41cbd8ac25a358e5f215316d43e2100224f4d" - ], - "markers": "python_version >= '3.7'", - "version": "==0.12.1" - }, - "tornado": { - "hashes": [ - "sha256:1bd19ca6c16882e4d37368e0152f99c099bad93e0950ce55e71daed74045908f", - "sha256:22d3c2fa10b5793da13c807e6fc38ff49a4f6e1e3868b0a6f4164768bb8e20f5", - "sha256:502fba735c84450974fec147340016ad928d29f1e91f49be168c0a4c18181e1d", - "sha256:65ceca9500383fbdf33a98c0087cb975b2ef3bfb874cb35b8de8740cf7f41bd3", - "sha256:71a8db65160a3c55d61839b7302a9a400074c9c753040455494e2af74e2501f2", - "sha256:7ac51f42808cca9b3613f51ffe2a965c8525cb1b00b7b2d56828b8045354f76a", - "sha256:7d01abc57ea0dbb51ddfed477dfe22719d376119844e33c661d873bf9c0e4a16", - "sha256:805d507b1f588320c26f7f097108eb4023bbaa984d63176d1652e184ba24270a", - "sha256:9dc4444c0defcd3929d5c1eb5706cbe1b116e762ff3e0deca8b715d14bf6ec17", - "sha256:ceb917a50cd35882b57600709dd5421a418c29ddc852da8bcdab1f0db33406b0", - "sha256:e7d8db41c0181c80d76c982aacc442c0783a2c54d6400fe028954201a2e032fe" - ], - "index": "pypi", - "markers": "python_version >= '3.8'", - "version": "==6.3.3" - }, - "traitlets": { - "hashes": [ - "sha256:9e6ec080259b9a5940c797d58b613b5e31441c2257b87c2e795c5228ae80d2d8", - "sha256:f6cde21a9c68cf756af02035f72d5a723bf607e862e7be33ece505abf4a3bad9" - ], - "index": "pypi", - "markers": "python_version >= '3.7'", - "version": "==5.9.0" - }, - "typing-extensions": { - "hashes": [ - "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d", - "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8" - ], - "markers": "python_version >= '3.8'", - "version": "==4.12.2" - }, - "urllib3": { - "hashes": [ - "sha256:8d36afa7616d8ab714608411b4a3b13e58f463aee519024578e062e141dce20f", - "sha256:8f135f6502756bde6b2a9b28989df5fbe87c9970cecaa69041edcce7f0589b14" - ], - "index": "pypi", - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'", - "version": "==1.26.16" - }, - "vine": { - "hashes": [ - "sha256:4c9dceab6f76ed92105027c49c823800dd33cacce13bdedc5b914e3514b7fb30", - "sha256:7d3b1624a953da82ef63462013bbd271d3eb75751489f9807598e8f340bd637e" - ], - "index": "pypi", - "markers": "python_version >= '3.6'", - "version": "==5.0.0" - }, - "wcwidth": { - "hashes": [ - "sha256:795b138f6875577cd91bba52baf9e445cd5118fd32723b460e30a0af30ea230e", - "sha256:a5220780a404dbe3353789870978e472cfe477761f06ee55077256e509b156d0" - ], - "index": "pypi", - "version": "==0.2.6" - }, - "web3": { - "hashes": [ - "sha256:d27fbd4ac5aa70d0e0c516bd3e3b802fbe74bc159b407c34052d9301b400f757", - "sha256:fb39683d6aa7586ce0ab0be4be392f8acb62c2503958079d61b59f2a0b883718" - ], - "index": "pypi", - "markers": "python_full_version >= '3.7.2'", - "version": "==6.19.0" - }, - "webargs": { - "hashes": [ - "sha256:6746327faf549533bf30be7333f99541b6c60a85f23acf1bb0bea68498e3bcd7", - "sha256:99d68940c452e07726485a15fef43f12f8ae6c0c5b391bcba76065d4527fb85d" - ], - "index": "pypi", - "markers": "python_full_version >= '3.7.2'", - "version": "==8.2.0" - }, - "websockets": { - "hashes": [ - "sha256:00700340c6c7ab788f176d118775202aadea7602c5cc6be6ae127761c16d6b0b", - "sha256:0bee75f400895aef54157b36ed6d3b308fcab62e5260703add87f44cee9c82a6", - "sha256:0e6e2711d5a8e6e482cacb927a49a3d432345dfe7dea8ace7b5790df5932e4df", - "sha256:12743ab88ab2af1d17dd4acb4645677cb7063ef4db93abffbf164218a5d54c6b", - "sha256:1a9d160fd080c6285e202327aba140fc9a0d910b09e423afff4ae5cbbf1c7205", - "sha256:1bf386089178ea69d720f8db6199a0504a406209a0fc23e603b27b300fdd6892", - "sha256:1df2fbd2c8a98d38a66f5238484405b8d1d16f929bb7a33ed73e4801222a6f53", - "sha256:1e4b3f8ea6a9cfa8be8484c9221ec0257508e3a1ec43c36acdefb2a9c3b00aa2", - "sha256:1f38a7b376117ef7aff996e737583172bdf535932c9ca021746573bce40165ed", - "sha256:23509452b3bc38e3a057382c2e941d5ac2e01e251acce7adc74011d7d8de434c", - "sha256:248d8e2446e13c1d4326e0a6a4e9629cb13a11195051a73acf414812700badbd", - "sha256:25eb766c8ad27da0f79420b2af4b85d29914ba0edf69f547cc4f06ca6f1d403b", - "sha256:27a5e9964ef509016759f2ef3f2c1e13f403725a5e6a1775555994966a66e931", - "sha256:2c71bd45a777433dd9113847af751aae36e448bc6b8c361a566cb043eda6ec30", - "sha256:2cb388a5bfb56df4d9a406783b7f9dbefb888c09b71629351cc6b036e9259370", - "sha256:2d225bb6886591b1746b17c0573e29804619c8f755b5598d875bb4235ea639be", - "sha256:2e5fc14ec6ea568200ea4ef46545073da81900a2b67b3e666f04adf53ad452ec", - "sha256:363f57ca8bc8576195d0540c648aa58ac18cf85b76ad5202b9f976918f4219cf", - "sha256:3c6cc1360c10c17463aadd29dd3af332d4a1adaa8796f6b0e9f9df1fdb0bad62", - "sha256:3d829f975fc2e527a3ef2f9c8f25e553eb7bc779c6665e8e1d52aa22800bb38b", - "sha256:3e3aa8c468af01d70332a382350ee95f6986db479ce7af14d5e81ec52aa2b402", - "sha256:3f61726cae9f65b872502ff3c1496abc93ffbe31b278455c418492016e2afc8f", - "sha256:423fc1ed29f7512fceb727e2d2aecb952c46aa34895e9ed96071821309951123", - "sha256:46e71dbbd12850224243f5d2aeec90f0aaa0f2dde5aeeb8fc8df21e04d99eff9", - "sha256:4d87be612cbef86f994178d5186add3d94e9f31cc3cb499a0482b866ec477603", - "sha256:5693ef74233122f8ebab026817b1b37fe25c411ecfca084b29bc7d6efc548f45", - "sha256:5aa9348186d79a5f232115ed3fa9020eab66d6c3437d72f9d2c8ac0c6858c558", - "sha256:5d873c7de42dea355d73f170be0f23788cf3fa9f7bed718fd2830eefedce01b4", - "sha256:5f6ffe2c6598f7f7207eef9a1228b6f5c818f9f4d53ee920aacd35cec8110438", - "sha256:604428d1b87edbf02b233e2c207d7d528460fa978f9e391bd8aaf9c8311de137", - "sha256:6350b14a40c95ddd53e775dbdbbbc59b124a5c8ecd6fbb09c2e52029f7a9f480", - "sha256:6e2df67b8014767d0f785baa98393725739287684b9f8d8a1001eb2839031447", - "sha256:6e96f5ed1b83a8ddb07909b45bd94833b0710f738115751cdaa9da1fb0cb66e8", - "sha256:6e9e7db18b4539a29cc5ad8c8b252738a30e2b13f033c2d6e9d0549b45841c04", - "sha256:70ec754cc2a769bcd218ed8d7209055667b30860ffecb8633a834dde27d6307c", - "sha256:7b645f491f3c48d3f8a00d1fce07445fab7347fec54a3e65f0725d730d5b99cb", - "sha256:7fa3d25e81bfe6a89718e9791128398a50dec6d57faf23770787ff441d851967", - "sha256:81df9cbcbb6c260de1e007e58c011bfebe2dafc8435107b0537f393dd38c8b1b", - "sha256:8572132c7be52632201a35f5e08348137f658e5ffd21f51f94572ca6c05ea81d", - "sha256:87b4aafed34653e465eb77b7c93ef058516cb5acf3eb21e42f33928616172def", - "sha256:8e332c210b14b57904869ca9f9bf4ca32f5427a03eeb625da9b616c85a3a506c", - "sha256:9893d1aa45a7f8b3bc4510f6ccf8db8c3b62120917af15e3de247f0780294b92", - "sha256:9edf3fc590cc2ec20dc9d7a45108b5bbaf21c0d89f9fd3fd1685e223771dc0b2", - "sha256:9fdf06fd06c32205a07e47328ab49c40fc1407cdec801d698a7c41167ea45113", - "sha256:a02413bc474feda2849c59ed2dfb2cddb4cd3d2f03a2fedec51d6e959d9b608b", - "sha256:a1d9697f3337a89691e3bd8dc56dea45a6f6d975f92e7d5f773bc715c15dde28", - "sha256:a571f035a47212288e3b3519944f6bf4ac7bc7553243e41eac50dd48552b6df7", - "sha256:ab3d732ad50a4fbd04a4490ef08acd0517b6ae6b77eb967251f4c263011a990d", - "sha256:ae0a5da8f35a5be197f328d4727dbcfafa53d1824fac3d96cdd3a642fe09394f", - "sha256:b067cb952ce8bf40115f6c19f478dc71c5e719b7fbaa511359795dfd9d1a6468", - "sha256:b2ee7288b85959797970114deae81ab41b731f19ebcd3bd499ae9ca0e3f1d2c8", - "sha256:b81f90dcc6c85a9b7f29873beb56c94c85d6f0dac2ea8b60d995bd18bf3e2aae", - "sha256:ba0cab91b3956dfa9f512147860783a1829a8d905ee218a9837c18f683239611", - "sha256:baa386875b70cbd81798fa9f71be689c1bf484f65fd6fb08d051a0ee4e79924d", - "sha256:bbe6013f9f791944ed31ca08b077e26249309639313fff132bfbf3ba105673b9", - "sha256:bea88d71630c5900690fcb03161ab18f8f244805c59e2e0dc4ffadae0a7ee0ca", - "sha256:befe90632d66caaf72e8b2ed4d7f02b348913813c8b0a32fae1cc5fe3730902f", - "sha256:c3181df4583c4d3994d31fb235dc681d2aaad744fbdbf94c4802485ececdecf2", - "sha256:c4e37d36f0d19f0a4413d3e18c0d03d0c268ada2061868c1e6f5ab1a6d575077", - "sha256:c588f6abc13f78a67044c6b1273a99e1cf31038ad51815b3b016ce699f0d75c2", - "sha256:cbe83a6bbdf207ff0541de01e11904827540aa069293696dd528a6640bd6a5f6", - "sha256:d554236b2a2006e0ce16315c16eaa0d628dab009c33b63ea03f41c6107958374", - "sha256:dbcf72a37f0b3316e993e13ecf32f10c0e1259c28ffd0a85cee26e8549595fbc", - "sha256:dc284bbc8d7c78a6c69e0c7325ab46ee5e40bb4d50e494d8131a07ef47500e9e", - "sha256:dff6cdf35e31d1315790149fee351f9e52978130cef6c87c4b6c9b3baf78bc53", - "sha256:e469d01137942849cff40517c97a30a93ae79917752b34029f0ec72df6b46399", - "sha256:eb809e816916a3b210bed3c82fb88eaf16e8afcf9c115ebb2bacede1797d2547", - "sha256:ed2fcf7a07334c77fc8a230755c2209223a7cc44fc27597729b8ef5425aa61a3", - "sha256:f44069528d45a933997a6fef143030d8ca8042f0dfaad753e2906398290e2870", - "sha256:f764ba54e33daf20e167915edc443b6f88956f37fb606449b4a5b10ba42235a5", - "sha256:fc4e7fa5414512b481a2483775a8e8be7803a35b30ca805afa4998a84f9fd9e8", - "sha256:ffefa1374cd508d633646d51a8e9277763a9b78ae71324183693959cf94635a7" - ], - "markers": "python_version >= '3.8'", - "version": "==12.0" - }, - "werkzeug": { - "hashes": [ - "sha256:4866679a0722de00796a74086238bb3b98d90f423f05de039abb09315487254a", - "sha256:a987caf1092edc7523edb139edb20c70571c4a8d5eed02e0b547b4739174d091" - ], - "index": "pypi", - "markers": "python_version >= '3.8'", - "version": "==2.3.3" - }, - "yarl": { - "hashes": [ - "sha256:008d3e808d03ef28542372d01057fd09168419cdc8f848efe2804f894ae03e51", - "sha256:03caa9507d3d3c83bca08650678e25364e1843b484f19986a527630ca376ecce", - "sha256:07574b007ee20e5c375a8fe4a0789fad26db905f9813be0f9fef5a68080de559", - "sha256:09efe4615ada057ba2d30df871d2f668af661e971dfeedf0c159927d48bbeff0", - "sha256:0d2454f0aef65ea81037759be5ca9947539667eecebca092733b2eb43c965a81", - "sha256:0e9d124c191d5b881060a9e5060627694c3bdd1fe24c5eecc8d5d7d0eb6faabc", - "sha256:18580f672e44ce1238b82f7fb87d727c4a131f3a9d33a5e0e82b793362bf18b4", - "sha256:1f23e4fe1e8794f74b6027d7cf19dc25f8b63af1483d91d595d4a07eca1fb26c", - "sha256:206a55215e6d05dbc6c98ce598a59e6fbd0c493e2de4ea6cc2f4934d5a18d130", - "sha256:23d32a2594cb5d565d358a92e151315d1b2268bc10f4610d098f96b147370136", - "sha256:26a1dc6285e03f3cc9e839a2da83bcbf31dcb0d004c72d0730e755b33466c30e", - "sha256:29e0f83f37610f173eb7e7b5562dd71467993495e568e708d99e9d1944f561ec", - "sha256:2b134fd795e2322b7684155b7855cc99409d10b2e408056db2b93b51a52accc7", - "sha256:2d47552b6e52c3319fede1b60b3de120fe83bde9b7bddad11a69fb0af7db32f1", - "sha256:357495293086c5b6d34ca9616a43d329317feab7917518bc97a08f9e55648455", - "sha256:35a2b9396879ce32754bd457d31a51ff0a9d426fd9e0e3c33394bf4b9036b099", - "sha256:3777ce5536d17989c91696db1d459574e9a9bd37660ea7ee4d3344579bb6f129", - "sha256:3986b6f41ad22988e53d5778f91855dc0399b043fc8946d4f2e68af22ee9ff10", - "sha256:44d8ffbb9c06e5a7f529f38f53eda23e50d1ed33c6c869e01481d3fafa6b8142", - "sha256:49a180c2e0743d5d6e0b4d1a9e5f633c62eca3f8a86ba5dd3c471060e352ca98", - "sha256:4aa9741085f635934f3a2583e16fcf62ba835719a8b2b28fb2917bb0537c1dfa", - "sha256:4b21516d181cd77ebd06ce160ef8cc2a5e9ad35fb1c5930882baff5ac865eee7", - "sha256:4b3c1ffe10069f655ea2d731808e76e0f452fc6c749bea04781daf18e6039525", - "sha256:4c7d56b293cc071e82532f70adcbd8b61909eec973ae9d2d1f9b233f3d943f2c", - "sha256:4e9035df8d0880b2f1c7f5031f33f69e071dfe72ee9310cfc76f7b605958ceb9", - "sha256:54525ae423d7b7a8ee81ba189f131054defdb122cde31ff17477951464c1691c", - "sha256:549d19c84c55d11687ddbd47eeb348a89df9cb30e1993f1b128f4685cd0ebbf8", - "sha256:54beabb809ffcacbd9d28ac57b0db46e42a6e341a030293fb3185c409e626b8b", - "sha256:566db86717cf8080b99b58b083b773a908ae40f06681e87e589a976faf8246bf", - "sha256:5a2e2433eb9344a163aced6a5f6c9222c0786e5a9e9cac2c89f0b28433f56e23", - "sha256:5aef935237d60a51a62b86249839b51345f47564208c6ee615ed2a40878dccdd", - "sha256:604f31d97fa493083ea21bd9b92c419012531c4e17ea6da0f65cacdcf5d0bd27", - "sha256:63b20738b5aac74e239622d2fe30df4fca4942a86e31bf47a81a0e94c14df94f", - "sha256:686a0c2f85f83463272ddffd4deb5e591c98aac1897d65e92319f729c320eece", - "sha256:6a962e04b8f91f8c4e5917e518d17958e3bdee71fd1d8b88cdce74dd0ebbf434", - "sha256:6ad6d10ed9b67a382b45f29ea028f92d25bc0bc1daf6c5b801b90b5aa70fb9ec", - "sha256:6f5cb257bc2ec58f437da2b37a8cd48f666db96d47b8a3115c29f316313654ff", - "sha256:6fe79f998a4052d79e1c30eeb7d6c1c1056ad33300f682465e1b4e9b5a188b78", - "sha256:7855426dfbddac81896b6e533ebefc0af2f132d4a47340cee6d22cac7190022d", - "sha256:7d5aaac37d19b2904bb9dfe12cdb08c8443e7ba7d2852894ad448d4b8f442863", - "sha256:801e9264d19643548651b9db361ce3287176671fb0117f96b5ac0ee1c3530d53", - "sha256:81eb57278deb6098a5b62e88ad8281b2ba09f2f1147c4767522353eaa6260b31", - "sha256:824d6c50492add5da9374875ce72db7a0733b29c2394890aef23d533106e2b15", - "sha256:8397a3817d7dcdd14bb266283cd1d6fc7264a48c186b986f32e86d86d35fbac5", - "sha256:848cd2a1df56ddbffeb375535fb62c9d1645dde33ca4d51341378b3f5954429b", - "sha256:84fc30f71689d7fc9168b92788abc977dc8cefa806909565fc2951d02f6b7d57", - "sha256:8619d6915b3b0b34420cf9b2bb6d81ef59d984cb0fde7544e9ece32b4b3043c3", - "sha256:8a854227cf581330ffa2c4824d96e52ee621dd571078a252c25e3a3b3d94a1b1", - "sha256:8be9e837ea9113676e5754b43b940b50cce76d9ed7d2461df1af39a8ee674d9f", - "sha256:928cecb0ef9d5a7946eb6ff58417ad2fe9375762382f1bf5c55e61645f2c43ad", - "sha256:957b4774373cf6f709359e5c8c4a0af9f6d7875db657adb0feaf8d6cb3c3964c", - "sha256:992f18e0ea248ee03b5a6e8b3b4738850ae7dbb172cc41c966462801cbf62cf7", - "sha256:9fc5fc1eeb029757349ad26bbc5880557389a03fa6ada41703db5e068881e5f2", - "sha256:a00862fb23195b6b8322f7d781b0dc1d82cb3bcac346d1e38689370cc1cc398b", - "sha256:a3a6ed1d525bfb91b3fc9b690c5a21bb52de28c018530ad85093cc488bee2dd2", - "sha256:a6327976c7c2f4ee6816eff196e25385ccc02cb81427952414a64811037bbc8b", - "sha256:a7409f968456111140c1c95301cadf071bd30a81cbd7ab829169fb9e3d72eae9", - "sha256:a825ec844298c791fd28ed14ed1bffc56a98d15b8c58a20e0e08c1f5f2bea1be", - "sha256:a8c1df72eb746f4136fe9a2e72b0c9dc1da1cbd23b5372f94b5820ff8ae30e0e", - "sha256:a9bd00dc3bc395a662900f33f74feb3e757429e545d831eef5bb280252631984", - "sha256:aa102d6d280a5455ad6a0f9e6d769989638718e938a6a0a2ff3f4a7ff8c62cc4", - "sha256:aaaea1e536f98754a6e5c56091baa1b6ce2f2700cc4a00b0d49eca8dea471074", - "sha256:ad4d7a90a92e528aadf4965d685c17dacff3df282db1121136c382dc0b6014d2", - "sha256:b8477c1ee4bd47c57d49621a062121c3023609f7a13b8a46953eb6c9716ca392", - "sha256:ba6f52cbc7809cd8d74604cce9c14868306ae4aa0282016b641c661f981a6e91", - "sha256:bac8d525a8dbc2a1507ec731d2867025d11ceadcb4dd421423a5d42c56818541", - "sha256:bef596fdaa8f26e3d66af846bbe77057237cb6e8efff8cd7cc8dff9a62278bbf", - "sha256:c0ec0ed476f77db9fb29bca17f0a8fcc7bc97ad4c6c1d8959c507decb22e8572", - "sha256:c38c9ddb6103ceae4e4498f9c08fac9b590c5c71b0370f98714768e22ac6fa66", - "sha256:c7224cab95645c7ab53791022ae77a4509472613e839dab722a72abe5a684575", - "sha256:c74018551e31269d56fab81a728f683667e7c28c04e807ba08f8c9e3bba32f14", - "sha256:ca06675212f94e7a610e85ca36948bb8fc023e458dd6c63ef71abfd482481aa5", - "sha256:d1d2532b340b692880261c15aee4dc94dd22ca5d61b9db9a8a361953d36410b1", - "sha256:d25039a474c4c72a5ad4b52495056f843a7ff07b632c1b92ea9043a3d9950f6e", - "sha256:d5ff2c858f5f6a42c2a8e751100f237c5e869cbde669a724f2062d4c4ef93551", - "sha256:d7d7f7de27b8944f1fee2c26a88b4dabc2409d2fea7a9ed3df79b67277644e17", - "sha256:d7eeb6d22331e2fd42fce928a81c697c9ee2d51400bd1a28803965883e13cead", - "sha256:d8a1c6c0be645c745a081c192e747c5de06e944a0d21245f4cf7c05e457c36e0", - "sha256:d8b889777de69897406c9fb0b76cdf2fd0f31267861ae7501d93003d55f54fbe", - "sha256:d9e09c9d74f4566e905a0b8fa668c58109f7624db96a2171f21747abc7524234", - "sha256:db8e58b9d79200c76956cefd14d5c90af54416ff5353c5bfd7cbe58818e26ef0", - "sha256:ddb2a5c08a4eaaba605340fdee8fc08e406c56617566d9643ad8bf6852778fc7", - "sha256:e0381b4ce23ff92f8170080c97678040fc5b08da85e9e292292aba67fdac6c34", - "sha256:e23a6d84d9d1738dbc6e38167776107e63307dfc8ad108e580548d1f2c587f42", - "sha256:e516dc8baf7b380e6c1c26792610230f37147bb754d6426462ab115a02944385", - "sha256:ea65804b5dc88dacd4a40279af0cdadcfe74b3e5b4c897aa0d81cf86927fee78", - "sha256:ec61d826d80fc293ed46c9dd26995921e3a82146feacd952ef0757236fc137be", - "sha256:ee04010f26d5102399bd17f8df8bc38dc7ccd7701dc77f4a68c5b8d733406958", - "sha256:f3bc6af6e2b8f92eced34ef6a96ffb248e863af20ef4fde9448cc8c9b858b749", - "sha256:f7d6b36dd2e029b6bcb8a13cf19664c7b8e19ab3a58e0fefbb5b8461447ed5ec" - ], - "markers": "python_version >= '3.7'", - "version": "==1.9.4" - }, - "zipp": { - "hashes": [ - "sha256:112929ad649da941c23de50f356a2b5570c954b65150642bccdd66bf194d224b", - "sha256:48904fc76a60e542af151aded95726c1a5c34ed43ab4134b597665c86d7ad556" - ], - "index": "pypi", - "markers": "python_version >= '3.7'", - "version": "==3.15.0" - } - }, - "develop": { - "asttokens": { - "hashes": [ - "sha256:4622110b2a6f30b77e1473affaa97e711bc2f07d3f10848420ff1898edbe94f3", - "sha256:6b0ac9e93fb0335014d382b8fa9b3afa7df546984258005da0b9e7095b3deb1c" - ], - "index": "pypi", - "version": "==2.2.1" - }, - "autopep8": { - "hashes": [ - "sha256:86e9303b5e5c8160872b2f5ef611161b2893e9bfe8ccc7e2f76385947d57a2f1", - "sha256:f9849cdd62108cb739dbcdbfb7fdcc9a30d1b63c4cc3e1c1f893b5360941b61c" - ], - "index": "pypi", - "markers": "python_version >= '3.6'", - "version": "==2.0.2" - }, - "backcall": { - "hashes": [ - "sha256:5cbdbf27be5e7cfadb448baf0aa95508f91f2bbc6c6437cd9cd06e2a4c215e1e", - "sha256:fbbce6a29f263178a1f7915c1940bde0ec2b2a967566fe1c65c1dfb7422bd255" - ], - "index": "pypi", - "version": "==0.2.0" - }, - "colorama": { - "hashes": [ - "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", - "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6" - ], - "markers": "platform_system == 'Windows'", - "version": "==0.4.6" - }, - "decorator": { - "hashes": [ - "sha256:637996211036b6385ef91435e4fae22989472f9d571faba8927ba8253acbc330", - "sha256:b8c3f85900b9dc423225913c5aace94729fe1fa9763b38939a95226f02d37186" - ], - "index": "pypi", - "markers": "python_version >= '3.5'", - "version": "==5.1.1" - }, - "executing": { - "hashes": [ - "sha256:0314a69e37426e3608aada02473b4161d4caf5a4b244d1d0c48072b8fee7bacc", - "sha256:19da64c18d2d851112f09c287f8d3dbbdf725ab0e569077efb6cdcbd3497c107" - ], - "index": "pypi", - "version": "==1.2.0" - }, - "flake8": { - "hashes": [ - "sha256:3833794e27ff64ea4e9cf5d410082a8b97ff1a06c16aa3d2027339cd0f1195c7", - "sha256:c61007e76655af75e6785a931f452915b371dc48f56efd765247c8fe68f2b181" - ], - "index": "pypi", - "markers": "python_full_version >= '3.8.1'", - "version": "==6.0.0" - }, - "ipython": { - "hashes": [ - "sha256:7dff3fad32b97f6488e02f87b970f309d082f758d7b7fc252e3b19ee0e432dbb", - "sha256:ffca270240fbd21b06b2974e14a86494d6d29290184e788275f55e0b55914926" - ], - "index": "pypi", - "markers": "python_version >= '3.9'", - "version": "==8.13.2" - }, - "jedi": { - "hashes": [ - "sha256:203c1fd9d969ab8f2119ec0a3342e0b49910045abe6af0a3ae83a5764d54639e", - "sha256:bae794c30d07f6d910d32a7048af09b5a39ed740918da923c6b780790ebac612" - ], - "index": "pypi", - "markers": "python_version >= '3.6'", - "version": "==0.18.2" - }, - "matplotlib-inline": { - "hashes": [ - "sha256:f1f41aab5328aa5aaea9b16d083b128102f8712542f819fe7e6a420ff581b311", - "sha256:f887e5f10ba98e8d2b150ddcf4702c1e5f8b3a20005eb0f74bfdbd360ee6f304" - ], - "index": "pypi", - "markers": "python_version >= '3.5'", - "version": "==0.1.6" - }, - "mccabe": { - "hashes": [ - "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325", - "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e" - ], - "index": "pypi", - "markers": "python_version >= '3.6'", - "version": "==0.7.0" - }, - "parso": { - "hashes": [ - "sha256:8c07be290bb59f03588915921e29e8a50002acaf2cdc5fa0e0114f91709fafa0", - "sha256:c001d4636cd3aecdaf33cbb40aebb59b094be2a74c556778ef5576c175e19e75" - ], - "index": "pypi", - "markers": "python_version >= '3.6'", - "version": "==0.8.3" - }, - "pickleshare": { - "hashes": [ - "sha256:87683d47965c1da65cdacaf31c8441d12b8044cdec9aca500cd78fc2c683afca", - "sha256:9649af414d74d4df115d5d718f82acb59c9d418196b7b4290ed47a12ce62df56" - ], - "index": "pypi", - "version": "==0.7.5" - }, - "prompt-toolkit": { - "hashes": [ - "sha256:23ac5d50538a9a38c8bde05fecb47d0b403ecd0662857a86f886f798563d5b9b", - "sha256:45ea77a2f7c60418850331366c81cf6b5b9cf4c7fd34616f733c5427e6abbb1f" - ], - "index": "pypi", - "markers": "python_full_version >= '3.7.0'", - "version": "==3.0.38" - }, - "pure-eval": { - "hashes": [ - "sha256:01eaab343580944bc56080ebe0a674b39ec44a945e6d09ba7db3cb8cec289350", - "sha256:2b45320af6dfaa1750f543d714b6d1c520a1688dec6fd24d339063ce0aaa9ac3" - ], - "index": "pypi", - "version": "==0.2.2" - }, - "pycodestyle": { - "hashes": [ - "sha256:347187bdb476329d98f695c213d7295a846d1152ff4fe9bacb8a9590b8ee7053", - "sha256:8a4eaf0d0495c7395bdab3589ac2db602797d76207242c17d470186815706610" - ], - "index": "pypi", - "markers": "python_version >= '3.6'", - "version": "==2.10.0" - }, - "pyflakes": { - "hashes": [ - "sha256:ec55bf7fe21fff7f1ad2f7da62363d749e2a470500eab1b555334b67aa1ef8cf", - "sha256:ec8b276a6b60bd80defed25add7e439881c19e64850afd9b346283d4165fd0fd" - ], - "index": "pypi", - "markers": "python_version >= '3.6'", - "version": "==3.0.1" - }, - "pygments": { - "hashes": [ - "sha256:8ace4d3c1dd481894b2005f560ead0f9f19ee64fe983366be1a21e171d12775c", - "sha256:db2db3deb4b4179f399a09054b023b6a586b76499d36965813c71aa8ed7b5fd1" - ], - "index": "pypi", - "markers": "python_version >= '3.7'", - "version": "==2.15.1" - }, - "six": { - "hashes": [ - "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926", - "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254" - ], - "index": "pypi", - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", - "version": "==1.16.0" - }, - "stack-data": { - "hashes": [ - "sha256:32d2dd0376772d01b6cb9fc996f3c8b57a357089dec328ed4b6553d037eaf815", - "sha256:cbb2a53eb64e5785878201a97ed7c7b94883f48b87bfb0bbe8b623c74679e4a8" - ], - "index": "pypi", - "version": "==0.6.2" - }, - "traitlets": { - "hashes": [ - "sha256:9e6ec080259b9a5940c797d58b613b5e31441c2257b87c2e795c5228ae80d2d8", - "sha256:f6cde21a9c68cf756af02035f72d5a723bf607e862e7be33ece505abf4a3bad9" - ], - "index": "pypi", - "markers": "python_version >= '3.7'", - "version": "==5.9.0" - }, - "wcwidth": { - "hashes": [ - "sha256:795b138f6875577cd91bba52baf9e445cd5118fd32723b460e30a0af30ea230e", - "sha256:a5220780a404dbe3353789870978e472cfe477761f06ee55077256e509b156d0" - ], - "index": "pypi", - "version": "==0.2.6" - } - } -} diff --git a/app/__init__.py b/app/__init__.py deleted file mode 100755 index bd41367..0000000 --- a/app/__init__.py +++ /dev/null @@ -1,40 +0,0 @@ -from dotenv import load_dotenv -from flask import Flask,jsonify -from flask_cors import CORS - -from flask_limiter import Limiter -from flask_limiter.util import get_remote_address -from flask_limiter.errors import RateLimitExceeded - - -def create_app(): - load_dotenv() - - app = Flask("KLEO-NETWORK") - - CORS(app, resources={r"/api/*": {"origins": "*"}}) - limiter = Limiter( - key_func=get_remote_address, - app=app, - default_limits=["500 per day", "200 per hour"] - ) - @app.errorhandler(RateLimitExceeded) - def rate_limit_handler(e): - return jsonify(error="Rate limit exceeded. Please try again later."), 429 - - register_blueprints(app, limiter) - - return app - - -def register_blueprints(app, limiter): - """ - Function to register all blueprints to the Flask app. - Keeps the create_app function clean and modular. - """ - from .core.views.user_v2_views import core as core_user_v2 - - limiter.limit("100 per hour")(core_user_v2) - app.register_blueprint( - core_user_v2, name="user_api_v2", url_prefix="/api/v2/core/user" - ) diff --git a/app/config.py b/app/config.py deleted file mode 100755 index 6b88593..0000000 --- a/app/config.py +++ /dev/null @@ -1,108 +0,0 @@ -from pydantic_settings import BaseSettings -from dotenv import load_dotenv -import os - - -class Settings(BaseSettings): - load_dotenv() - APP_NAME: str = "Kleo Backend" - APP_VERSION: str = "1.0" - DEBUG: bool = os.getenv("DEBUG", False) - - -def get_settings(): - return Settings() - - -# from os import environ, path - -# from dotenv import load_dotenv - -# basedir = path.abspath(path.join(path.dirname(__file__), '..')) -# # loading env vars from .env file -# load_dotenv() - - -# class BaseConfig(object): -# ''' Base config class. ''' - -# APP_NAME = environ.get('APP_NAME') or 'flask-boilerplate' -# ORIGINS = ['*'] -# EMAIL_CHARSET = 'UTF-8' -# API_KEY = environ.get('API_KEY') -# BROKER_URL = environ.get('BROKER_URL') -# RESULT_BACKEND = environ.get('RESULT_BACKEND') -# LOG_INFO_FILE = path.join(basedir, 'log', 'info.log') -# LOG_CELERY_FILE = path.join(basedir, 'log', 'celery.log') -# LOGGING = { -# 'version': 1, -# 'disable_existing_loggers': False, -# 'formatters': { -# 'standard': { -# 'format': '[%(asctime)s] - %(name)s - %(levelname)s - ' -# '%(message)s', -# 'datefmt': '%b %d %Y %H:%M:%S' -# }, -# 'simple': { -# 'format': '%(levelname)s - %(message)s' -# }, -# }, -# 'handlers': { -# 'console': { -# 'level': 'DEBUG', -# 'class': 'logging.StreamHandler', -# 'formatter': 'simple' -# }, -# 'log_info_file': { -# 'level': 'DEBUG', -# 'class': 'logging.handlers.RotatingFileHandler', -# 'filename': LOG_INFO_FILE, -# 'maxBytes': 16777216, # 16megabytes -# 'formatter': 'standard', -# 'backupCount': 5 -# }, -# }, -# 'loggers': { -# APP_NAME: { -# 'level': 'DEBUG', -# 'handlers': ['log_info_file'], -# }, -# }, -# } - -# CELERY_LOGGING = { -# 'format': '[%(asctime)s] - %(name)s - %(levelname)s - ' -# '%(message)s', -# 'datefmt': '%b %d %Y %H:%M:%S', -# 'filename': LOG_CELERY_FILE, -# 'maxBytes': 10000000, # 10megabytes -# 'backupCount': 5 -# } - - -# class Development(BaseConfig): -# ''' Development config. ''' - -# DEBUG = True -# ENV = 'dev' - - -# class Staging(BaseConfig): -# ''' Staging config. ''' - -# DEBUG = True -# ENV = 'staging' - - -# class Production(BaseConfig): -# ''' Production config ''' - -# DEBUG = False -# ENV = 'production' - - -# config = { -# 'development': Development, -# 'staging': Staging, -# 'production': Production, -# } diff --git a/app/core/views/user_v2_views.py b/app/core/views/user_v2_views.py deleted file mode 100644 index 83db884..0000000 --- a/app/core/views/user_v2_views.py +++ /dev/null @@ -1,226 +0,0 @@ -from flask import Blueprint, request, jsonify -import random - -from app.core.modules.activity_chart import upload_image_to_image_bb -from ..models.user import * -from ..modules.auth import get_jwt_token -from ...celery.tasks import * -from ..models.history import get_top_activities, get_history_count -from ...core.models.constants import ABI, POLYGON_RPC - -core = Blueprint("core", __name__) - - -@core.route("/get-user-graph/", methods=["GET"]) -def get_user_graph(userAddress): - try: - if not userAddress: - return jsonify({"error": "Address is required"}), 400 - - cache_key = f"user_graph:{userAddress}" - cached_data = redis_client.get(cache_key) - - if cached_data: - data = json.loads(cached_data) - response = jsonify({"data": data}) - response.status_code = 200 - else: - response = jsonify({"processing": True}) - response.status_code = 200 - - update_user_graph_cache.delay(userAddress) - - return response - except Exception as e: - return jsonify({"error": str(e)}), 500 - - -@core.route("/save-history", methods=["POST"]) -def save_history(): - data = request.get_json() - # print(data) - user_address = str(data.get("address")).lower() - signup = data.get("signup") - history = data.get("history") - return_abi_contract = False - user = find_by_address(user_address) - - try: - if signup: - referee_address = find_referral_in_history(history) - if referee_address: - update_referee_and_bonus(user_address, referee_address) - contextual_activity_classification_for_batch.delay(history, user_address) - return jsonify({"data": "Signup successful!"}), 200 - else: - if get_history_count(user_address) > 50: - return_abi_contract = True - - for item in history: - if "content" in item: - user = find_by_address(user_address) - contextual_activity_classification.delay(item, user_address) - - if return_abi_contract: - user = find_by_address(user_address) - previous_hash = user.get("previous_hash", "first_hash") - chain_data_list = [ - { - "name": "polygon", - "rpc": POLYGON_RPC, - "contractData": { - "address": "0xD133A1aE09EAA45c51Daa898031c0037485347B0", - "abi": ABI, - "functionName": "safeMint", - "functionParams": [ - user_address, - previous_hash, - ], - }, - } - ] - - response = { - "chains": chain_data_list, - "password": user.get("slug"), - } - - return jsonify({"data": response}), 200 - return ( - jsonify({"status": "success", "message": "History saved successfully"}), - 200, - ) - except Exception as e: - return jsonify({"status": "error", "message": str(e)}), 500 - - - -@core.route("/create-user", methods=["POST"]) -def create_user(): - data = request.get_json() - wallet_address = data.get("address") - - if not wallet_address: - return jsonify({"error": "Address is required"}), 400 - - user = find_by_address(wallet_address) - if user: - try: - token = get_jwt_token(wallet_address, wallet_address) - except Exception as e: - return jsonify({'error': 'Failed to generate token'}), 500 - - user_data = {"password": user["slug"], "token": token} - return jsonify(user_data), 200 - - random_code = str(random.randint(100, 9999999)) - - user = User(address=wallet_address, slug=random_code) - response = user.save(signup=True) - - try: - token = get_jwt_token(wallet_address, wallet_address) - except Exception as e: - return jsonify({'error': 'Failed to generate token'}), 500 - - user_data = { - "password": response["slug"], - "token": token, - } - print(user_data) - return jsonify(user_data), 200 - - - -@core.route("/upload_activity_chart", methods=["POST"]) -def upload_activity_chart(): - try: - # Retrieve base64 image data from the POST request body - image_data = request.json.get("image") - - if not image_data: - return jsonify({"error": "No image data provided"}), 400 - - # Call the upload function to upload the image to Imgbb - image_url = upload_image_to_image_bb(image_data) - - if image_url: - return jsonify({"url": image_url}), 200 - else: - return jsonify({"error": "Image upload failed"}), 500 - except Exception as e: - return jsonify({"error": str(e)}), 500 - - -@core.route("/get-user/", methods=["GET"]) -def get_user(userAddress): - """ - Fetch user data from MongoDB based on the user's address. - """ - try: - # Query the MongoDB collection using the user's address - user_data = find_by_address(userAddress) - - # If user data is not found, return a 404 error - if not user_data: - return jsonify({"error": "User not found"}), 404 - - # Return the user data as JSON - return jsonify(user_data), 200 - except Exception as e: - # Handle any exceptions that occur and return a 500 error - return jsonify({"error": str(e)}), 500 - - -@core.route("/top-users", methods=["GET"]) -def get_top_users(): - """Fetch the top users based on Kleo points and include the user's rank at the first index if the address is provided.""" - try: - limit = request.args.get("limit", default=20, type=int) - user_address = request.args.get("address", default=None, type=str) - leaderboard = get_top_users_by_kleo_points(limit) - - # If user_address is provided, calculate the rank and add it at the first position - if user_address: - user_rank_data = calculate_rank(user_address) - - if user_rank_data: - user_rank_entry = { - "address": user_rank_data["address"], - "kleo_points": user_rank_data["kleo_points"], - "rank": user_rank_data["rank"], - } - - # Insert the user's rank at the first position - leaderboard.insert(0, user_rank_entry) - else: - return ( - jsonify( - { - "error": "Error fetching user's rank for address: {user_address}" - } - ), - 500, - ) - return jsonify(leaderboard), 200 - except Exception as e: - return jsonify({"error": "An error occurred while fetching top users"}), 500 - - -@core.route("/rank/", methods=["GET"]) -def get_user_rank(userAddress): - """Fetch the user's rank according to kleo_points""" - try: - rank = calculate_rank(userAddress) - return rank - except Exception as e: - return jsonify({"error": "An error occurred while fetching user's rank"}) - - -@core.route("/referrals/", methods=["GET"]) -def get_user_referrals(userAddress): - try: - referrals = fetch_users_referrals(userAddress) - return referrals - except Exception as e: - return jsonify({"error": "An error occurred while fetching user's referrals"}) \ No newline at end of file diff --git a/backend/bin/Activate.ps1 b/backend/bin/Activate.ps1 deleted file mode 100644 index b49d77b..0000000 --- a/backend/bin/Activate.ps1 +++ /dev/null @@ -1,247 +0,0 @@ -<# -.Synopsis -Activate a Python virtual environment for the current PowerShell session. - -.Description -Pushes the python executable for a virtual environment to the front of the -$Env:PATH environment variable and sets the prompt to signify that you are -in a Python virtual environment. Makes use of the command line switches as -well as the `pyvenv.cfg` file values present in the virtual environment. - -.Parameter VenvDir -Path to the directory that contains the virtual environment to activate. The -default value for this is the parent of the directory that the Activate.ps1 -script is located within. - -.Parameter Prompt -The prompt prefix to display when this virtual environment is activated. By -default, this prompt is the name of the virtual environment folder (VenvDir) -surrounded by parentheses and followed by a single space (ie. '(.venv) '). - -.Example -Activate.ps1 -Activates the Python virtual environment that contains the Activate.ps1 script. - -.Example -Activate.ps1 -Verbose -Activates the Python virtual environment that contains the Activate.ps1 script, -and shows extra information about the activation as it executes. - -.Example -Activate.ps1 -VenvDir C:\Users\MyUser\Common\.venv -Activates the Python virtual environment located in the specified location. - -.Example -Activate.ps1 -Prompt "MyPython" -Activates the Python virtual environment that contains the Activate.ps1 script, -and prefixes the current prompt with the specified string (surrounded in -parentheses) while the virtual environment is active. - -.Notes -On Windows, it may be required to enable this Activate.ps1 script by setting the -execution policy for the user. You can do this by issuing the following PowerShell -command: - -PS C:\> Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser - -For more information on Execution Policies: -https://go.microsoft.com/fwlink/?LinkID=135170 - -#> -Param( - [Parameter(Mandatory = $false)] - [String] - $VenvDir, - [Parameter(Mandatory = $false)] - [String] - $Prompt -) - -<# Function declarations --------------------------------------------------- #> - -<# -.Synopsis -Remove all shell session elements added by the Activate script, including the -addition of the virtual environment's Python executable from the beginning of -the PATH variable. - -.Parameter NonDestructive -If present, do not remove this function from the global namespace for the -session. - -#> -function global:deactivate ([switch]$NonDestructive) { - # Revert to original values - - # The prior prompt: - if (Test-Path -Path Function:_OLD_VIRTUAL_PROMPT) { - Copy-Item -Path Function:_OLD_VIRTUAL_PROMPT -Destination Function:prompt - Remove-Item -Path Function:_OLD_VIRTUAL_PROMPT - } - - # The prior PYTHONHOME: - if (Test-Path -Path Env:_OLD_VIRTUAL_PYTHONHOME) { - Copy-Item -Path Env:_OLD_VIRTUAL_PYTHONHOME -Destination Env:PYTHONHOME - Remove-Item -Path Env:_OLD_VIRTUAL_PYTHONHOME - } - - # The prior PATH: - if (Test-Path -Path Env:_OLD_VIRTUAL_PATH) { - Copy-Item -Path Env:_OLD_VIRTUAL_PATH -Destination Env:PATH - Remove-Item -Path Env:_OLD_VIRTUAL_PATH - } - - # Just remove the VIRTUAL_ENV altogether: - if (Test-Path -Path Env:VIRTUAL_ENV) { - Remove-Item -Path env:VIRTUAL_ENV - } - - # Just remove VIRTUAL_ENV_PROMPT altogether. - if (Test-Path -Path Env:VIRTUAL_ENV_PROMPT) { - Remove-Item -Path env:VIRTUAL_ENV_PROMPT - } - - # Just remove the _PYTHON_VENV_PROMPT_PREFIX altogether: - if (Get-Variable -Name "_PYTHON_VENV_PROMPT_PREFIX" -ErrorAction SilentlyContinue) { - Remove-Variable -Name _PYTHON_VENV_PROMPT_PREFIX -Scope Global -Force - } - - # Leave deactivate function in the global namespace if requested: - if (-not $NonDestructive) { - Remove-Item -Path function:deactivate - } -} - -<# -.Description -Get-PyVenvConfig parses the values from the pyvenv.cfg file located in the -given folder, and returns them in a map. - -For each line in the pyvenv.cfg file, if that line can be parsed into exactly -two strings separated by `=` (with any amount of whitespace surrounding the =) -then it is considered a `key = value` line. The left hand string is the key, -the right hand is the value. - -If the value starts with a `'` or a `"` then the first and last character is -stripped from the value before being captured. - -.Parameter ConfigDir -Path to the directory that contains the `pyvenv.cfg` file. -#> -function Get-PyVenvConfig( - [String] - $ConfigDir -) { - Write-Verbose "Given ConfigDir=$ConfigDir, obtain values in pyvenv.cfg" - - # Ensure the file exists, and issue a warning if it doesn't (but still allow the function to continue). - $pyvenvConfigPath = Join-Path -Resolve -Path $ConfigDir -ChildPath 'pyvenv.cfg' -ErrorAction Continue - - # An empty map will be returned if no config file is found. - $pyvenvConfig = @{ } - - if ($pyvenvConfigPath) { - - Write-Verbose "File exists, parse `key = value` lines" - $pyvenvConfigContent = Get-Content -Path $pyvenvConfigPath - - $pyvenvConfigContent | ForEach-Object { - $keyval = $PSItem -split "\s*=\s*", 2 - if ($keyval[0] -and $keyval[1]) { - $val = $keyval[1] - - # Remove extraneous quotations around a string value. - if ("'""".Contains($val.Substring(0, 1))) { - $val = $val.Substring(1, $val.Length - 2) - } - - $pyvenvConfig[$keyval[0]] = $val - Write-Verbose "Adding Key: '$($keyval[0])'='$val'" - } - } - } - return $pyvenvConfig -} - - -<# Begin Activate script --------------------------------------------------- #> - -# Determine the containing directory of this script -$VenvExecPath = Split-Path -Parent $MyInvocation.MyCommand.Definition -$VenvExecDir = Get-Item -Path $VenvExecPath - -Write-Verbose "Activation script is located in path: '$VenvExecPath'" -Write-Verbose "VenvExecDir Fullname: '$($VenvExecDir.FullName)" -Write-Verbose "VenvExecDir Name: '$($VenvExecDir.Name)" - -# Set values required in priority: CmdLine, ConfigFile, Default -# First, get the location of the virtual environment, it might not be -# VenvExecDir if specified on the command line. -if ($VenvDir) { - Write-Verbose "VenvDir given as parameter, using '$VenvDir' to determine values" -} -else { - Write-Verbose "VenvDir not given as a parameter, using parent directory name as VenvDir." - $VenvDir = $VenvExecDir.Parent.FullName.TrimEnd("\\/") - Write-Verbose "VenvDir=$VenvDir" -} - -# Next, read the `pyvenv.cfg` file to determine any required value such -# as `prompt`. -$pyvenvCfg = Get-PyVenvConfig -ConfigDir $VenvDir - -# Next, set the prompt from the command line, or the config file, or -# just use the name of the virtual environment folder. -if ($Prompt) { - Write-Verbose "Prompt specified as argument, using '$Prompt'" -} -else { - Write-Verbose "Prompt not specified as argument to script, checking pyvenv.cfg value" - if ($pyvenvCfg -and $pyvenvCfg['prompt']) { - Write-Verbose " Setting based on value in pyvenv.cfg='$($pyvenvCfg['prompt'])'" - $Prompt = $pyvenvCfg['prompt']; - } - else { - Write-Verbose " Setting prompt based on parent's directory's name. (Is the directory name passed to venv module when creating the virtual environment)" - Write-Verbose " Got leaf-name of $VenvDir='$(Split-Path -Path $venvDir -Leaf)'" - $Prompt = Split-Path -Path $venvDir -Leaf - } -} - -Write-Verbose "Prompt = '$Prompt'" -Write-Verbose "VenvDir='$VenvDir'" - -# Deactivate any currently active virtual environment, but leave the -# deactivate function in place. -deactivate -nondestructive - -# Now set the environment variable VIRTUAL_ENV, used by many tools to determine -# that there is an activated venv. -$env:VIRTUAL_ENV = $VenvDir - -if (-not $Env:VIRTUAL_ENV_DISABLE_PROMPT) { - - Write-Verbose "Setting prompt to '$Prompt'" - - # Set the prompt to include the env name - # Make sure _OLD_VIRTUAL_PROMPT is global - function global:_OLD_VIRTUAL_PROMPT { "" } - Copy-Item -Path function:prompt -Destination function:_OLD_VIRTUAL_PROMPT - New-Variable -Name _PYTHON_VENV_PROMPT_PREFIX -Description "Python virtual environment prompt prefix" -Scope Global -Option ReadOnly -Visibility Public -Value $Prompt - - function global:prompt { - Write-Host -NoNewline -ForegroundColor Green "($_PYTHON_VENV_PROMPT_PREFIX) " - _OLD_VIRTUAL_PROMPT - } - $env:VIRTUAL_ENV_PROMPT = $Prompt -} - -# Clear PYTHONHOME -if (Test-Path -Path Env:PYTHONHOME) { - Copy-Item -Path Env:PYTHONHOME -Destination Env:_OLD_VIRTUAL_PYTHONHOME - Remove-Item -Path Env:PYTHONHOME -} - -# Add the venv to the PATH -Copy-Item -Path Env:PATH -Destination Env:_OLD_VIRTUAL_PATH -$Env:PATH = "$VenvExecDir$([System.IO.Path]::PathSeparator)$Env:PATH" diff --git a/backend/bin/activate b/backend/bin/activate deleted file mode 100644 index 913b2c3..0000000 --- a/backend/bin/activate +++ /dev/null @@ -1,70 +0,0 @@ -# This file must be used with "source bin/activate" *from bash* -# You cannot run it directly - -deactivate () { - # reset old environment variables - if [ -n "${_OLD_VIRTUAL_PATH:-}" ] ; then - PATH="${_OLD_VIRTUAL_PATH:-}" - export PATH - unset _OLD_VIRTUAL_PATH - fi - if [ -n "${_OLD_VIRTUAL_PYTHONHOME:-}" ] ; then - PYTHONHOME="${_OLD_VIRTUAL_PYTHONHOME:-}" - export PYTHONHOME - unset _OLD_VIRTUAL_PYTHONHOME - fi - - # Call hash to forget past commands. Without forgetting - # past commands the $PATH changes we made may not be respected - hash -r 2> /dev/null - - if [ -n "${_OLD_VIRTUAL_PS1:-}" ] ; then - PS1="${_OLD_VIRTUAL_PS1:-}" - export PS1 - unset _OLD_VIRTUAL_PS1 - fi - - unset VIRTUAL_ENV - unset VIRTUAL_ENV_PROMPT - if [ ! "${1:-}" = "nondestructive" ] ; then - # Self destruct! - unset -f deactivate - fi -} - -# unset irrelevant variables -deactivate nondestructive - -# on Windows, a path can contain colons and backslashes and has to be converted: -if [ "${OSTYPE:-}" = "cygwin" ] || [ "${OSTYPE:-}" = "msys" ] ; then - # transform D:\path\to\venv to /d/path/to/venv on MSYS - # and to /cygdrive/d/path/to/venv on Cygwin - export VIRTUAL_ENV=$(cygpath "/Users/vaibhavgeek/kleo/backend/backend") -else - # use the path as-is - export VIRTUAL_ENV="/Users/vaibhavgeek/kleo/backend/backend" -fi - -_OLD_VIRTUAL_PATH="$PATH" -PATH="$VIRTUAL_ENV/bin:$PATH" -export PATH - -# unset PYTHONHOME if set -# this will fail if PYTHONHOME is set to the empty string (which is bad anyway) -# could use `if (set -u; : $PYTHONHOME) ;` in bash -if [ -n "${PYTHONHOME:-}" ] ; then - _OLD_VIRTUAL_PYTHONHOME="${PYTHONHOME:-}" - unset PYTHONHOME -fi - -if [ -z "${VIRTUAL_ENV_DISABLE_PROMPT:-}" ] ; then - _OLD_VIRTUAL_PS1="${PS1:-}" - PS1="(backend) ${PS1:-}" - export PS1 - VIRTUAL_ENV_PROMPT="(backend) " - export VIRTUAL_ENV_PROMPT -fi - -# Call hash to forget past commands. Without forgetting -# past commands the $PATH changes we made may not be respected -hash -r 2> /dev/null diff --git a/backend/bin/activate.csh b/backend/bin/activate.csh deleted file mode 100644 index a938b77..0000000 --- a/backend/bin/activate.csh +++ /dev/null @@ -1,27 +0,0 @@ -# This file must be used with "source bin/activate.csh" *from csh*. -# You cannot run it directly. - -# Created by Davide Di Blasi . -# Ported to Python 3.3 venv by Andrew Svetlov - -alias deactivate 'test $?_OLD_VIRTUAL_PATH != 0 && setenv PATH "$_OLD_VIRTUAL_PATH" && unset _OLD_VIRTUAL_PATH; rehash; test $?_OLD_VIRTUAL_PROMPT != 0 && set prompt="$_OLD_VIRTUAL_PROMPT" && unset _OLD_VIRTUAL_PROMPT; unsetenv VIRTUAL_ENV; unsetenv VIRTUAL_ENV_PROMPT; test "\!:*" != "nondestructive" && unalias deactivate' - -# Unset irrelevant variables. -deactivate nondestructive - -setenv VIRTUAL_ENV "/Users/vaibhavgeek/kleo/backend/backend" - -set _OLD_VIRTUAL_PATH="$PATH" -setenv PATH "$VIRTUAL_ENV/bin:$PATH" - - -set _OLD_VIRTUAL_PROMPT="$prompt" - -if (! "$?VIRTUAL_ENV_DISABLE_PROMPT") then - set prompt = "(backend) $prompt" - setenv VIRTUAL_ENV_PROMPT "(backend) " -endif - -alias pydoc python -m pydoc - -rehash diff --git a/backend/bin/activate.fish b/backend/bin/activate.fish deleted file mode 100644 index 8605d5b..0000000 --- a/backend/bin/activate.fish +++ /dev/null @@ -1,69 +0,0 @@ -# This file must be used with "source /bin/activate.fish" *from fish* -# (https://fishshell.com/). You cannot run it directly. - -function deactivate -d "Exit virtual environment and return to normal shell environment" - # reset old environment variables - if test -n "$_OLD_VIRTUAL_PATH" - set -gx PATH $_OLD_VIRTUAL_PATH - set -e _OLD_VIRTUAL_PATH - end - if test -n "$_OLD_VIRTUAL_PYTHONHOME" - set -gx PYTHONHOME $_OLD_VIRTUAL_PYTHONHOME - set -e _OLD_VIRTUAL_PYTHONHOME - end - - if test -n "$_OLD_FISH_PROMPT_OVERRIDE" - set -e _OLD_FISH_PROMPT_OVERRIDE - # prevents error when using nested fish instances (Issue #93858) - if functions -q _old_fish_prompt - functions -e fish_prompt - functions -c _old_fish_prompt fish_prompt - functions -e _old_fish_prompt - end - end - - set -e VIRTUAL_ENV - set -e VIRTUAL_ENV_PROMPT - if test "$argv[1]" != "nondestructive" - # Self-destruct! - functions -e deactivate - end -end - -# Unset irrelevant variables. -deactivate nondestructive - -set -gx VIRTUAL_ENV "/Users/vaibhavgeek/kleo/backend/backend" - -set -gx _OLD_VIRTUAL_PATH $PATH -set -gx PATH "$VIRTUAL_ENV/bin" $PATH - -# Unset PYTHONHOME if set. -if set -q PYTHONHOME - set -gx _OLD_VIRTUAL_PYTHONHOME $PYTHONHOME - set -e PYTHONHOME -end - -if test -z "$VIRTUAL_ENV_DISABLE_PROMPT" - # fish uses a function instead of an env var to generate the prompt. - - # Save the current fish_prompt function as the function _old_fish_prompt. - functions -c fish_prompt _old_fish_prompt - - # With the original prompt function renamed, we can override with our own. - function fish_prompt - # Save the return status of the last command. - set -l old_status $status - - # Output the venv prompt; color taken from the blue of the Python logo. - printf "%s%s%s" (set_color 4B8BBE) "(backend) " (set_color normal) - - # Restore the return status of the previous command. - echo "exit $old_status" | . - # Output the original/"old" prompt. - _old_fish_prompt - end - - set -gx _OLD_FISH_PROMPT_OVERRIDE "$VIRTUAL_ENV" - set -gx VIRTUAL_ENV_PROMPT "(backend) " -end diff --git a/backend/bin/celery b/backend/bin/celery deleted file mode 100755 index f747135..0000000 --- a/backend/bin/celery +++ /dev/null @@ -1,8 +0,0 @@ -#!/Users/vaibhavgeek/kleo/backend/backend/bin/python3.12 -# -*- coding: utf-8 -*- -import re -import sys -from celery.__main__ import main -if __name__ == '__main__': - sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) - sys.exit(main()) diff --git a/backend/bin/convert-caffe2-to-onnx b/backend/bin/convert-caffe2-to-onnx deleted file mode 100755 index 261c0d4..0000000 --- a/backend/bin/convert-caffe2-to-onnx +++ /dev/null @@ -1,8 +0,0 @@ -#!/Users/vaibhavgeek/kleo/backend/backend/bin/python3.12 -# -*- coding: utf-8 -*- -import re -import sys -from caffe2.python.onnx.bin.conversion import caffe2_to_onnx -if __name__ == '__main__': - sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) - sys.exit(caffe2_to_onnx()) diff --git a/backend/bin/convert-onnx-to-caffe2 b/backend/bin/convert-onnx-to-caffe2 deleted file mode 100755 index 02942ab..0000000 --- a/backend/bin/convert-onnx-to-caffe2 +++ /dev/null @@ -1,8 +0,0 @@ -#!/Users/vaibhavgeek/kleo/backend/backend/bin/python3.12 -# -*- coding: utf-8 -*- -import re -import sys -from caffe2.python.onnx.bin.conversion import onnx_to_caffe2 -if __name__ == '__main__': - sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) - sys.exit(onnx_to_caffe2()) diff --git a/backend/bin/dotenv b/backend/bin/dotenv deleted file mode 100755 index ab832a4..0000000 --- a/backend/bin/dotenv +++ /dev/null @@ -1,8 +0,0 @@ -#!/Users/vaibhavgeek/kleo/backend/backend/bin/python3.12 -# -*- coding: utf-8 -*- -import re -import sys -from dotenv.__main__ import cli -if __name__ == '__main__': - sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) - sys.exit(cli()) diff --git a/backend/bin/f2py b/backend/bin/f2py deleted file mode 100755 index 6265c88..0000000 --- a/backend/bin/f2py +++ /dev/null @@ -1,8 +0,0 @@ -#!/Users/vaibhavgeek/kleo/backend/backend/bin/python3.12 -# -*- coding: utf-8 -*- -import re -import sys -from numpy.f2py.f2py2e import main -if __name__ == '__main__': - sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) - sys.exit(main()) diff --git a/backend/bin/flask b/backend/bin/flask deleted file mode 100755 index 080b2f1..0000000 --- a/backend/bin/flask +++ /dev/null @@ -1,8 +0,0 @@ -#!/Users/vaibhavgeek/kleo/backend/backend/bin/python3.12 -# -*- coding: utf-8 -*- -import re -import sys -from flask.cli import main -if __name__ == '__main__': - sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) - sys.exit(main()) diff --git a/backend/bin/gunicorn b/backend/bin/gunicorn deleted file mode 100755 index 36cac4c..0000000 --- a/backend/bin/gunicorn +++ /dev/null @@ -1,8 +0,0 @@ -#!/Users/vaibhavgeek/kleo/backend/backend/bin/python3.12 -# -*- coding: utf-8 -*- -import re -import sys -from gunicorn.app.wsgiapp import run -if __name__ == '__main__': - sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) - sys.exit(run()) diff --git a/backend/bin/huggingface-cli b/backend/bin/huggingface-cli deleted file mode 100755 index fddb746..0000000 --- a/backend/bin/huggingface-cli +++ /dev/null @@ -1,8 +0,0 @@ -#!/Users/vaibhavgeek/kleo/backend/backend/bin/python3.12 -# -*- coding: utf-8 -*- -import re -import sys -from huggingface_hub.commands.huggingface_cli import main -if __name__ == '__main__': - sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) - sys.exit(main()) diff --git a/backend/bin/isympy b/backend/bin/isympy deleted file mode 100755 index 70674aa..0000000 --- a/backend/bin/isympy +++ /dev/null @@ -1,8 +0,0 @@ -#!/Users/vaibhavgeek/kleo/backend/backend/bin/python3.12 -# -*- coding: utf-8 -*- -import re -import sys -from isympy import main -if __name__ == '__main__': - sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) - sys.exit(main()) diff --git a/backend/bin/markdown-it b/backend/bin/markdown-it deleted file mode 100755 index c168b44..0000000 --- a/backend/bin/markdown-it +++ /dev/null @@ -1,8 +0,0 @@ -#!/Users/vaibhavgeek/kleo/backend/backend/bin/python3.12 -# -*- coding: utf-8 -*- -import re -import sys -from markdown_it.cli.parse import main -if __name__ == '__main__': - sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) - sys.exit(main()) diff --git a/backend/bin/nltk b/backend/bin/nltk deleted file mode 100755 index 36ed78e..0000000 --- a/backend/bin/nltk +++ /dev/null @@ -1,8 +0,0 @@ -#!/Users/vaibhavgeek/kleo/backend/backend/bin/python3.12 -# -*- coding: utf-8 -*- -import re -import sys -from nltk.cli import cli -if __name__ == '__main__': - sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) - sys.exit(cli()) diff --git a/backend/bin/normalizer b/backend/bin/normalizer deleted file mode 100755 index bfd0bf2..0000000 --- a/backend/bin/normalizer +++ /dev/null @@ -1,8 +0,0 @@ -#!/Users/vaibhavgeek/kleo/backend/backend/bin/python3.12 -# -*- coding: utf-8 -*- -import re -import sys -from charset_normalizer.cli import cli_detect -if __name__ == '__main__': - sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) - sys.exit(cli_detect()) diff --git a/backend/bin/numpy-config b/backend/bin/numpy-config deleted file mode 100755 index 96e2fa0..0000000 --- a/backend/bin/numpy-config +++ /dev/null @@ -1,8 +0,0 @@ -#!/Users/vaibhavgeek/kleo/backend/backend/bin/python3.12 -# -*- coding: utf-8 -*- -import re -import sys -from numpy._configtool import main -if __name__ == '__main__': - sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) - sys.exit(main()) diff --git a/backend/bin/pip b/backend/bin/pip deleted file mode 100755 index 382cf89..0000000 --- a/backend/bin/pip +++ /dev/null @@ -1,8 +0,0 @@ -#!/Users/vaibhavgeek/kleo/backend/backend/bin/python3.12 -# -*- coding: utf-8 -*- -import re -import sys -from pip._internal.cli.main import main -if __name__ == '__main__': - sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) - sys.exit(main()) diff --git a/backend/bin/pip3 b/backend/bin/pip3 deleted file mode 100755 index 382cf89..0000000 --- a/backend/bin/pip3 +++ /dev/null @@ -1,8 +0,0 @@ -#!/Users/vaibhavgeek/kleo/backend/backend/bin/python3.12 -# -*- coding: utf-8 -*- -import re -import sys -from pip._internal.cli.main import main -if __name__ == '__main__': - sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) - sys.exit(main()) diff --git a/backend/bin/pip3.12 b/backend/bin/pip3.12 deleted file mode 100755 index 382cf89..0000000 --- a/backend/bin/pip3.12 +++ /dev/null @@ -1,8 +0,0 @@ -#!/Users/vaibhavgeek/kleo/backend/backend/bin/python3.12 -# -*- coding: utf-8 -*- -import re -import sys -from pip._internal.cli.main import main -if __name__ == '__main__': - sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) - sys.exit(main()) diff --git a/backend/bin/pygmentize b/backend/bin/pygmentize deleted file mode 100755 index 855bf0f..0000000 --- a/backend/bin/pygmentize +++ /dev/null @@ -1,8 +0,0 @@ -#!/Users/vaibhavgeek/kleo/backend/backend/bin/python3.12 -# -*- coding: utf-8 -*- -import re -import sys -from pygments.cmdline import main -if __name__ == '__main__': - sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) - sys.exit(main()) diff --git a/backend/bin/python b/backend/bin/python deleted file mode 120000 index 11b9d88..0000000 --- a/backend/bin/python +++ /dev/null @@ -1 +0,0 @@ -python3.12 \ No newline at end of file diff --git a/backend/bin/python3 b/backend/bin/python3 deleted file mode 120000 index 11b9d88..0000000 --- a/backend/bin/python3 +++ /dev/null @@ -1 +0,0 @@ -python3.12 \ No newline at end of file diff --git a/backend/bin/python3.12 b/backend/bin/python3.12 deleted file mode 120000 index a3f0508..0000000 --- a/backend/bin/python3.12 +++ /dev/null @@ -1 +0,0 @@ -/opt/homebrew/opt/python@3.12/bin/python3.12 \ No newline at end of file diff --git a/backend/bin/spacy b/backend/bin/spacy deleted file mode 100755 index c0bf28a..0000000 --- a/backend/bin/spacy +++ /dev/null @@ -1,8 +0,0 @@ -#!/Users/vaibhavgeek/kleo/backend/backend/bin/python3.12 -# -*- coding: utf-8 -*- -import re -import sys -from spacy.cli import setup_cli -if __name__ == '__main__': - sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) - sys.exit(setup_cli()) diff --git a/backend/bin/tldextract b/backend/bin/tldextract deleted file mode 100755 index 33bda29..0000000 --- a/backend/bin/tldextract +++ /dev/null @@ -1,8 +0,0 @@ -#!/Users/vaibhavgeek/kleo/backend/backend/bin/python3.12 -# -*- coding: utf-8 -*- -import re -import sys -from tldextract.cli import main -if __name__ == '__main__': - sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) - sys.exit(main()) diff --git a/backend/bin/torchfrtrace b/backend/bin/torchfrtrace deleted file mode 100755 index 05e61b0..0000000 --- a/backend/bin/torchfrtrace +++ /dev/null @@ -1,8 +0,0 @@ -#!/Users/vaibhavgeek/kleo/backend/backend/bin/python3.12 -# -*- coding: utf-8 -*- -import re -import sys -from tools.flight_recorder.fr_trace import main -if __name__ == '__main__': - sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) - sys.exit(main()) diff --git a/backend/bin/torchrun b/backend/bin/torchrun deleted file mode 100755 index 7ca1c7d..0000000 --- a/backend/bin/torchrun +++ /dev/null @@ -1,8 +0,0 @@ -#!/Users/vaibhavgeek/kleo/backend/backend/bin/python3.12 -# -*- coding: utf-8 -*- -import re -import sys -from torch.distributed.run import main -if __name__ == '__main__': - sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) - sys.exit(main()) diff --git a/backend/bin/tqdm b/backend/bin/tqdm deleted file mode 100755 index 8e47f23..0000000 --- a/backend/bin/tqdm +++ /dev/null @@ -1,8 +0,0 @@ -#!/Users/vaibhavgeek/kleo/backend/backend/bin/python3.12 -# -*- coding: utf-8 -*- -import re -import sys -from tqdm.cli import main -if __name__ == '__main__': - sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) - sys.exit(main()) diff --git a/backend/bin/transformers-cli b/backend/bin/transformers-cli deleted file mode 100755 index 2499a67..0000000 --- a/backend/bin/transformers-cli +++ /dev/null @@ -1,8 +0,0 @@ -#!/Users/vaibhavgeek/kleo/backend/backend/bin/python3.12 -# -*- coding: utf-8 -*- -import re -import sys -from transformers.commands.transformers_cli import main -if __name__ == '__main__': - sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) - sys.exit(main()) diff --git a/backend/bin/typer b/backend/bin/typer deleted file mode 100755 index 29ac77b..0000000 --- a/backend/bin/typer +++ /dev/null @@ -1,8 +0,0 @@ -#!/Users/vaibhavgeek/kleo/backend/backend/bin/python3.12 -# -*- coding: utf-8 -*- -import re -import sys -from typer.cli import main -if __name__ == '__main__': - sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) - sys.exit(main()) diff --git a/backend/bin/weasel b/backend/bin/weasel deleted file mode 100755 index d6e5ee8..0000000 --- a/backend/bin/weasel +++ /dev/null @@ -1,8 +0,0 @@ -#!/Users/vaibhavgeek/kleo/backend/backend/bin/python3.12 -# -*- coding: utf-8 -*- -import re -import sys -from weasel.cli import app -if __name__ == '__main__': - sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) - sys.exit(app()) diff --git a/backend/pyvenv.cfg b/backend/pyvenv.cfg deleted file mode 100644 index 9861c36..0000000 --- a/backend/pyvenv.cfg +++ /dev/null @@ -1,5 +0,0 @@ -home = /opt/homebrew/opt/python@3.12/bin -include-system-site-packages = false -version = 3.12.5 -executable = /opt/homebrew/Cellar/python@3.12/3.12.5/Frameworks/Python.framework/Versions/3.12/bin/python3.12 -command = /opt/homebrew/opt/python@3.12/bin/python3.12 -m venv /Users/vaibhavgeek/kleo/backend/backend diff --git a/backend/share/man/man1/isympy.1 b/backend/share/man/man1/isympy.1 deleted file mode 100644 index 0ff9661..0000000 --- a/backend/share/man/man1/isympy.1 +++ /dev/null @@ -1,188 +0,0 @@ -'\" -*- coding: us-ascii -*- -.if \n(.g .ds T< \\FC -.if \n(.g .ds T> \\F[\n[.fam]] -.de URL -\\$2 \(la\\$1\(ra\\$3 -.. -.if \n(.g .mso www.tmac -.TH isympy 1 2007-10-8 "" "" -.SH NAME -isympy \- interactive shell for SymPy -.SH SYNOPSIS -'nh -.fi -.ad l -\fBisympy\fR \kx -.if (\nx>(\n(.l/2)) .nr x (\n(.l/5) -'in \n(.iu+\nxu -[\fB-c\fR | \fB--console\fR] [\fB-p\fR ENCODING | \fB--pretty\fR ENCODING] [\fB-t\fR TYPE | \fB--types\fR TYPE] [\fB-o\fR ORDER | \fB--order\fR ORDER] [\fB-q\fR | \fB--quiet\fR] [\fB-d\fR | \fB--doctest\fR] [\fB-C\fR | \fB--no-cache\fR] [\fB-a\fR | \fB--auto\fR] [\fB-D\fR | \fB--debug\fR] [ --- | PYTHONOPTIONS] -'in \n(.iu-\nxu -.ad b -'hy -'nh -.fi -.ad l -\fBisympy\fR \kx -.if (\nx>(\n(.l/2)) .nr x (\n(.l/5) -'in \n(.iu+\nxu -[ -{\fB-h\fR | \fB--help\fR} -| -{\fB-v\fR | \fB--version\fR} -] -'in \n(.iu-\nxu -.ad b -'hy -.SH DESCRIPTION -isympy is a Python shell for SymPy. It is just a normal python shell -(ipython shell if you have the ipython package installed) that executes -the following commands so that you don't have to: -.PP -.nf -\*(T< ->>> from __future__ import division ->>> from sympy import * ->>> x, y, z = symbols("x,y,z") ->>> k, m, n = symbols("k,m,n", integer=True) - \*(T> -.fi -.PP -So starting isympy is equivalent to starting python (or ipython) and -executing the above commands by hand. It is intended for easy and quick -experimentation with SymPy. For more complicated programs, it is recommended -to write a script and import things explicitly (using the "from sympy -import sin, log, Symbol, ..." idiom). -.SH OPTIONS -.TP -\*(T<\fB\-c \fR\*(T>\fISHELL\fR, \*(T<\fB\-\-console=\fR\*(T>\fISHELL\fR -Use the specified shell (python or ipython) as -console backend instead of the default one (ipython -if present or python otherwise). - -Example: isympy -c python - -\fISHELL\fR could be either -\&'ipython' or 'python' -.TP -\*(T<\fB\-p \fR\*(T>\fIENCODING\fR, \*(T<\fB\-\-pretty=\fR\*(T>\fIENCODING\fR -Setup pretty printing in SymPy. By default, the most pretty, unicode -printing is enabled (if the terminal supports it). You can use less -pretty ASCII printing instead or no pretty printing at all. - -Example: isympy -p no - -\fIENCODING\fR must be one of 'unicode', -\&'ascii' or 'no'. -.TP -\*(T<\fB\-t \fR\*(T>\fITYPE\fR, \*(T<\fB\-\-types=\fR\*(T>\fITYPE\fR -Setup the ground types for the polys. By default, gmpy ground types -are used if gmpy2 or gmpy is installed, otherwise it falls back to python -ground types, which are a little bit slower. You can manually -choose python ground types even if gmpy is installed (e.g., for testing purposes). - -Note that sympy ground types are not supported, and should be used -only for experimental purposes. - -Note that the gmpy1 ground type is primarily intended for testing; it the -use of gmpy even if gmpy2 is available. - -This is the same as setting the environment variable -SYMPY_GROUND_TYPES to the given ground type (e.g., -SYMPY_GROUND_TYPES='gmpy') - -The ground types can be determined interactively from the variable -sympy.polys.domains.GROUND_TYPES inside the isympy shell itself. - -Example: isympy -t python - -\fITYPE\fR must be one of 'gmpy', -\&'gmpy1' or 'python'. -.TP -\*(T<\fB\-o \fR\*(T>\fIORDER\fR, \*(T<\fB\-\-order=\fR\*(T>\fIORDER\fR -Setup the ordering of terms for printing. The default is lex, which -orders terms lexicographically (e.g., x**2 + x + 1). You can choose -other orderings, such as rev-lex, which will use reverse -lexicographic ordering (e.g., 1 + x + x**2). - -Note that for very large expressions, ORDER='none' may speed up -printing considerably, with the tradeoff that the order of the terms -in the printed expression will have no canonical order - -Example: isympy -o rev-lax - -\fIORDER\fR must be one of 'lex', 'rev-lex', 'grlex', -\&'rev-grlex', 'grevlex', 'rev-grevlex', 'old', or 'none'. -.TP -\*(T<\fB\-q\fR\*(T>, \*(T<\fB\-\-quiet\fR\*(T> -Print only Python's and SymPy's versions to stdout at startup, and nothing else. -.TP -\*(T<\fB\-d\fR\*(T>, \*(T<\fB\-\-doctest\fR\*(T> -Use the same format that should be used for doctests. This is -equivalent to '\fIisympy -c python -p no\fR'. -.TP -\*(T<\fB\-C\fR\*(T>, \*(T<\fB\-\-no\-cache\fR\*(T> -Disable the caching mechanism. Disabling the cache may slow certain -operations down considerably. This is useful for testing the cache, -or for benchmarking, as the cache can result in deceptive benchmark timings. - -This is the same as setting the environment variable SYMPY_USE_CACHE -to 'no'. -.TP -\*(T<\fB\-a\fR\*(T>, \*(T<\fB\-\-auto\fR\*(T> -Automatically create missing symbols. Normally, typing a name of a -Symbol that has not been instantiated first would raise NameError, -but with this option enabled, any undefined name will be -automatically created as a Symbol. This only works in IPython 0.11. - -Note that this is intended only for interactive, calculator style -usage. In a script that uses SymPy, Symbols should be instantiated -at the top, so that it's clear what they are. - -This will not override any names that are already defined, which -includes the single character letters represented by the mnemonic -QCOSINE (see the "Gotchas and Pitfalls" document in the -documentation). You can delete existing names by executing "del -name" in the shell itself. You can see if a name is defined by typing -"'name' in globals()". - -The Symbols that are created using this have default assumptions. -If you want to place assumptions on symbols, you should create them -using symbols() or var(). - -Finally, this only works in the top level namespace. So, for -example, if you define a function in isympy with an undefined -Symbol, it will not work. -.TP -\*(T<\fB\-D\fR\*(T>, \*(T<\fB\-\-debug\fR\*(T> -Enable debugging output. This is the same as setting the -environment variable SYMPY_DEBUG to 'True'. The debug status is set -in the variable SYMPY_DEBUG within isympy. -.TP --- \fIPYTHONOPTIONS\fR -These options will be passed on to \fIipython (1)\fR shell. -Only supported when ipython is being used (standard python shell not supported). - -Two dashes (--) are required to separate \fIPYTHONOPTIONS\fR -from the other isympy options. - -For example, to run iSymPy without startup banner and colors: - -isympy -q -c ipython -- --colors=NoColor -.TP -\*(T<\fB\-h\fR\*(T>, \*(T<\fB\-\-help\fR\*(T> -Print help output and exit. -.TP -\*(T<\fB\-v\fR\*(T>, \*(T<\fB\-\-version\fR\*(T> -Print isympy version information and exit. -.SH FILES -.TP -\*(T<\fI${HOME}/.sympy\-history\fR\*(T> -Saves the history of commands when using the python -shell as backend. -.SH BUGS -The upstreams BTS can be found at \(lahttps://github.com/sympy/sympy/issues\(ra -Please report all bugs that you find in there, this will help improve -the overall quality of SymPy. -.SH "SEE ALSO" -\fBipython\fR(1), \fBpython\fR(1) diff --git a/celerybeat-schedule.db b/celerybeat-schedule.db deleted file mode 100644 index 54dd42567da9c23dab51bf69e0af5efc0e8a399f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16384 zcmeI%Jx?1k7zc2Z9_7NDL5QkS*A8L0t5m7t10bdd23lt8NK73OF45U(6{M3g@gjM{ ze2IRFF5Nm+{QwmmIxw(T>dWI`RE7c@669~m_dIv!m&d;(Q`qChj4@VWEc(LO9HnfU zu`vq1vp6L5e)!-~h&76l&rkC5J4N687~k)_#luqXd|PY?0SG_<0uX=z1Rwwb2tWV= z5V$u2G5gJb@^gO1zwyuf6aUCRP`@|jqfiJy00Izz00bZa0SG_<0wXUlhz`@9X$YBT zTW#4KMC+;98$>77AY;d0r7zQEmkRMt7P{5Rg`n4`;jh%v)$Dw)+suqia``@aTV!3O zotY)MR=`rx(i!T282zHXWK_W50uG?aHg^ zv0Is(_%U5sc>ZMe#f-C2w{P|+h|M=Ew8_$j+jkpo?Q6x(g>rPLgDQ+Ka~i28Y}GH` zlx>sIeVx@O>+FCgAFccAQt3)(D6!AFMW-RP4hK!Pi_UIxS*40G z%&F?Xv#jM#&4$v|f?B-3oT`!9B%aOr&9B^Aeu3!+2ucT0=~7AjElK$;AMby@5+naZ z0RRLb009U<00Izz00bZa0SG`~1O$HlL4yDUAOHafKmY;|fB*y_009U<;Gqlr1%NHc AN&o-= diff --git a/docker-compose.yml b/docker-compose.yml index b80faed..37c01eb 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -3,21 +3,9 @@ services: image: redis ports: - 6379:6379 - api: - build: . - command: gunicorn -w 4 --bind 0.0.0.0:5001 run:app - ports: - - 5001:5001 - volumes: - - .:/app - container_name: development + celery: build: . command: celery -A run.celery worker --pool=prefork --concurrency=8 --loglevel=info - depends_on: - - api volumes: - - .:/app - -volumes: - app: \ No newline at end of file + - .:/app \ No newline at end of file diff --git a/dump.rdb b/dump.rdb deleted file mode 100644 index ce053a5af814cce3f03da9ddbf39a2368477ca8c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 485 zcmZvYKWh|G6vf{r%qB643cHbDu_M-ZxcA+e_hz<`M6|F~ur$0scft^N7iNt;20HF)Co@PN_ zOZ)clP$|_@A2+Rk&_CFuyX(Qd{|d7Bc3d4_jxKvj?WnJBX6>1@*~5RPEHWpB8~L0F zf*}LBrUEL80>TA)lqxu1s`2X9cpo(})x;1qAB~4zz#--k3#