├── src └── google_flights_scraper │ ├── __init__.py │ ├── models.py │ ├── exception.py │ ├── conf.py │ ├── __main__.py │ ├── collector.py │ └── scraper.py ├── .gitignore ├── Makefile ├── .flake8 ├── pyproject.toml ├── .pre-commit-config.yaml ├── examples └── google_flights_scraper_example.py ├── README.md └── poetry.lock /src/google_flights_scraper/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | #mypy cache 7 | .mypy_cache 8 | 9 | # Environments 10 | .env 11 | .venv 12 | env/ 13 | venv/ 14 | ENV/ 15 | env.bak/ 16 | venv.bak/ 17 | 18 | # Generated CSV files 19 | *.csv 20 | -------------------------------------------------------------------------------- /src/google_flights_scraper/models.py: -------------------------------------------------------------------------------- 1 | """ 2 | Pydantic models for Google Flights scraper. 3 | """ 4 | 5 | from pydantic import BaseModel 6 | 7 | 8 | class Flight(BaseModel): 9 | price: str 10 | departure_time: str 11 | arrival_time: str 12 | airline: str 13 | stops: str 14 | full_detail: str 15 | -------------------------------------------------------------------------------- /src/google_flights_scraper/exception.py: -------------------------------------------------------------------------------- 1 | """ 2 | Module for base exception class. 3 | """ 4 | 5 | 6 | class BaseException(Exception): 7 | """Base exception class""" 8 | 9 | message: str = "" 10 | 11 | def __init__(self, message: str | None = None) -> None: 12 | super().__init__(message or self.message) 13 | -------------------------------------------------------------------------------- /src/google_flights_scraper/conf.py: -------------------------------------------------------------------------------- 1 | """ 2 | Config module for google_flights_scraper. 3 | """ 4 | 5 | from pydantic_settings import BaseSettings 6 | 7 | 8 | class GoogleFlightsScraperSettings(BaseSettings): 9 | """Settings class for Google Flights Scraper""" 10 | 11 | flights_url: str = "https://www.google.com/travel/flights" 12 | 13 | 14 | google_flights_scraper_settings = GoogleFlightsScraperSettings() 15 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Makefile for running the Google Flights scraper 2 | 3 | 4 | .PHONY: install 5 | install: 6 | pip install poetry==1.8.2 7 | poetry install 8 | 9 | 10 | .PHONY: scrape 11 | scrape: 12 | @if [ -z "$(URL)" ]; then \ 13 | echo 'Error: A URL of a Google Flights page is required. Use make scrape URL=""'; \ 14 | exit 1; \ 15 | else \ 16 | poetry run python -m google_flights_scraper --url="$(URL)"; \ 17 | fi 18 | -------------------------------------------------------------------------------- /.flake8: -------------------------------------------------------------------------------- 1 | [flake8] 2 | min_python_version = 3.11 3 | max-line-length = 88 4 | ban-relative-imports = true 5 | format-greedy = 1 6 | inline-quotes = double 7 | mypy-init-return = true 8 | enable-extensions = TC, TC1 9 | type-checking-exempt-modules = typing, typing-extensions 10 | eradicate-whitelist-extend = ^-.*; 11 | extend-ignore = 12 | E203, 13 | SIM106, 14 | E501, 15 | INP001, 16 | W503, 17 | ANN001, 18 | ANN201, 19 | ANN002, 20 | ANN003, 21 | ANN101, 22 | ANN102, 23 | ANN204, 24 | ANN205, 25 | FS001, 26 | SIM119, 27 | -------------------------------------------------------------------------------- /src/google_flights_scraper/__main__.py: -------------------------------------------------------------------------------- 1 | """ 2 | Main module for google_flights_scraper. 3 | """ 4 | 5 | import logging 6 | 7 | import click 8 | 9 | from google_flights_scraper.collector import GoogleFlightsDataCollector 10 | 11 | 12 | logging.basicConfig(level=logging.INFO) 13 | 14 | 15 | @click.command() 16 | @click.option( 17 | "--url", 18 | help="The url for which to return Google Flights results for.", 19 | required=True, 20 | ) 21 | def scrape_google_flights(url: str) -> None: 22 | collector = GoogleFlightsDataCollector() 23 | collector.save_flight_data_for_url(url) 24 | 25 | 26 | if __name__ == "__main__": 27 | scrape_google_flights() 28 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.poetry] 2 | name = "google-flights-scraper" 3 | version = "0.1.0" 4 | description = "A tool for scraping Google Flights data." 5 | packages = [ 6 | { include = "google_flights_scraper", from = "src" }, 7 | ] 8 | authors = ["Ignas Šimkūnas "] 9 | readme = "README.md" 10 | 11 | [tool.poetry.dependencies] 12 | python = "^3.11" 13 | bs4 = "^0.0.2" 14 | httpx = "^0.27.0" 15 | pydantic = "^2.7.4" 16 | click = "^8.1.7" 17 | pandas = "^2.2.2" 18 | selenium = "^4.22.0" 19 | webdriver-manager = "^4.0.2" 20 | pydantic-settings = "^2.3.4" 21 | 22 | 23 | [build-system] 24 | requires = ["poetry-core"] 25 | build-backend = "poetry.core.masonry.api" 26 | 27 | [tool.mypy] 28 | files = "." 29 | ignore_missing_imports = true 30 | follow_imports = "silent" 31 | show_error_codes = true 32 | warn_redundant_casts = true 33 | warn_unused_configs = true 34 | warn_unused_ignores = true 35 | disallow_incomplete_defs = true 36 | 37 | [tool.isort] 38 | py_version = 311 39 | combine_as_imports = true 40 | profile = "black" 41 | lines_between_types = 1 42 | lines_after_imports = 2 43 | -------------------------------------------------------------------------------- /src/google_flights_scraper/collector.py: -------------------------------------------------------------------------------- 1 | """ 2 | Main module for collecting Google flights data. 3 | """ 4 | 5 | import logging 6 | 7 | from typing import List 8 | 9 | import pandas as pd 10 | 11 | from google_flights_scraper.models import Flight 12 | from google_flights_scraper.scraper import GoogleFlightsScraper 13 | 14 | 15 | DEFAULT_OUTPUT_FILE = "flights.csv" 16 | 17 | 18 | class GoogleFlightsDataCollector: 19 | """Data collector class for Google Flights""" 20 | 21 | def __init__( 22 | self, 23 | output_file: str | None = None, 24 | logger: logging.Logger | None = None, 25 | ) -> None: 26 | self._scraper = GoogleFlightsScraper() 27 | self._output_file = output_file if output_file else DEFAULT_OUTPUT_FILE 28 | self._logger = logger if logger else logging.getLogger(__name__) 29 | 30 | def _save_to_csv(self, flights: List[Flight]) -> None: 31 | """Saves given list of flights to a CSV file.""" 32 | self._logger.info(f"Writing {len(flights)} flights to {self._output_file}..") 33 | flight_objects = [flight.model_dump() for flight in flights] 34 | df = pd.DataFrame(flight_objects) 35 | df.to_csv(self._output_file) 36 | 37 | def save_flight_data_for_url(self, url: str) -> None: 38 | """ 39 | Scrapes data from Google flights for a given flight url and stores it into a CSV file. 40 | 41 | Args: 42 | url (str): The URL of the flight for which to get Google flights results. 43 | """ 44 | self._logger.info(f"Getting Google flights data for flight url {url}..") 45 | try: 46 | flights = self._scraper.get_flights_for_url(url) 47 | except Exception: 48 | self._logger.exception(f"Error when scraping Google flights for url {url}.") 49 | return 50 | 51 | if not flights: 52 | self._logger.info("No flights found.") 53 | return 54 | 55 | self._save_to_csv(flights) 56 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | repos: 2 | - repo: https://github.com/pre-commit/pre-commit-hooks 3 | rev: v4.6.0 4 | hooks: 5 | - id: trailing-whitespace 6 | - id: end-of-file-fixer 7 | - id: check-merge-conflict 8 | - id: check-case-conflict 9 | - id: check-json 10 | - id: check-toml 11 | - id: check-yaml 12 | - id: pretty-format-json 13 | args: [--autofix, --no-ensure-ascii, --no-sort-keys] 14 | - id: check-ast 15 | - id: debug-statements 16 | - id: check-docstring-first 17 | 18 | - repo: https://github.com/pre-commit/pygrep-hooks 19 | rev: v1.10.0 20 | hooks: 21 | - id: python-check-mock-methods 22 | - id: python-use-type-annotations 23 | - id: python-check-blanket-type-ignore 24 | - id: python-check-blanket-noqa 25 | 26 | - repo: https://github.com/asottile/yesqa 27 | rev: v1.5.0 28 | hooks: 29 | - id: yesqa 30 | additional_dependencies: &flake8_deps 31 | - flake8-annotations==3.1.1 32 | - flake8-broken-line==1.0.0 33 | - flake8-bugbear==24.4.26 34 | - flake8-comprehensions==3.14.0 35 | - flake8-eradicate==1.5.0 36 | - flake8-no-pep420==2.7.0 37 | - flake8-quotes==3.4.0 38 | - flake8-simplify==0.21.0 39 | - flake8-tidy-imports==4.10.0 40 | - flake8-typing-imports==1.15.0 41 | - flake8-use-fstring==1.4 42 | 43 | - repo: https://github.com/pycqa/isort 44 | rev: 5.13.2 45 | hooks: 46 | - id: isort 47 | name: "isort (python)" 48 | types: [python] 49 | - id: isort 50 | name: "isort (pyi)" 51 | types: [pyi] 52 | args: [--lines-after-imports, "-1"] 53 | 54 | - repo: https://github.com/psf/black 55 | rev: 24.4.2 56 | hooks: 57 | - id: black 58 | 59 | - repo: https://github.com/pycqa/flake8 60 | rev: 7.1.0 61 | hooks: 62 | - id: flake8 63 | additional_dependencies: *flake8_deps 64 | 65 | - repo: https://github.com/pre-commit/mirrors-mypy 66 | rev: v1.10.1 67 | hooks: 68 | - id: mypy 69 | args: [--python-version=3.11] 70 | pass_filenames: false 71 | additional_dependencies: 72 | - types-requests 73 | 74 | - repo: https://github.com/pre-commit/pre-commit 75 | rev: v2.17.0 76 | hooks: 77 | - id: validate_manifest 78 | -------------------------------------------------------------------------------- /examples/google_flights_scraper_example.py: -------------------------------------------------------------------------------- 1 | import json 2 | 3 | import requests 4 | 5 | from bs4 import BeautifulSoup 6 | 7 | 8 | def get_price(soup_element): 9 | price = soup_element.find("div", "BVAVmf").find("div", "YMlIz").get_text() 10 | 11 | return price 12 | 13 | 14 | def get_time(soup_element): 15 | spans = ( 16 | soup_element.find("div", "Ir0Voe") 17 | .find("div", "zxVSec", recursive=False) 18 | .find_all("span", "eoY5cb") 19 | ) 20 | 21 | time = "" 22 | 23 | for span in spans: 24 | time = time + span.get_text() + "; " 25 | 26 | return time 27 | 28 | 29 | def get_airline(soup_element): 30 | airline = soup_element.find("div", "Ir0Voe").find("div", "sSHqwe") 31 | 32 | spans = airline.find_all("span", attrs={"class": None}, recursive=False) 33 | 34 | result = "" 35 | 36 | for span in spans: 37 | result = result + span.get_text() + "; " 38 | 39 | return result 40 | 41 | 42 | def save_results(results, filepath): 43 | with open(filepath, "w", encoding="utf-8") as file: 44 | json.dump(results, file, ensure_ascii=False, indent=4) 45 | 46 | return 47 | 48 | 49 | def get_flights_html(url): 50 | payload = { 51 | "source": "google", 52 | "render": "html", 53 | "url": url, 54 | } 55 | 56 | # Get response. 57 | response = requests.request( 58 | "POST", 59 | "https://realtime.oxylabs.io/v1/queries", 60 | auth=("username", "password"), 61 | json=payload, 62 | ) 63 | 64 | response_json = response.json() 65 | 66 | html = response_json["results"][0]["content"] 67 | 68 | return html 69 | 70 | 71 | def extract_flight_information_from_soup(soup_of_the_whole_page): 72 | flight_listings = soup_of_the_whole_page.find_all("li", "pIav2d") 73 | 74 | flights = [] 75 | 76 | for listing in flight_listings: 77 | if listing is not None: 78 | price = get_price(listing) 79 | time = get_time(listing) 80 | airline = get_airline(listing) 81 | 82 | flight = {"airline": airline, "time": time, "price": price} 83 | 84 | flights.append(flight) 85 | 86 | return flights 87 | 88 | 89 | def extract_flights_data_from_urls(urls): 90 | constructed_flight_results = [] 91 | 92 | for url in urls: 93 | html = get_flights_html(url) 94 | 95 | soup = BeautifulSoup(html, "html.parser") 96 | 97 | flights = extract_flight_information_from_soup(soup) 98 | 99 | constructed_flight_results.append({"url": url, "flight_data": flights}) 100 | 101 | return constructed_flight_results 102 | 103 | 104 | def main(): 105 | results_file = "data.json" 106 | 107 | urls = [ 108 | "https://www.google.com/travel/flights?tfs=CBsQAhooEgoyMDI0LTA3LTI4agwIAxIIL20vMDE1NnFyDAgCEggvbS8wNGpwbBooEgoyMDI0LTA4LTAxagwIAhIIL20vMDRqcGxyDAgDEggvbS8wMTU2cUABSAFSA0VVUnABemxDalJJTkRCNVRGbDBOMU5UVEdOQlJ6aG5lRUZDUnkwdExTMHRMUzB0TFMxM1pXc3lOMEZCUVVGQlIxZ3dhRWxSUVRoaWFtTkJFZ1pWTWpnMk1qSWFDZ2lRYnhBQ0dnTkZWVkk0SEhEN2VBPT2YAQGyARIYASABKgwIAxIIL20vMDRqcGw&hl=en-US&curr=EUR&sa=X&ved=0CAoQtY0DahgKEwiAz9bF5PaEAxUAAAAAHQAAAAAQngM", 109 | "https://www.google.com/travel/flights/search?tfs=CBwQAhooEgoyMDI0LTA3LTI4agwIAxIIL20vMDE1NnFyDAgDEggvbS8wN19rcRooEgoyMDI0LTA4LTAxagwIAxIIL20vMDdfa3FyDAgDEggvbS8wMTU2cUABSAFwAYIBCwj___________8BmAEB&hl=en-US&curr=EUR", 110 | ] 111 | 112 | constructed_flight_results = extract_flights_data_from_urls(urls) 113 | 114 | save_results(constructed_flight_results, results_file) 115 | 116 | 117 | if __name__ == "__main__": 118 | main() 119 | -------------------------------------------------------------------------------- /src/google_flights_scraper/scraper.py: -------------------------------------------------------------------------------- 1 | """ 2 | Module for scraping Google flights. 3 | """ 4 | 5 | import logging 6 | import time 7 | 8 | from typing import List 9 | 10 | from pydantic import ValidationError 11 | from selenium import webdriver 12 | from selenium.webdriver.chrome.options import Options 13 | from selenium.webdriver.chrome.service import Service 14 | from selenium.webdriver.common.by import By 15 | from webdriver_manager.chrome import ChromeDriverManager 16 | 17 | from google_flights_scraper.conf import google_flights_scraper_settings 18 | from google_flights_scraper.models import Flight 19 | 20 | 21 | logging.getLogger("WDM").setLevel(logging.ERROR) 22 | 23 | 24 | class ConsentFormAcceptError(BaseException): 25 | message = "Unable to accept Google consent form." 26 | 27 | 28 | class DriverInitializationError(BaseException): 29 | message = "Unable to initialize Chrome webdriver for scraping." 30 | 31 | 32 | class DriverGetFlightDataError(BaseException): 33 | message = "Unable to get Google flight data with Chrome webdriver." 34 | 35 | 36 | class GoogleFlightsScraper: 37 | """Class for scraping Google flights""" 38 | 39 | def __init__(self, logger: logging.Logger | None = None) -> None: 40 | self._logger = logger if logger else logging.getLogger(__name__) 41 | self._consent_button_xpath = "/html/body/c-wiz/div/div/div/div[2]/div[1]/div[3]/div[1]/div[1]/form[2]/div/div/button/span" 42 | 43 | def _init_chrome_driver(self) -> webdriver.Chrome: 44 | """Initializes Chrome webdriver""" 45 | chrome_options = Options() 46 | chrome_options.add_argument("--headless") 47 | chrome_options.add_argument("--no-sandbox") 48 | chrome_options.add_argument("--disable-dev-shm-usage") 49 | service = Service(ChromeDriverManager().install()) 50 | return webdriver.Chrome(service=service, options=chrome_options) 51 | 52 | def _click_consent_button(self, driver: webdriver.Chrome) -> None: 53 | """Clicks google consent form with selenium Chrome webdriver""" 54 | self._logger.info("Accepting consent form..") 55 | try: 56 | driver.get(google_flights_scraper_settings.flights_url) 57 | consent_button = driver.find_element( 58 | By.XPATH, 59 | self._consent_button_xpath, 60 | ) 61 | consent_button.click() 62 | except Exception as e: 63 | raise ConsentFormAcceptError from e 64 | 65 | time.sleep(2) 66 | 67 | def _get_data_from_flight_div(self, div: webdriver.Chrome) -> Flight: 68 | """Retrieves flight data from a div element and returns it as a Flight object.""" 69 | price = ( 70 | div.find_element( 71 | By.CLASS_NAME, 72 | "BVAVmf", 73 | ) 74 | .find_element(By.CLASS_NAME, "YMlIz") 75 | .find_element(By.TAG_NAME, "span") 76 | .get_attribute("aria-label") 77 | ) 78 | detail = div.find_element(By.CLASS_NAME, "JMc5Xc").get_attribute("aria-label") 79 | departure_time = div.find_element(By.CLASS_NAME, "wtdjmc").get_attribute( 80 | "aria-label" 81 | ) 82 | 83 | arrival_time = div.find_element(By.CLASS_NAME, "XWcVob").get_attribute( 84 | "aria-label" 85 | ) 86 | info_div = div.find_element(By.CLASS_NAME, "gKm0ye") 87 | airline = ( 88 | info_div.find_element(By.CLASS_NAME, "h1fkLb") 89 | .find_element(By.TAG_NAME, "span") 90 | .text 91 | ) 92 | 93 | stops = info_div.find_element(By.CLASS_NAME, "VG3hNb").text 94 | 95 | return Flight( 96 | price=price, 97 | departure_time=( 98 | departure_time.split("Departure time: ")[1] if departure_time else None 99 | ), 100 | arrival_time=( 101 | arrival_time.split("Arrival time: ")[1] if arrival_time else None 102 | ), 103 | airline=airline, 104 | stops=stops, 105 | full_detail=detail, 106 | ) 107 | 108 | def _get_flights_from_page( 109 | self, url: str, driver: webdriver.Chrome 110 | ) -> List[Flight]: 111 | """Retrieves Flight data from a Google flights search page.""" 112 | self._logger.info("Scraping Google flights page..") 113 | driver.get(url) 114 | time.sleep(5) 115 | flights = driver.find_elements(By.CLASS_NAME, "pIav2d") 116 | 117 | flight_data = [] 118 | 119 | for div in flights: 120 | try: 121 | flight_entry = self._get_data_from_flight_div(div) 122 | except ValidationError: 123 | self._logger.error( 124 | f"Data missing from flight div: {div.get_attribute('outerHTML')}" 125 | ) 126 | continue 127 | 128 | flight_data.append(flight_entry) 129 | 130 | return flight_data 131 | 132 | def get_flights_for_url(self, url: str) -> List[Flight]: 133 | """ 134 | Retrieves a list of flights queried in Google flights for a given Flight URL. 135 | 136 | Returns: 137 | List[Flight]: A list of Flight objects. 138 | Raises: 139 | ConsentFormAcceptError: If the Google consent form cannot be accepted. 140 | DriverInitializationError: If the Chrome webdriver cannot be initialized. 141 | DriverGetFlightDataError: If the Flight data cannot be scraped from the Google flights site. 142 | """ 143 | self._logger.info(f"Retrieving flights for {url}..") 144 | 145 | try: 146 | driver = self._init_chrome_driver() 147 | except Exception as e: 148 | raise DriverInitializationError from e 149 | 150 | try: 151 | self._click_consent_button(driver) 152 | except Exception as e: 153 | driver.close() 154 | raise e 155 | 156 | try: 157 | return self._get_flights_from_page(url, driver) 158 | except Exception as e: 159 | raise DriverGetFlightDataError from e 160 | finally: 161 | driver.close() 162 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # How to Scrape Google Flights with Python 2 | 3 | [![Oxylabs promo code](https://raw.githubusercontent.com/oxylabs/how-to-scrape-google-scholar/refs/heads/main/Google-Scraper-API-1090x275.png)](https://oxylabs.io/products/scraper-api/serp/google?utm_source=877&utm_medium=affiliate&groupid=877&utm_content=how-to-scrape-google-flights-github&transaction_id=102c8d36f7f0d0e5797b8f26152160) 4 | 5 | [![](https://dcbadge.limes.pink/api/server/Pds3gBmKMH?style=for-the-badge&theme=discord)](https://discord.gg/Pds3gBmKMH) [![YouTube](https://img.shields.io/badge/YouTube-Oxylabs-red?style=for-the-badge&logo=youtube&logoColor=white)](https://www.youtube.com/@oxylabs) 6 | 7 | * [Free Google Flights Scraper](#free-google-flights-scraper) 8 | + [Prerequisites](#prerequisites) 9 | + [Installation](#installation) 10 | + [Getting the URL for a Google Flights page](#getting-the-url-for-a-google-flights-page) 11 | + [Scraping Google Flights](#scraping-google-flights) 12 | + [Notes](#notes) 13 | * [Scrape public Google Flights data with Oxylabs API](#scrape-public-google-flights-data-with-oxylabs-api) 14 | + [Installing prerequisite libraries](#installing-prerequisite-libraries) 15 | + [Creating core structure](#creating-core-structure) 16 | + [Getting the price](#getting-the-price) 17 | + [Getting the flight time](#getting-the-flight-time) 18 | + [Getting the airline name](#getting-the-airline-name) 19 | + [Final result](#final-result) 20 | 21 | 22 | ## Free Google Flights Scraper 23 | 24 | A free tool used to get data from Google Flights for a provided Google Flights URL. 25 | 26 | ### Prerequisites 27 | 28 | To run this tool, you need to have Python 3.11 installed in your system. 29 | 30 | ### Installation 31 | 32 | Open up a terminal window, navigate to this repository and run this command: 33 | 34 | ```make install``` 35 | 36 | ### Getting the URL for a Google Flights page 37 | 38 | First of all, go to [Google Flights](https://www.google.com/travel/flights) in your browser and select your desired departure and arrival locations along with the dates. 39 | 40 | For this example, we'll be scraping flights from Berlin to Paris, two weeks apart. 41 | 42 | After clicking **Search**, you should see something like this. 43 | 44 | image 45 | 46 | Copy and save the URL from your browser, it will be used for scraping the data for this flight configuration. 47 | 48 | Here's the URL for this example 49 | ```https://www.google.com/travel/flights/search?tfs=CBwQAhooEgoyMDI0LTA5LTA0agwIAxIIL20vMDE1NnFyDAgDEggvbS8wNXF0ahooEgoyMDI0LTA5LTE4agwIAxIIL20vMDVxdGpyDAgDEggvbS8wMTU2cUABSAFwAYIBCwj___________8BmAEB``` 50 | 51 | ### Scraping Google Flights 52 | 53 | To get results from Google Flights, simply run this command in your terminal: 54 | 55 | ```make scrape URL=""``` 56 | 57 | With the URL we retrieved earlier, the command would look like this: 58 | 59 | ```make scrape URL="https://www.google.com/travel/flights/search?tfs=CBwQAhooEgoyMDI0LTA5LTA0agwIAxIIL20vMDE1NnFyDAgDEggvbS8wNXF0ahooEgoyMDI0LTA5LTE4agwIAxIIL20vMDVxdGpyDAgDEggvbS8wMTU2cUABSAFwAYIBCwj___________8BmAEB"``` 60 | 61 | Make sure to surround the URL with quotation marks, otherwise the tool might have trouble parsing it. 62 | 63 | After running the command, your terminal should look something like this: 64 | 65 | image 66 | 67 | After the tool has finished running, you should notice that a `flights.csv` file appeared in your current directory. 68 | 69 | This data in this file has these columns for the Google Flights data based on your provided URL: 70 | 71 | - `price` - The full price of a flight. 72 | - `departure_time` - The departure time of a flight. 73 | - `arrival_time` - The arrival time of a flight. 74 | - `airline` - The airline, or multiple airlines that operate the flight. 75 | - `stops` - The number of stops between the departure and arrival locations. 76 | - `full_detail` - The full detail of the flight in plain text. 77 | 78 | Here's an example of how the data can look like: 79 | 80 | image 81 | 82 | ### Notes 83 | 84 | In case the code doesn't work or your project is of bigger scale, please refer to the second part of the tutorial. There, we showcase how to scrape public data with Oxylabs Scraper API. 85 | 86 | ## Scrape public Google Flights data with Oxylabs API 87 | 88 | In case you were not able to carry out your project with the free scraper, you may use Oxylabs API instead. 89 | 90 | In this section of the guide, we’re going to demonstrate how to scrape public data from **flight pages** and generate **search results** with Python and [Oxylabs Google Flights API](https://oxylabs.io/products/scraper-api/serp/google/flights) (a part of Web Scraper API). To use the Oxylabs API, you'll need an **active subscription** – you can get a **free trial** by signing up [via the self-service dashboard](https://dashboard.oxylabs.io/). 91 | 92 | We’ll gather all sorts of data, including **price**, **flight time**, and **airline name**. 93 | 94 | Head to our blog to see the [complete article](https://oxylabs.io/blog/how-to-scrape-google-flights) with in-depth explanations and images for a visual reference. 95 | 96 | - [1. Installing prerequisite libraries](#1-installing-prerequisite-libraries) 97 | - [2. Creating core structure](#2-creating-core-structure) 98 | - [3. Getting the price](#3-getting-the-price) 99 | - [4. Getting the flight time](#4-getting-the-flight-time) 100 | - [5. Getting the airline name](#5-getting-the-airline-name) 101 | - [6. Final result](#6-final-result) 102 | 103 | ## Installing prerequisite libraries 104 | 105 | ```bash 106 | pip install bs4 107 | ``` 108 | 109 | ## Creating core structure 110 | 111 | To start off, let’s create a function that will take a URL as a parameter, scrape that URL with [Google Flights API](https://oxylabs.io/products/scraper-api/serp/google/flights) (you can get **a free 7-day trial** for it) and return the scraped HTML: 112 | 113 | ```python 114 | def get_flights_html(url): 115 | payload = { 116 | 'source': 'google', 117 | 'render': 'html', 118 | 'url': url, 119 | } 120 | 121 | response = requests.request( 122 | 'POST', 123 | 'https://realtime.oxylabs.io/v1/queries', 124 | auth=('username', 'password'), 125 | json=payload, 126 | ) 127 | 128 | response_json = response.json() 129 | 130 | html = response_json['results'][0]['content'] 131 | 132 | return html 133 | ``` 134 | 135 | Make sure to change up `USERNAME` and `PASSWORD` with your actual Oxylabs credentials. 136 | 137 | Next up, we’ll create a function that accepts a `BeautifulSoup` object created from the HTML of the whole page. This function will create and return an array of objects containing information from individual flight listings. Let’s try to form the function in such a way that makes it easily extendible if required: 138 | 139 | ```python 140 | def extract_flight_information_from_soup(soup_of_the_whole_page): 141 | flight_listings = soup_of_the_whole_page.find_all('li','pIav2d') 142 | 143 | flights = [] 144 | 145 | for listing in flight_listings: 146 | if listing is not None: 147 | # Add some specific data extraction here 148 | 149 | flight = {} 150 | 151 | flights.append(flight) 152 | 153 | return flights 154 | ``` 155 | 156 | Now that we can get the HTML and have a function to hold our information extraction, we can organize both of those into one: 157 | 158 | ```python 159 | def extract_flights_data_from_urls(urls): 160 | constructed_flight_results = [] 161 | 162 | for url in urls: 163 | html = get_flights_html(url) 164 | 165 | soup = BeautifulSoup(html,'html.parser') 166 | 167 | flights = extract_flight_information_from_soup(soup) 168 | 169 | constructed_flight_results.append({ 170 | 'url': url, 171 | 'flight_data': flights 172 | }) 173 | 174 | return constructed_flight_results 175 | ``` 176 | 177 | This function will take an array of URLs as a parameter and return an object of extracted flight data. 178 | 179 | One thing left for our core is a function that takes this data and saves it as a file: 180 | 181 | ```python 182 | def save_results(results, filepath): 183 | with open(filepath, 'w', encoding='utf-8') as file: 184 | json.dump(results, file, ensure_ascii=False, indent=4) 185 | 186 | return 187 | ``` 188 | 189 | We can finish by creating a simple `main` function to invoke all that we’ve created so far: 190 | ```python 191 | def main(): 192 | results_file = 'data.json' 193 | 194 | urls = [ 195 | 'https://www.google.com/travel/flights?tfs=CBsQAhooEgoyMDI0LTA3LTI4agwIAxIIL20vMDE1NnFyDAgCEggvbS8wNGpwbBooEgoyMDI0LTA4LTAxagwIAhIIL20vMDRqcGxyDAgDEggvbS8wMTU2cUABSAFSA0VVUnABemxDalJJTkRCNVRGbDBOMU5UVEdOQlJ6aG5lRUZDUnkwdExTMHRMUzB0TFMxM1pXc3lOMEZCUVVGQlIxZ3dhRWxSUVRoaWFtTkJFZ1pWTWpnMk1qSWFDZ2lRYnhBQ0dnTkZWVkk0SEhEN2VBPT2YAQGyARIYASABKgwIAxIIL20vMDRqcGw&hl=en-US&curr=EUR&sa=X&ved=0CAoQtY0DahgKEwiAz9bF5PaEAxUAAAAAHQAAAAAQngM', 196 | 'https://www.google.com/travel/flights/search?tfs=CBwQAhooEgoyMDI0LTA3LTI4agwIAxIIL20vMDE1NnFyDAgDEggvbS8wN19rcRooEgoyMDI0LTA4LTAxagwIAxIIL20vMDdfa3FyDAgDEggvbS8wMTU2cUABSAFwAYIBCwj___________8BmAEB&hl=en-US&curr=EUR' 197 | ] 198 | 199 | constructed_flight_results = extract_flights_data_from_urls(urls) 200 | 201 | save_results(constructed_flight_results, results_file) 202 | ``` 203 | 204 | ## Getting the price 205 | 206 | ```python 207 | def get_price(soup_element): 208 | price = soup_element.find('div','BVAVmf').find('div','YMlIz').get_text() 209 | 210 | return price 211 | ``` 212 | 213 | ## Getting the flight time 214 | 215 | ```python 216 | def get_time(soup_element): 217 | spans = soup_element.find('div','Ir0Voe').find('div','zxVSec', recursive=False).find_all('span', 'eoY5cb') 218 | 219 | time = "" 220 | 221 | for span in spans: 222 | time = time + span.get_text() + "; " 223 | 224 | return time 225 | ``` 226 | 227 | ## Getting the airline name 228 | 229 | ```python 230 | def get_airline(soup_element): 231 | airline = soup_element.find('div','Ir0Voe').find('div','sSHqwe') 232 | 233 | spans = airline.find_all('span', attrs={"class": None}, recursive=False) 234 | 235 | result = "" 236 | 237 | for span in spans: 238 | result = result + span.get_text() + "; " 239 | 240 | return result 241 | ``` 242 | 243 | Having all of these functions for data extraction, we just need to add them to the place we designated earlier to finish up our code. 244 | 245 | 246 | ```python 247 | def extract_flight_information_from_soup(soup_of_the_whole_page): 248 | flight_listings = soup_of_the_whole_page.find_all('li','pIav2d') 249 | 250 | flights = [] 251 | 252 | for listing in flight_listings: 253 | if listing is not None: 254 | price = get_price(listing) 255 | time = get_time(listing) 256 | airline = get_airline(listing) 257 | 258 | flight = { 259 | "airline": airline, 260 | "time": time, 261 | "price": price 262 | } 263 | 264 | flights.append(flight) 265 | 266 | return flights 267 | ``` 268 | ## Final result 269 | If we add all of it together, the final product should look something like this. 270 | 271 | 272 | ```python 273 | from bs4 import BeautifulSoup 274 | import requests 275 | import json 276 | 277 | def get_price(soup_element): 278 | price = soup_element.find('div','BVAVmf').find('div','YMlIz').get_text() 279 | 280 | return price 281 | 282 | 283 | def get_time(soup_element): 284 | spans = soup_element.find('div','Ir0Voe').find('div','zxVSec', recursive=False).find_all('span', 'eoY5cb') 285 | 286 | time = "" 287 | 288 | for span in spans: 289 | time = time + span.get_text() + "; " 290 | 291 | return time 292 | 293 | 294 | def get_airline(soup_element): 295 | airline = soup_element.find('div','Ir0Voe').find('div','sSHqwe') 296 | 297 | spans = airline.find_all('span', attrs={"class": None}, recursive=False) 298 | 299 | result = "" 300 | 301 | for span in spans: 302 | result = result + span.get_text() + "; " 303 | 304 | return result 305 | 306 | 307 | def save_results(results, filepath): 308 | with open(filepath, 'w', encoding='utf-8') as file: 309 | json.dump(results, file, ensure_ascii=False, indent=4) 310 | 311 | return 312 | 313 | 314 | def get_flights_html(url): 315 | payload = { 316 | 'source': 'google', 317 | 'render': 'html', 318 | 'url': url, 319 | } 320 | 321 | # Get response. 322 | response = requests.request( 323 | 'POST', 324 | 'https://realtime.oxylabs.io/v1/queries', 325 | auth=('username', 'password'), 326 | json=payload, 327 | ) 328 | 329 | response_json = response.json() 330 | 331 | html = response_json['results'][0]['content'] 332 | 333 | return html 334 | 335 | 336 | def extract_flight_information_from_soup(soup_of_the_whole_page): 337 | flight_listings = soup_of_the_whole_page.find_all('li','pIav2d') 338 | 339 | flights = [] 340 | 341 | for listing in flight_listings: 342 | if listing is not None: 343 | price = get_price(listing) 344 | time = get_time(listing) 345 | airline = get_airline(listing) 346 | 347 | flight = { 348 | "airline": airline, 349 | "time": time, 350 | "price": price 351 | } 352 | 353 | flights.append(flight) 354 | 355 | return flights 356 | 357 | 358 | def extract_flights_data_from_urls(urls): 359 | constructed_flight_results = [] 360 | 361 | for url in urls: 362 | html = get_flights_html(url) 363 | 364 | soup = BeautifulSoup(html,'html.parser') 365 | 366 | flights = extract_flight_information_from_soup(soup) 367 | 368 | constructed_flight_results.append({ 369 | 'url': url, 370 | 'flight_data': flights 371 | }) 372 | 373 | return constructed_flight_results 374 | 375 | 376 | def main(): 377 | results_file = 'data.json' 378 | 379 | urls = [ 380 | 'https://www.google.com/travel/flights?tfs=CBsQAhooEgoyMDI0LTA3LTI4agwIAxIIL20vMDE1NnFyDAgCEggvbS8wNGpwbBooEgoyMDI0LTA4LTAxagwIAhIIL20vMDRqcGxyDAgDEggvbS8wMTU2cUABSAFSA0VVUnABemxDalJJTkRCNVRGbDBOMU5UVEdOQlJ6aG5lRUZDUnkwdExTMHRMUzB0TFMxM1pXc3lOMEZCUVVGQlIxZ3dhRWxSUVRoaWFtTkJFZ1pWTWpnMk1qSWFDZ2lRYnhBQ0dnTkZWVkk0SEhEN2VBPT2YAQGyARIYASABKgwIAxIIL20vMDRqcGw&hl=en-US&curr=EUR&sa=X&ved=0CAoQtY0DahgKEwiAz9bF5PaEAxUAAAAAHQAAAAAQngM', 381 | 'https://www.google.com/travel/flights/search?tfs=CBwQAhooEgoyMDI0LTA3LTI4agwIAxIIL20vMDE1NnFyDAgDEggvbS8wN19rcRooEgoyMDI0LTA4LTAxagwIAxIIL20vMDdfa3FyDAgDEggvbS8wMTU2cUABSAFwAYIBCwj___________8BmAEB&hl=en-US&curr=EUR' 382 | ] 383 | 384 | constructed_flight_results = extract_flights_data_from_urls(urls) 385 | 386 | save_results(constructed_flight_results, results_file) 387 | 388 | 389 | if __name__ == "__main__": 390 | main() 391 | ``` 392 | 393 | By employing Python and Oxylabs Web Scraper API, you can easily deal with the dynamic nature of Google Flights and gather public data successfully. 394 | 395 | Read More Google Scraping Related Repositories: [Google Sheets for Basic Web Scraping](https://github.com/oxylabs/web-scraping-google-sheets), [How to Scrape Google Shopping Results](https://github.com/oxylabs/scrape-google-shopping), [Google Play Scraper](https://github.com/oxylabs/google-play-scraper), [How To Scrape Google Jobs](https://github.com/oxylabs/how-to-scrape-google-jobs), [Google News Scrpaer](https://github.com/oxylabs/google-news-scraper), [How to Scrape Google Scholar](https://github.com/oxylabs/how-to-scrape-google-scholar), [How To Scrape Google Images](https://github.com/oxylabs/how-to-scrape-google-images), [Scrape Google Search Results](https://github.com/oxylabs/scrape-google-python), [Scrape Google Trends](https://github.com/oxylabs/how-to-scrape-google-trends) 396 | 397 | -------------------------------------------------------------------------------- /poetry.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Poetry 1.6.1 and should not be changed by hand. 2 | 3 | [[package]] 4 | name = "annotated-types" 5 | version = "0.7.0" 6 | description = "Reusable constraint types to use with typing.Annotated" 7 | optional = false 8 | python-versions = ">=3.8" 9 | files = [ 10 | {file = "annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53"}, 11 | {file = "annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89"}, 12 | ] 13 | 14 | [[package]] 15 | name = "anyio" 16 | version = "4.4.0" 17 | description = "High level compatibility layer for multiple asynchronous event loop implementations" 18 | optional = false 19 | python-versions = ">=3.8" 20 | files = [ 21 | {file = "anyio-4.4.0-py3-none-any.whl", hash = "sha256:c1b2d8f46a8a812513012e1107cb0e68c17159a7a594208005a57dc776e1bdc7"}, 22 | {file = "anyio-4.4.0.tar.gz", hash = "sha256:5aadc6a1bbb7cdb0bede386cac5e2940f5e2ff3aa20277e991cf028e0585ce94"}, 23 | ] 24 | 25 | [package.dependencies] 26 | idna = ">=2.8" 27 | sniffio = ">=1.1" 28 | 29 | [package.extras] 30 | doc = ["Sphinx (>=7)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx-rtd-theme"] 31 | test = ["anyio[trio]", "coverage[toml] (>=7)", "exceptiongroup (>=1.2.0)", "hypothesis (>=4.0)", "psutil (>=5.9)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "uvloop (>=0.17)"] 32 | trio = ["trio (>=0.23)"] 33 | 34 | [[package]] 35 | name = "attrs" 36 | version = "24.2.0" 37 | description = "Classes Without Boilerplate" 38 | optional = false 39 | python-versions = ">=3.7" 40 | files = [ 41 | {file = "attrs-24.2.0-py3-none-any.whl", hash = "sha256:81921eb96de3191c8258c199618104dd27ac608d9366f5e35d011eae1867ede2"}, 42 | {file = "attrs-24.2.0.tar.gz", hash = "sha256:5cfb1b9148b5b086569baec03f20d7b6bf3bcacc9a42bebf87ffaaca362f6346"}, 43 | ] 44 | 45 | [package.extras] 46 | benchmark = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-codspeed", "pytest-mypy-plugins", "pytest-xdist[psutil]"] 47 | cov = ["cloudpickle", "coverage[toml] (>=5.3)", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] 48 | dev = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pre-commit", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] 49 | docs = ["cogapp", "furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier (<24.7)"] 50 | tests = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] 51 | tests-mypy = ["mypy (>=1.11.1)", "pytest-mypy-plugins"] 52 | 53 | [[package]] 54 | name = "beautifulsoup4" 55 | version = "4.12.3" 56 | description = "Screen-scraping library" 57 | optional = false 58 | python-versions = ">=3.6.0" 59 | files = [ 60 | {file = "beautifulsoup4-4.12.3-py3-none-any.whl", hash = "sha256:b80878c9f40111313e55da8ba20bdba06d8fa3969fc68304167741bbf9e082ed"}, 61 | {file = "beautifulsoup4-4.12.3.tar.gz", hash = "sha256:74e3d1928edc070d21748185c46e3fb33490f22f52a3addee9aee0f4f7781051"}, 62 | ] 63 | 64 | [package.dependencies] 65 | soupsieve = ">1.2" 66 | 67 | [package.extras] 68 | cchardet = ["cchardet"] 69 | chardet = ["chardet"] 70 | charset-normalizer = ["charset-normalizer"] 71 | html5lib = ["html5lib"] 72 | lxml = ["lxml"] 73 | 74 | [[package]] 75 | name = "bs4" 76 | version = "0.0.2" 77 | description = "Dummy package for Beautiful Soup (beautifulsoup4)" 78 | optional = false 79 | python-versions = "*" 80 | files = [ 81 | {file = "bs4-0.0.2-py2.py3-none-any.whl", hash = "sha256:abf8742c0805ef7f662dce4b51cca104cffe52b835238afc169142ab9b3fbccc"}, 82 | {file = "bs4-0.0.2.tar.gz", hash = "sha256:a48685c58f50fe127722417bae83fe6badf500d54b55f7e39ffe43b798653925"}, 83 | ] 84 | 85 | [package.dependencies] 86 | beautifulsoup4 = "*" 87 | 88 | [[package]] 89 | name = "certifi" 90 | version = "2024.7.4" 91 | description = "Python package for providing Mozilla's CA Bundle." 92 | optional = false 93 | python-versions = ">=3.6" 94 | files = [ 95 | {file = "certifi-2024.7.4-py3-none-any.whl", hash = "sha256:c198e21b1289c2ab85ee4e67bb4b4ef3ead0892059901a8d5b622f24a1101e90"}, 96 | {file = "certifi-2024.7.4.tar.gz", hash = "sha256:5a1e7645bc0ec61a09e26c36f6106dd4cf40c6db3a1fb6352b0244e7fb057c7b"}, 97 | ] 98 | 99 | [[package]] 100 | name = "cffi" 101 | version = "1.17.0" 102 | description = "Foreign Function Interface for Python calling C code." 103 | optional = false 104 | python-versions = ">=3.8" 105 | files = [ 106 | {file = "cffi-1.17.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f9338cc05451f1942d0d8203ec2c346c830f8e86469903d5126c1f0a13a2bcbb"}, 107 | {file = "cffi-1.17.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a0ce71725cacc9ebf839630772b07eeec220cbb5f03be1399e0457a1464f8e1a"}, 108 | {file = "cffi-1.17.0-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c815270206f983309915a6844fe994b2fa47e5d05c4c4cef267c3b30e34dbe42"}, 109 | {file = "cffi-1.17.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d6bdcd415ba87846fd317bee0774e412e8792832e7805938987e4ede1d13046d"}, 110 | {file = "cffi-1.17.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8a98748ed1a1df4ee1d6f927e151ed6c1a09d5ec21684de879c7ea6aa96f58f2"}, 111 | {file = "cffi-1.17.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0a048d4f6630113e54bb4b77e315e1ba32a5a31512c31a273807d0027a7e69ab"}, 112 | {file = "cffi-1.17.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:24aa705a5f5bd3a8bcfa4d123f03413de5d86e497435693b638cbffb7d5d8a1b"}, 113 | {file = "cffi-1.17.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:856bf0924d24e7f93b8aee12a3a1095c34085600aa805693fb7f5d1962393206"}, 114 | {file = "cffi-1.17.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:4304d4416ff032ed50ad6bb87416d802e67139e31c0bde4628f36a47a3164bfa"}, 115 | {file = "cffi-1.17.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:331ad15c39c9fe9186ceaf87203a9ecf5ae0ba2538c9e898e3a6967e8ad3db6f"}, 116 | {file = "cffi-1.17.0-cp310-cp310-win32.whl", hash = "sha256:669b29a9eca6146465cc574659058ed949748f0809a2582d1f1a324eb91054dc"}, 117 | {file = "cffi-1.17.0-cp310-cp310-win_amd64.whl", hash = "sha256:48b389b1fd5144603d61d752afd7167dfd205973a43151ae5045b35793232aa2"}, 118 | {file = "cffi-1.17.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c5d97162c196ce54af6700949ddf9409e9833ef1003b4741c2b39ef46f1d9720"}, 119 | {file = "cffi-1.17.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5ba5c243f4004c750836f81606a9fcb7841f8874ad8f3bf204ff5e56332b72b9"}, 120 | {file = "cffi-1.17.0-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bb9333f58fc3a2296fb1d54576138d4cf5d496a2cc118422bd77835e6ae0b9cb"}, 121 | {file = "cffi-1.17.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:435a22d00ec7d7ea533db494da8581b05977f9c37338c80bc86314bec2619424"}, 122 | {file = "cffi-1.17.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d1df34588123fcc88c872f5acb6f74ae59e9d182a2707097f9e28275ec26a12d"}, 123 | {file = "cffi-1.17.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:df8bb0010fdd0a743b7542589223a2816bdde4d94bb5ad67884348fa2c1c67e8"}, 124 | {file = "cffi-1.17.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a8b5b9712783415695663bd463990e2f00c6750562e6ad1d28e072a611c5f2a6"}, 125 | {file = "cffi-1.17.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ffef8fd58a36fb5f1196919638f73dd3ae0db1a878982b27a9a5a176ede4ba91"}, 126 | {file = "cffi-1.17.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:4e67d26532bfd8b7f7c05d5a766d6f437b362c1bf203a3a5ce3593a645e870b8"}, 127 | {file = "cffi-1.17.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:45f7cd36186db767d803b1473b3c659d57a23b5fa491ad83c6d40f2af58e4dbb"}, 128 | {file = "cffi-1.17.0-cp311-cp311-win32.whl", hash = "sha256:a9015f5b8af1bb6837a3fcb0cdf3b874fe3385ff6274e8b7925d81ccaec3c5c9"}, 129 | {file = "cffi-1.17.0-cp311-cp311-win_amd64.whl", hash = "sha256:b50aaac7d05c2c26dfd50c3321199f019ba76bb650e346a6ef3616306eed67b0"}, 130 | {file = "cffi-1.17.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:aec510255ce690d240f7cb23d7114f6b351c733a74c279a84def763660a2c3bc"}, 131 | {file = "cffi-1.17.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2770bb0d5e3cc0e31e7318db06efcbcdb7b31bcb1a70086d3177692a02256f59"}, 132 | {file = "cffi-1.17.0-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:db9a30ec064129d605d0f1aedc93e00894b9334ec74ba9c6bdd08147434b33eb"}, 133 | {file = "cffi-1.17.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a47eef975d2b8b721775a0fa286f50eab535b9d56c70a6e62842134cf7841195"}, 134 | {file = "cffi-1.17.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f3e0992f23bbb0be00a921eae5363329253c3b86287db27092461c887b791e5e"}, 135 | {file = "cffi-1.17.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6107e445faf057c118d5050560695e46d272e5301feffda3c41849641222a828"}, 136 | {file = "cffi-1.17.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eb862356ee9391dc5a0b3cbc00f416b48c1b9a52d252d898e5b7696a5f9fe150"}, 137 | {file = "cffi-1.17.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:c1c13185b90bbd3f8b5963cd8ce7ad4ff441924c31e23c975cb150e27c2bf67a"}, 138 | {file = "cffi-1.17.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:17c6d6d3260c7f2d94f657e6872591fe8733872a86ed1345bda872cfc8c74885"}, 139 | {file = "cffi-1.17.0-cp312-cp312-win32.whl", hash = "sha256:c3b8bd3133cd50f6b637bb4322822c94c5ce4bf0d724ed5ae70afce62187c492"}, 140 | {file = "cffi-1.17.0-cp312-cp312-win_amd64.whl", hash = "sha256:dca802c8db0720ce1c49cce1149ff7b06e91ba15fa84b1d59144fef1a1bc7ac2"}, 141 | {file = "cffi-1.17.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:6ce01337d23884b21c03869d2f68c5523d43174d4fc405490eb0091057943118"}, 142 | {file = "cffi-1.17.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:cab2eba3830bf4f6d91e2d6718e0e1c14a2f5ad1af68a89d24ace0c6b17cced7"}, 143 | {file = "cffi-1.17.0-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:14b9cbc8f7ac98a739558eb86fabc283d4d564dafed50216e7f7ee62d0d25377"}, 144 | {file = "cffi-1.17.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b00e7bcd71caa0282cbe3c90966f738e2db91e64092a877c3ff7f19a1628fdcb"}, 145 | {file = "cffi-1.17.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:41f4915e09218744d8bae14759f983e466ab69b178de38066f7579892ff2a555"}, 146 | {file = "cffi-1.17.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e4760a68cab57bfaa628938e9c2971137e05ce48e762a9cb53b76c9b569f1204"}, 147 | {file = "cffi-1.17.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:011aff3524d578a9412c8b3cfaa50f2c0bd78e03eb7af7aa5e0df59b158efb2f"}, 148 | {file = "cffi-1.17.0-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:a003ac9edc22d99ae1286b0875c460351f4e101f8c9d9d2576e78d7e048f64e0"}, 149 | {file = "cffi-1.17.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:ef9528915df81b8f4c7612b19b8628214c65c9b7f74db2e34a646a0a2a0da2d4"}, 150 | {file = "cffi-1.17.0-cp313-cp313-win32.whl", hash = "sha256:70d2aa9fb00cf52034feac4b913181a6e10356019b18ef89bc7c12a283bf5f5a"}, 151 | {file = "cffi-1.17.0-cp313-cp313-win_amd64.whl", hash = "sha256:b7b6ea9e36d32582cda3465f54c4b454f62f23cb083ebc7a94e2ca6ef011c3a7"}, 152 | {file = "cffi-1.17.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:964823b2fc77b55355999ade496c54dde161c621cb1f6eac61dc30ed1b63cd4c"}, 153 | {file = "cffi-1.17.0-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:516a405f174fd3b88829eabfe4bb296ac602d6a0f68e0d64d5ac9456194a5b7e"}, 154 | {file = "cffi-1.17.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dec6b307ce928e8e112a6bb9921a1cb00a0e14979bf28b98e084a4b8a742bd9b"}, 155 | {file = "cffi-1.17.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e4094c7b464cf0a858e75cd14b03509e84789abf7b79f8537e6a72152109c76e"}, 156 | {file = "cffi-1.17.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2404f3de742f47cb62d023f0ba7c5a916c9c653d5b368cc966382ae4e57da401"}, 157 | {file = "cffi-1.17.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3aa9d43b02a0c681f0bfbc12d476d47b2b2b6a3f9287f11ee42989a268a1833c"}, 158 | {file = "cffi-1.17.0-cp38-cp38-win32.whl", hash = "sha256:0bb15e7acf8ab35ca8b24b90af52c8b391690ef5c4aec3d31f38f0d37d2cc499"}, 159 | {file = "cffi-1.17.0-cp38-cp38-win_amd64.whl", hash = "sha256:93a7350f6706b31f457c1457d3a3259ff9071a66f312ae64dc024f049055f72c"}, 160 | {file = "cffi-1.17.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:1a2ddbac59dc3716bc79f27906c010406155031a1c801410f1bafff17ea304d2"}, 161 | {file = "cffi-1.17.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:6327b572f5770293fc062a7ec04160e89741e8552bf1c358d1a23eba68166759"}, 162 | {file = "cffi-1.17.0-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dbc183e7bef690c9abe5ea67b7b60fdbca81aa8da43468287dae7b5c046107d4"}, 163 | {file = "cffi-1.17.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5bdc0f1f610d067c70aa3737ed06e2726fd9d6f7bfee4a351f4c40b6831f4e82"}, 164 | {file = "cffi-1.17.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6d872186c1617d143969defeadac5a904e6e374183e07977eedef9c07c8953bf"}, 165 | {file = "cffi-1.17.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0d46ee4764b88b91f16661a8befc6bfb24806d885e27436fdc292ed7e6f6d058"}, 166 | {file = "cffi-1.17.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6f76a90c345796c01d85e6332e81cab6d70de83b829cf1d9762d0a3da59c7932"}, 167 | {file = "cffi-1.17.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0e60821d312f99d3e1569202518dddf10ae547e799d75aef3bca3a2d9e8ee693"}, 168 | {file = "cffi-1.17.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:eb09b82377233b902d4c3fbeeb7ad731cdab579c6c6fda1f763cd779139e47c3"}, 169 | {file = "cffi-1.17.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:24658baf6224d8f280e827f0a50c46ad819ec8ba380a42448e24459daf809cf4"}, 170 | {file = "cffi-1.17.0-cp39-cp39-win32.whl", hash = "sha256:0fdacad9e0d9fc23e519efd5ea24a70348305e8d7d85ecbb1a5fa66dc834e7fb"}, 171 | {file = "cffi-1.17.0-cp39-cp39-win_amd64.whl", hash = "sha256:7cbc78dc018596315d4e7841c8c3a7ae31cc4d638c9b627f87d52e8abaaf2d29"}, 172 | {file = "cffi-1.17.0.tar.gz", hash = "sha256:f3157624b7558b914cb039fd1af735e5e8049a87c817cc215109ad1c8779df76"}, 173 | ] 174 | 175 | [package.dependencies] 176 | pycparser = "*" 177 | 178 | [[package]] 179 | name = "charset-normalizer" 180 | version = "3.3.2" 181 | description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." 182 | optional = false 183 | python-versions = ">=3.7.0" 184 | files = [ 185 | {file = "charset-normalizer-3.3.2.tar.gz", hash = "sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5"}, 186 | {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:25baf083bf6f6b341f4121c2f3c548875ee6f5339300e08be3f2b2ba1721cdd3"}, 187 | {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:06435b539f889b1f6f4ac1758871aae42dc3a8c0e24ac9e60c2384973ad73027"}, 188 | {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9063e24fdb1e498ab71cb7419e24622516c4a04476b17a2dab57e8baa30d6e03"}, 189 | {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6897af51655e3691ff853668779c7bad41579facacf5fd7253b0133308cf000d"}, 190 | {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1d3193f4a680c64b4b6a9115943538edb896edc190f0b222e73761716519268e"}, 191 | {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd70574b12bb8a4d2aaa0094515df2463cb429d8536cfb6c7ce983246983e5a6"}, 192 | {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8465322196c8b4d7ab6d1e049e4c5cb460d0394da4a27d23cc242fbf0034b6b5"}, 193 | {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a9a8e9031d613fd2009c182b69c7b2c1ef8239a0efb1df3f7c8da66d5dd3d537"}, 194 | {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:beb58fe5cdb101e3a055192ac291b7a21e3b7ef4f67fa1d74e331a7f2124341c"}, 195 | {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e06ed3eb3218bc64786f7db41917d4e686cc4856944f53d5bdf83a6884432e12"}, 196 | {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:2e81c7b9c8979ce92ed306c249d46894776a909505d8f5a4ba55b14206e3222f"}, 197 | {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:572c3763a264ba47b3cf708a44ce965d98555f618ca42c926a9c1616d8f34269"}, 198 | {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519"}, 199 | {file = "charset_normalizer-3.3.2-cp310-cp310-win32.whl", hash = "sha256:3d47fa203a7bd9c5b6cee4736ee84ca03b8ef23193c0d1ca99b5089f72645c73"}, 200 | {file = "charset_normalizer-3.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:10955842570876604d404661fbccbc9c7e684caf432c09c715ec38fbae45ae09"}, 201 | {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:802fe99cca7457642125a8a88a084cef28ff0cf9407060f7b93dca5aa25480db"}, 202 | {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96"}, 203 | {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e"}, 204 | {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f"}, 205 | {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ceae2f17a9c33cb48e3263960dc5fc8005351ee19db217e9b1bb15d28c02574"}, 206 | {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:65f6f63034100ead094b8744b3b97965785388f308a64cf8d7c34f2f2e5be0c4"}, 207 | {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8"}, 208 | {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4a78b2b446bd7c934f5dcedc588903fb2f5eec172f3d29e52a9096a43722adfc"}, 209 | {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e537484df0d8f426ce2afb2d0f8e1c3d0b114b83f8850e5f2fbea0e797bd82ae"}, 210 | {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:eb6904c354526e758fda7167b33005998fb68c46fbc10e013ca97f21ca5c8887"}, 211 | {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:deb6be0ac38ece9ba87dea880e438f25ca3eddfac8b002a2ec3d9183a454e8ae"}, 212 | {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:4ab2fe47fae9e0f9dee8c04187ce5d09f48eabe611be8259444906793ab7cbce"}, 213 | {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:80402cd6ee291dcb72644d6eac93785fe2c8b9cb30893c1af5b8fdd753b9d40f"}, 214 | {file = "charset_normalizer-3.3.2-cp311-cp311-win32.whl", hash = "sha256:7cd13a2e3ddeed6913a65e66e94b51d80a041145a026c27e6bb76c31a853c6ab"}, 215 | {file = "charset_normalizer-3.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77"}, 216 | {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0b2b64d2bb6d3fb9112bafa732def486049e63de9618b5843bcdd081d8144cd8"}, 217 | {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b"}, 218 | {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6"}, 219 | {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8f4a014bc36d3c57402e2977dada34f9c12300af536839dc38c0beab8878f38a"}, 220 | {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a10af20b82360ab00827f916a6058451b723b4e65030c5a18577c8b2de5b3389"}, 221 | {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8d756e44e94489e49571086ef83b2bb8ce311e730092d2c34ca8f7d925cb20aa"}, 222 | {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:90d558489962fd4918143277a773316e56c72da56ec7aa3dc3dbbe20fdfed15b"}, 223 | {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6ac7ffc7ad6d040517be39eb591cac5ff87416c2537df6ba3cba3bae290c0fed"}, 224 | {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:7ed9e526742851e8d5cc9e6cf41427dfc6068d4f5a3bb03659444b4cabf6bc26"}, 225 | {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:8bdb58ff7ba23002a4c5808d608e4e6c687175724f54a5dade5fa8c67b604e4d"}, 226 | {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:6b3251890fff30ee142c44144871185dbe13b11bab478a88887a639655be1068"}, 227 | {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:b4a23f61ce87adf89be746c8a8974fe1c823c891d8f86eb218bb957c924bb143"}, 228 | {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:efcb3f6676480691518c177e3b465bcddf57cea040302f9f4e6e191af91174d4"}, 229 | {file = "charset_normalizer-3.3.2-cp312-cp312-win32.whl", hash = "sha256:d965bba47ddeec8cd560687584e88cf699fd28f192ceb452d1d7ee807c5597b7"}, 230 | {file = "charset_normalizer-3.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:96b02a3dc4381e5494fad39be677abcb5e6634bf7b4fa83a6dd3112607547001"}, 231 | {file = "charset_normalizer-3.3.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:95f2a5796329323b8f0512e09dbb7a1860c46a39da62ecb2324f116fa8fdc85c"}, 232 | {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c002b4ffc0be611f0d9da932eb0f704fe2602a9a949d1f738e4c34c75b0863d5"}, 233 | {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a981a536974bbc7a512cf44ed14938cf01030a99e9b3a06dd59578882f06f985"}, 234 | {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3287761bc4ee9e33561a7e058c72ac0938c4f57fe49a09eae428fd88aafe7bb6"}, 235 | {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:42cb296636fcc8b0644486d15c12376cb9fa75443e00fb25de0b8602e64c1714"}, 236 | {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0a55554a2fa0d408816b3b5cedf0045f4b8e1a6065aec45849de2d6f3f8e9786"}, 237 | {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:c083af607d2515612056a31f0a8d9e0fcb5876b7bfc0abad3ecd275bc4ebc2d5"}, 238 | {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:87d1351268731db79e0f8e745d92493ee2841c974128ef629dc518b937d9194c"}, 239 | {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:bd8f7df7d12c2db9fab40bdd87a7c09b1530128315d047a086fa3ae3435cb3a8"}, 240 | {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:c180f51afb394e165eafe4ac2936a14bee3eb10debc9d9e4db8958fe36afe711"}, 241 | {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:8c622a5fe39a48f78944a87d4fb8a53ee07344641b0562c540d840748571b811"}, 242 | {file = "charset_normalizer-3.3.2-cp37-cp37m-win32.whl", hash = "sha256:db364eca23f876da6f9e16c9da0df51aa4f104a972735574842618b8c6d999d4"}, 243 | {file = "charset_normalizer-3.3.2-cp37-cp37m-win_amd64.whl", hash = "sha256:86216b5cee4b06df986d214f664305142d9c76df9b6512be2738aa72a2048f99"}, 244 | {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:6463effa3186ea09411d50efc7d85360b38d5f09b870c48e4600f63af490e56a"}, 245 | {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6c4caeef8fa63d06bd437cd4bdcf3ffefe6738fb1b25951440d80dc7df8c03ac"}, 246 | {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:37e55c8e51c236f95b033f6fb391d7d7970ba5fe7ff453dad675e88cf303377a"}, 247 | {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb69256e180cb6c8a894fee62b3afebae785babc1ee98b81cdf68bbca1987f33"}, 248 | {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ae5f4161f18c61806f411a13b0310bea87f987c7d2ecdbdaad0e94eb2e404238"}, 249 | {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b2b0a0c0517616b6869869f8c581d4eb2dd83a4d79e0ebcb7d373ef9956aeb0a"}, 250 | {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:45485e01ff4d3630ec0d9617310448a8702f70e9c01906b0d0118bdf9d124cf2"}, 251 | {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eb00ed941194665c332bf8e078baf037d6c35d7c4f3102ea2d4f16ca94a26dc8"}, 252 | {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:2127566c664442652f024c837091890cb1942c30937add288223dc895793f898"}, 253 | {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a50aebfa173e157099939b17f18600f72f84eed3049e743b68ad15bd69b6bf99"}, 254 | {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:4d0d1650369165a14e14e1e47b372cfcb31d6ab44e6e33cb2d4e57265290044d"}, 255 | {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:923c0c831b7cfcb071580d3f46c4baf50f174be571576556269530f4bbd79d04"}, 256 | {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:06a81e93cd441c56a9b65d8e1d043daeb97a3d0856d177d5c90ba85acb3db087"}, 257 | {file = "charset_normalizer-3.3.2-cp38-cp38-win32.whl", hash = "sha256:6ef1d82a3af9d3eecdba2321dc1b3c238245d890843e040e41e470ffa64c3e25"}, 258 | {file = "charset_normalizer-3.3.2-cp38-cp38-win_amd64.whl", hash = "sha256:eb8821e09e916165e160797a6c17edda0679379a4be5c716c260e836e122f54b"}, 259 | {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c235ebd9baae02f1b77bcea61bce332cb4331dc3617d254df3323aa01ab47bd4"}, 260 | {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5b4c145409bef602a690e7cfad0a15a55c13320ff7a3ad7ca59c13bb8ba4d45d"}, 261 | {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:68d1f8a9e9e37c1223b656399be5d6b448dea850bed7d0f87a8311f1ff3dabb0"}, 262 | {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22afcb9f253dac0696b5a4be4a1c0f8762f8239e21b99680099abd9b2b1b2269"}, 263 | {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e27ad930a842b4c5eb8ac0016b0a54f5aebbe679340c26101df33424142c143c"}, 264 | {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1f79682fbe303db92bc2b1136016a38a42e835d932bab5b3b1bfcfbf0640e519"}, 265 | {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b261ccdec7821281dade748d088bb6e9b69e6d15b30652b74cbbac25e280b796"}, 266 | {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:122c7fa62b130ed55f8f285bfd56d5f4b4a5b503609d181f9ad85e55c89f4185"}, 267 | {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d0eccceffcb53201b5bfebb52600a5fb483a20b61da9dbc885f8b103cbe7598c"}, 268 | {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9f96df6923e21816da7e0ad3fd47dd8f94b2a5ce594e00677c0013018b813458"}, 269 | {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:7f04c839ed0b6b98b1a7501a002144b76c18fb1c1850c8b98d458ac269e26ed2"}, 270 | {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:34d1c8da1e78d2e001f363791c98a272bb734000fcef47a491c1e3b0505657a8"}, 271 | {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561"}, 272 | {file = "charset_normalizer-3.3.2-cp39-cp39-win32.whl", hash = "sha256:aed38f6e4fb3f5d6bf81bfa990a07806be9d83cf7bacef998ab1a9bd660a581f"}, 273 | {file = "charset_normalizer-3.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:b01b88d45a6fcb69667cd6d2f7a9aeb4bf53760d7fc536bf679ec94fe9f3ff3d"}, 274 | {file = "charset_normalizer-3.3.2-py3-none-any.whl", hash = "sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc"}, 275 | ] 276 | 277 | [[package]] 278 | name = "click" 279 | version = "8.1.7" 280 | description = "Composable command line interface toolkit" 281 | optional = false 282 | python-versions = ">=3.7" 283 | files = [ 284 | {file = "click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28"}, 285 | {file = "click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"}, 286 | ] 287 | 288 | [package.dependencies] 289 | colorama = {version = "*", markers = "platform_system == \"Windows\""} 290 | 291 | [[package]] 292 | name = "colorama" 293 | version = "0.4.6" 294 | description = "Cross-platform colored terminal text." 295 | optional = false 296 | python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" 297 | files = [ 298 | {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, 299 | {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, 300 | ] 301 | 302 | [[package]] 303 | name = "h11" 304 | version = "0.14.0" 305 | description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" 306 | optional = false 307 | python-versions = ">=3.7" 308 | files = [ 309 | {file = "h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761"}, 310 | {file = "h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d"}, 311 | ] 312 | 313 | [[package]] 314 | name = "httpcore" 315 | version = "1.0.5" 316 | description = "A minimal low-level HTTP client." 317 | optional = false 318 | python-versions = ">=3.8" 319 | files = [ 320 | {file = "httpcore-1.0.5-py3-none-any.whl", hash = "sha256:421f18bac248b25d310f3cacd198d55b8e6125c107797b609ff9b7a6ba7991b5"}, 321 | {file = "httpcore-1.0.5.tar.gz", hash = "sha256:34a38e2f9291467ee3b44e89dd52615370e152954ba21721378a87b2960f7a61"}, 322 | ] 323 | 324 | [package.dependencies] 325 | certifi = "*" 326 | h11 = ">=0.13,<0.15" 327 | 328 | [package.extras] 329 | asyncio = ["anyio (>=4.0,<5.0)"] 330 | http2 = ["h2 (>=3,<5)"] 331 | socks = ["socksio (==1.*)"] 332 | trio = ["trio (>=0.22.0,<0.26.0)"] 333 | 334 | [[package]] 335 | name = "httpx" 336 | version = "0.27.0" 337 | description = "The next generation HTTP client." 338 | optional = false 339 | python-versions = ">=3.8" 340 | files = [ 341 | {file = "httpx-0.27.0-py3-none-any.whl", hash = "sha256:71d5465162c13681bff01ad59b2cc68dd838ea1f10e51574bac27103f00c91a5"}, 342 | {file = "httpx-0.27.0.tar.gz", hash = "sha256:a0cb88a46f32dc874e04ee956e4c2764aba2aa228f650b06788ba6bda2962ab5"}, 343 | ] 344 | 345 | [package.dependencies] 346 | anyio = "*" 347 | certifi = "*" 348 | httpcore = "==1.*" 349 | idna = "*" 350 | sniffio = "*" 351 | 352 | [package.extras] 353 | brotli = ["brotli", "brotlicffi"] 354 | cli = ["click (==8.*)", "pygments (==2.*)", "rich (>=10,<14)"] 355 | http2 = ["h2 (>=3,<5)"] 356 | socks = ["socksio (==1.*)"] 357 | 358 | [[package]] 359 | name = "idna" 360 | version = "3.7" 361 | description = "Internationalized Domain Names in Applications (IDNA)" 362 | optional = false 363 | python-versions = ">=3.5" 364 | files = [ 365 | {file = "idna-3.7-py3-none-any.whl", hash = "sha256:82fee1fc78add43492d3a1898bfa6d8a904cc97d8427f683ed8e798d07761aa0"}, 366 | {file = "idna-3.7.tar.gz", hash = "sha256:028ff3aadf0609c1fd278d8ea3089299412a7a8b9bd005dd08b9f8285bcb5cfc"}, 367 | ] 368 | 369 | [[package]] 370 | name = "numpy" 371 | version = "2.0.1" 372 | description = "Fundamental package for array computing in Python" 373 | optional = false 374 | python-versions = ">=3.9" 375 | files = [ 376 | {file = "numpy-2.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0fbb536eac80e27a2793ffd787895242b7f18ef792563d742c2d673bfcb75134"}, 377 | {file = "numpy-2.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:69ff563d43c69b1baba77af455dd0a839df8d25e8590e79c90fcbe1499ebde42"}, 378 | {file = "numpy-2.0.1-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:1b902ce0e0a5bb7704556a217c4f63a7974f8f43e090aff03fcf262e0b135e02"}, 379 | {file = "numpy-2.0.1-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:f1659887361a7151f89e79b276ed8dff3d75877df906328f14d8bb40bb4f5101"}, 380 | {file = "numpy-2.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4658c398d65d1b25e1760de3157011a80375da861709abd7cef3bad65d6543f9"}, 381 | {file = "numpy-2.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4127d4303b9ac9f94ca0441138acead39928938660ca58329fe156f84b9f3015"}, 382 | {file = "numpy-2.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:e5eeca8067ad04bc8a2a8731183d51d7cbaac66d86085d5f4766ee6bf19c7f87"}, 383 | {file = "numpy-2.0.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:9adbd9bb520c866e1bfd7e10e1880a1f7749f1f6e5017686a5fbb9b72cf69f82"}, 384 | {file = "numpy-2.0.1-cp310-cp310-win32.whl", hash = "sha256:7b9853803278db3bdcc6cd5beca37815b133e9e77ff3d4733c247414e78eb8d1"}, 385 | {file = "numpy-2.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:81b0893a39bc5b865b8bf89e9ad7807e16717f19868e9d234bdaf9b1f1393868"}, 386 | {file = "numpy-2.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:75b4e316c5902d8163ef9d423b1c3f2f6252226d1aa5cd8a0a03a7d01ffc6268"}, 387 | {file = "numpy-2.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:6e4eeb6eb2fced786e32e6d8df9e755ce5be920d17f7ce00bc38fcde8ccdbf9e"}, 388 | {file = "numpy-2.0.1-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:a1e01dcaab205fbece13c1410253a9eea1b1c9b61d237b6fa59bcc46e8e89343"}, 389 | {file = "numpy-2.0.1-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:a8fc2de81ad835d999113ddf87d1ea2b0f4704cbd947c948d2f5513deafe5a7b"}, 390 | {file = "numpy-2.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5a3d94942c331dd4e0e1147f7a8699a4aa47dffc11bf8a1523c12af8b2e91bbe"}, 391 | {file = "numpy-2.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:15eb4eca47d36ec3f78cde0a3a2ee24cf05ca7396ef808dda2c0ddad7c2bde67"}, 392 | {file = "numpy-2.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:b83e16a5511d1b1f8a88cbabb1a6f6a499f82c062a4251892d9ad5d609863fb7"}, 393 | {file = "numpy-2.0.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1f87fec1f9bc1efd23f4227becff04bd0e979e23ca50cc92ec88b38489db3b55"}, 394 | {file = "numpy-2.0.1-cp311-cp311-win32.whl", hash = "sha256:36d3a9405fd7c511804dc56fc32974fa5533bdeb3cd1604d6b8ff1d292b819c4"}, 395 | {file = "numpy-2.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:08458fbf403bff5e2b45f08eda195d4b0c9b35682311da5a5a0a0925b11b9bd8"}, 396 | {file = "numpy-2.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:6bf4e6f4a2a2e26655717a1983ef6324f2664d7011f6ef7482e8c0b3d51e82ac"}, 397 | {file = "numpy-2.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7d6fddc5fe258d3328cd8e3d7d3e02234c5d70e01ebe377a6ab92adb14039cb4"}, 398 | {file = "numpy-2.0.1-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:5daab361be6ddeb299a918a7c0864fa8618af66019138263247af405018b04e1"}, 399 | {file = "numpy-2.0.1-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:ea2326a4dca88e4a274ba3a4405eb6c6467d3ffbd8c7d38632502eaae3820587"}, 400 | {file = "numpy-2.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:529af13c5f4b7a932fb0e1911d3a75da204eff023ee5e0e79c1751564221a5c8"}, 401 | {file = "numpy-2.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6790654cb13eab303d8402354fabd47472b24635700f631f041bd0b65e37298a"}, 402 | {file = "numpy-2.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:cbab9fc9c391700e3e1287666dfd82d8666d10e69a6c4a09ab97574c0b7ee0a7"}, 403 | {file = "numpy-2.0.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:99d0d92a5e3613c33a5f01db206a33f8fdf3d71f2912b0de1739894668b7a93b"}, 404 | {file = "numpy-2.0.1-cp312-cp312-win32.whl", hash = "sha256:173a00b9995f73b79eb0191129f2455f1e34c203f559dd118636858cc452a1bf"}, 405 | {file = "numpy-2.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:bb2124fdc6e62baae159ebcfa368708867eb56806804d005860b6007388df171"}, 406 | {file = "numpy-2.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:bfc085b28d62ff4009364e7ca34b80a9a080cbd97c2c0630bb5f7f770dae9414"}, 407 | {file = "numpy-2.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8fae4ebbf95a179c1156fab0b142b74e4ba4204c87bde8d3d8b6f9c34c5825ef"}, 408 | {file = "numpy-2.0.1-cp39-cp39-macosx_14_0_arm64.whl", hash = "sha256:72dc22e9ec8f6eaa206deb1b1355eb2e253899d7347f5e2fae5f0af613741d06"}, 409 | {file = "numpy-2.0.1-cp39-cp39-macosx_14_0_x86_64.whl", hash = "sha256:ec87f5f8aca726117a1c9b7083e7656a9d0d606eec7299cc067bb83d26f16e0c"}, 410 | {file = "numpy-2.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f682ea61a88479d9498bf2091fdcd722b090724b08b31d63e022adc063bad59"}, 411 | {file = "numpy-2.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8efc84f01c1cd7e34b3fb310183e72fcdf55293ee736d679b6d35b35d80bba26"}, 412 | {file = "numpy-2.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:3fdabe3e2a52bc4eff8dc7a5044342f8bd9f11ef0934fcd3289a788c0eb10018"}, 413 | {file = "numpy-2.0.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:24a0e1befbfa14615b49ba9659d3d8818a0f4d8a1c5822af8696706fbda7310c"}, 414 | {file = "numpy-2.0.1-cp39-cp39-win32.whl", hash = "sha256:f9cf5ea551aec449206954b075db819f52adc1638d46a6738253a712d553c7b4"}, 415 | {file = "numpy-2.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:e9e81fa9017eaa416c056e5d9e71be93d05e2c3c2ab308d23307a8bc4443c368"}, 416 | {file = "numpy-2.0.1-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:61728fba1e464f789b11deb78a57805c70b2ed02343560456190d0501ba37b0f"}, 417 | {file = "numpy-2.0.1-pp39-pypy39_pp73-macosx_14_0_x86_64.whl", hash = "sha256:12f5d865d60fb9734e60a60f1d5afa6d962d8d4467c120a1c0cda6eb2964437d"}, 418 | {file = "numpy-2.0.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eacf3291e263d5a67d8c1a581a8ebbcfd6447204ef58828caf69a5e3e8c75990"}, 419 | {file = "numpy-2.0.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:2c3a346ae20cfd80b6cfd3e60dc179963ef2ea58da5ec074fd3d9e7a1e7ba97f"}, 420 | {file = "numpy-2.0.1.tar.gz", hash = "sha256:485b87235796410c3519a699cfe1faab097e509e90ebb05dcd098db2ae87e7b3"}, 421 | ] 422 | 423 | [[package]] 424 | name = "outcome" 425 | version = "1.3.0.post0" 426 | description = "Capture the outcome of Python function calls." 427 | optional = false 428 | python-versions = ">=3.7" 429 | files = [ 430 | {file = "outcome-1.3.0.post0-py2.py3-none-any.whl", hash = "sha256:e771c5ce06d1415e356078d3bdd68523f284b4ce5419828922b6871e65eda82b"}, 431 | {file = "outcome-1.3.0.post0.tar.gz", hash = "sha256:9dcf02e65f2971b80047b377468e72a268e15c0af3cf1238e6ff14f7f91143b8"}, 432 | ] 433 | 434 | [package.dependencies] 435 | attrs = ">=19.2.0" 436 | 437 | [[package]] 438 | name = "packaging" 439 | version = "24.1" 440 | description = "Core utilities for Python packages" 441 | optional = false 442 | python-versions = ">=3.8" 443 | files = [ 444 | {file = "packaging-24.1-py3-none-any.whl", hash = "sha256:5b8f2217dbdbd2f7f384c41c628544e6d52f2d0f53c6d0c3ea61aa5d1d7ff124"}, 445 | {file = "packaging-24.1.tar.gz", hash = "sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002"}, 446 | ] 447 | 448 | [[package]] 449 | name = "pandas" 450 | version = "2.2.2" 451 | description = "Powerful data structures for data analysis, time series, and statistics" 452 | optional = false 453 | python-versions = ">=3.9" 454 | files = [ 455 | {file = "pandas-2.2.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:90c6fca2acf139569e74e8781709dccb6fe25940488755716d1d354d6bc58bce"}, 456 | {file = "pandas-2.2.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c7adfc142dac335d8c1e0dcbd37eb8617eac386596eb9e1a1b77791cf2498238"}, 457 | {file = "pandas-2.2.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4abfe0be0d7221be4f12552995e58723c7422c80a659da13ca382697de830c08"}, 458 | {file = "pandas-2.2.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8635c16bf3d99040fdf3ca3db669a7250ddf49c55dc4aa8fe0ae0fa8d6dcc1f0"}, 459 | {file = "pandas-2.2.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:40ae1dffb3967a52203105a077415a86044a2bea011b5f321c6aa64b379a3f51"}, 460 | {file = "pandas-2.2.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:8e5a0b00e1e56a842f922e7fae8ae4077aee4af0acb5ae3622bd4b4c30aedf99"}, 461 | {file = "pandas-2.2.2-cp310-cp310-win_amd64.whl", hash = "sha256:ddf818e4e6c7c6f4f7c8a12709696d193976b591cc7dc50588d3d1a6b5dc8772"}, 462 | {file = "pandas-2.2.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:696039430f7a562b74fa45f540aca068ea85fa34c244d0deee539cb6d70aa288"}, 463 | {file = "pandas-2.2.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8e90497254aacacbc4ea6ae5e7a8cd75629d6ad2b30025a4a8b09aa4faf55151"}, 464 | {file = "pandas-2.2.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:58b84b91b0b9f4bafac2a0ac55002280c094dfc6402402332c0913a59654ab2b"}, 465 | {file = "pandas-2.2.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6d2123dc9ad6a814bcdea0f099885276b31b24f7edf40f6cdbc0912672e22eee"}, 466 | {file = "pandas-2.2.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:2925720037f06e89af896c70bca73459d7e6a4be96f9de79e2d440bd499fe0db"}, 467 | {file = "pandas-2.2.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:0cace394b6ea70c01ca1595f839cf193df35d1575986e484ad35c4aeae7266c1"}, 468 | {file = "pandas-2.2.2-cp311-cp311-win_amd64.whl", hash = "sha256:873d13d177501a28b2756375d59816c365e42ed8417b41665f346289adc68d24"}, 469 | {file = "pandas-2.2.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:9dfde2a0ddef507a631dc9dc4af6a9489d5e2e740e226ad426a05cabfbd7c8ef"}, 470 | {file = "pandas-2.2.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:e9b79011ff7a0f4b1d6da6a61aa1aa604fb312d6647de5bad20013682d1429ce"}, 471 | {file = "pandas-2.2.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1cb51fe389360f3b5a4d57dbd2848a5f033350336ca3b340d1c53a1fad33bcad"}, 472 | {file = "pandas-2.2.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eee3a87076c0756de40b05c5e9a6069c035ba43e8dd71c379e68cab2c20f16ad"}, 473 | {file = "pandas-2.2.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:3e374f59e440d4ab45ca2fffde54b81ac3834cf5ae2cdfa69c90bc03bde04d76"}, 474 | {file = "pandas-2.2.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:43498c0bdb43d55cb162cdc8c06fac328ccb5d2eabe3cadeb3529ae6f0517c32"}, 475 | {file = "pandas-2.2.2-cp312-cp312-win_amd64.whl", hash = "sha256:d187d355ecec3629624fccb01d104da7d7f391db0311145817525281e2804d23"}, 476 | {file = "pandas-2.2.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:0ca6377b8fca51815f382bd0b697a0814c8bda55115678cbc94c30aacbb6eff2"}, 477 | {file = "pandas-2.2.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9057e6aa78a584bc93a13f0a9bf7e753a5e9770a30b4d758b8d5f2a62a9433cd"}, 478 | {file = "pandas-2.2.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:001910ad31abc7bf06f49dcc903755d2f7f3a9186c0c040b827e522e9cef0863"}, 479 | {file = "pandas-2.2.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:66b479b0bd07204e37583c191535505410daa8df638fd8e75ae1b383851fe921"}, 480 | {file = "pandas-2.2.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:a77e9d1c386196879aa5eb712e77461aaee433e54c68cf253053a73b7e49c33a"}, 481 | {file = "pandas-2.2.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:92fd6b027924a7e178ac202cfbe25e53368db90d56872d20ffae94b96c7acc57"}, 482 | {file = "pandas-2.2.2-cp39-cp39-win_amd64.whl", hash = "sha256:640cef9aa381b60e296db324337a554aeeb883ead99dc8f6c18e81a93942f5f4"}, 483 | {file = "pandas-2.2.2.tar.gz", hash = "sha256:9e79019aba43cb4fda9e4d983f8e88ca0373adbb697ae9c6c43093218de28b54"}, 484 | ] 485 | 486 | [package.dependencies] 487 | numpy = [ 488 | {version = ">=1.23.2", markers = "python_version == \"3.11\""}, 489 | {version = ">=1.26.0", markers = "python_version >= \"3.12\""}, 490 | ] 491 | python-dateutil = ">=2.8.2" 492 | pytz = ">=2020.1" 493 | tzdata = ">=2022.7" 494 | 495 | [package.extras] 496 | all = ["PyQt5 (>=5.15.9)", "SQLAlchemy (>=2.0.0)", "adbc-driver-postgresql (>=0.8.0)", "adbc-driver-sqlite (>=0.8.0)", "beautifulsoup4 (>=4.11.2)", "bottleneck (>=1.3.6)", "dataframe-api-compat (>=0.1.7)", "fastparquet (>=2022.12.0)", "fsspec (>=2022.11.0)", "gcsfs (>=2022.11.0)", "html5lib (>=1.1)", "hypothesis (>=6.46.1)", "jinja2 (>=3.1.2)", "lxml (>=4.9.2)", "matplotlib (>=3.6.3)", "numba (>=0.56.4)", "numexpr (>=2.8.4)", "odfpy (>=1.4.1)", "openpyxl (>=3.1.0)", "pandas-gbq (>=0.19.0)", "psycopg2 (>=2.9.6)", "pyarrow (>=10.0.1)", "pymysql (>=1.0.2)", "pyreadstat (>=1.2.0)", "pytest (>=7.3.2)", "pytest-xdist (>=2.2.0)", "python-calamine (>=0.1.7)", "pyxlsb (>=1.0.10)", "qtpy (>=2.3.0)", "s3fs (>=2022.11.0)", "scipy (>=1.10.0)", "tables (>=3.8.0)", "tabulate (>=0.9.0)", "xarray (>=2022.12.0)", "xlrd (>=2.0.1)", "xlsxwriter (>=3.0.5)", "zstandard (>=0.19.0)"] 497 | aws = ["s3fs (>=2022.11.0)"] 498 | clipboard = ["PyQt5 (>=5.15.9)", "qtpy (>=2.3.0)"] 499 | compression = ["zstandard (>=0.19.0)"] 500 | computation = ["scipy (>=1.10.0)", "xarray (>=2022.12.0)"] 501 | consortium-standard = ["dataframe-api-compat (>=0.1.7)"] 502 | excel = ["odfpy (>=1.4.1)", "openpyxl (>=3.1.0)", "python-calamine (>=0.1.7)", "pyxlsb (>=1.0.10)", "xlrd (>=2.0.1)", "xlsxwriter (>=3.0.5)"] 503 | feather = ["pyarrow (>=10.0.1)"] 504 | fss = ["fsspec (>=2022.11.0)"] 505 | gcp = ["gcsfs (>=2022.11.0)", "pandas-gbq (>=0.19.0)"] 506 | hdf5 = ["tables (>=3.8.0)"] 507 | html = ["beautifulsoup4 (>=4.11.2)", "html5lib (>=1.1)", "lxml (>=4.9.2)"] 508 | mysql = ["SQLAlchemy (>=2.0.0)", "pymysql (>=1.0.2)"] 509 | output-formatting = ["jinja2 (>=3.1.2)", "tabulate (>=0.9.0)"] 510 | parquet = ["pyarrow (>=10.0.1)"] 511 | performance = ["bottleneck (>=1.3.6)", "numba (>=0.56.4)", "numexpr (>=2.8.4)"] 512 | plot = ["matplotlib (>=3.6.3)"] 513 | postgresql = ["SQLAlchemy (>=2.0.0)", "adbc-driver-postgresql (>=0.8.0)", "psycopg2 (>=2.9.6)"] 514 | pyarrow = ["pyarrow (>=10.0.1)"] 515 | spss = ["pyreadstat (>=1.2.0)"] 516 | sql-other = ["SQLAlchemy (>=2.0.0)", "adbc-driver-postgresql (>=0.8.0)", "adbc-driver-sqlite (>=0.8.0)"] 517 | test = ["hypothesis (>=6.46.1)", "pytest (>=7.3.2)", "pytest-xdist (>=2.2.0)"] 518 | xml = ["lxml (>=4.9.2)"] 519 | 520 | [[package]] 521 | name = "pycparser" 522 | version = "2.22" 523 | description = "C parser in Python" 524 | optional = false 525 | python-versions = ">=3.8" 526 | files = [ 527 | {file = "pycparser-2.22-py3-none-any.whl", hash = "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc"}, 528 | {file = "pycparser-2.22.tar.gz", hash = "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6"}, 529 | ] 530 | 531 | [[package]] 532 | name = "pydantic" 533 | version = "2.8.2" 534 | description = "Data validation using Python type hints" 535 | optional = false 536 | python-versions = ">=3.8" 537 | files = [ 538 | {file = "pydantic-2.8.2-py3-none-any.whl", hash = "sha256:73ee9fddd406dc318b885c7a2eab8a6472b68b8fb5ba8150949fc3db939f23c8"}, 539 | {file = "pydantic-2.8.2.tar.gz", hash = "sha256:6f62c13d067b0755ad1c21a34bdd06c0c12625a22b0fc09c6b149816604f7c2a"}, 540 | ] 541 | 542 | [package.dependencies] 543 | annotated-types = ">=0.4.0" 544 | pydantic-core = "2.20.1" 545 | typing-extensions = [ 546 | {version = ">=4.6.1", markers = "python_version < \"3.13\""}, 547 | {version = ">=4.12.2", markers = "python_version >= \"3.13\""}, 548 | ] 549 | 550 | [package.extras] 551 | email = ["email-validator (>=2.0.0)"] 552 | 553 | [[package]] 554 | name = "pydantic-core" 555 | version = "2.20.1" 556 | description = "Core functionality for Pydantic validation and serialization" 557 | optional = false 558 | python-versions = ">=3.8" 559 | files = [ 560 | {file = "pydantic_core-2.20.1-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:3acae97ffd19bf091c72df4d726d552c473f3576409b2a7ca36b2f535ffff4a3"}, 561 | {file = "pydantic_core-2.20.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:41f4c96227a67a013e7de5ff8f20fb496ce573893b7f4f2707d065907bffdbd6"}, 562 | {file = "pydantic_core-2.20.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5f239eb799a2081495ea659d8d4a43a8f42cd1fe9ff2e7e436295c38a10c286a"}, 563 | {file = "pydantic_core-2.20.1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:53e431da3fc53360db73eedf6f7124d1076e1b4ee4276b36fb25514544ceb4a3"}, 564 | {file = "pydantic_core-2.20.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f1f62b2413c3a0e846c3b838b2ecd6c7a19ec6793b2a522745b0869e37ab5bc1"}, 565 | {file = "pydantic_core-2.20.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5d41e6daee2813ecceea8eda38062d69e280b39df793f5a942fa515b8ed67953"}, 566 | {file = "pydantic_core-2.20.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3d482efec8b7dc6bfaedc0f166b2ce349df0011f5d2f1f25537ced4cfc34fd98"}, 567 | {file = "pydantic_core-2.20.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e93e1a4b4b33daed65d781a57a522ff153dcf748dee70b40c7258c5861e1768a"}, 568 | {file = "pydantic_core-2.20.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:e7c4ea22b6739b162c9ecaaa41d718dfad48a244909fe7ef4b54c0b530effc5a"}, 569 | {file = "pydantic_core-2.20.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:4f2790949cf385d985a31984907fecb3896999329103df4e4983a4a41e13e840"}, 570 | {file = "pydantic_core-2.20.1-cp310-none-win32.whl", hash = "sha256:5e999ba8dd90e93d57410c5e67ebb67ffcaadcea0ad973240fdfd3a135506250"}, 571 | {file = "pydantic_core-2.20.1-cp310-none-win_amd64.whl", hash = "sha256:512ecfbefef6dac7bc5eaaf46177b2de58cdf7acac8793fe033b24ece0b9566c"}, 572 | {file = "pydantic_core-2.20.1-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:d2a8fa9d6d6f891f3deec72f5cc668e6f66b188ab14bb1ab52422fe8e644f312"}, 573 | {file = "pydantic_core-2.20.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:175873691124f3d0da55aeea1d90660a6ea7a3cfea137c38afa0a5ffabe37b88"}, 574 | {file = "pydantic_core-2.20.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:37eee5b638f0e0dcd18d21f59b679686bbd18917b87db0193ae36f9c23c355fc"}, 575 | {file = "pydantic_core-2.20.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:25e9185e2d06c16ee438ed39bf62935ec436474a6ac4f9358524220f1b236e43"}, 576 | {file = "pydantic_core-2.20.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:150906b40ff188a3260cbee25380e7494ee85048584998c1e66df0c7a11c17a6"}, 577 | {file = "pydantic_core-2.20.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8ad4aeb3e9a97286573c03df758fc7627aecdd02f1da04516a86dc159bf70121"}, 578 | {file = "pydantic_core-2.20.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d3f3ed29cd9f978c604708511a1f9c2fdcb6c38b9aae36a51905b8811ee5cbf1"}, 579 | {file = "pydantic_core-2.20.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b0dae11d8f5ded51699c74d9548dcc5938e0804cc8298ec0aa0da95c21fff57b"}, 580 | {file = "pydantic_core-2.20.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:faa6b09ee09433b87992fb5a2859efd1c264ddc37280d2dd5db502126d0e7f27"}, 581 | {file = "pydantic_core-2.20.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:9dc1b507c12eb0481d071f3c1808f0529ad41dc415d0ca11f7ebfc666e66a18b"}, 582 | {file = "pydantic_core-2.20.1-cp311-none-win32.whl", hash = "sha256:fa2fddcb7107e0d1808086ca306dcade7df60a13a6c347a7acf1ec139aa6789a"}, 583 | {file = "pydantic_core-2.20.1-cp311-none-win_amd64.whl", hash = "sha256:40a783fb7ee353c50bd3853e626f15677ea527ae556429453685ae32280c19c2"}, 584 | {file = "pydantic_core-2.20.1-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:595ba5be69b35777474fa07f80fc260ea71255656191adb22a8c53aba4479231"}, 585 | {file = "pydantic_core-2.20.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a4f55095ad087474999ee28d3398bae183a66be4823f753cd7d67dd0153427c9"}, 586 | {file = "pydantic_core-2.20.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f9aa05d09ecf4c75157197f27cdc9cfaeb7c5f15021c6373932bf3e124af029f"}, 587 | {file = "pydantic_core-2.20.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e97fdf088d4b31ff4ba35db26d9cc472ac7ef4a2ff2badeabf8d727b3377fc52"}, 588 | {file = "pydantic_core-2.20.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bc633a9fe1eb87e250b5c57d389cf28998e4292336926b0b6cdaee353f89a237"}, 589 | {file = "pydantic_core-2.20.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d573faf8eb7e6b1cbbcb4f5b247c60ca8be39fe2c674495df0eb4318303137fe"}, 590 | {file = "pydantic_core-2.20.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:26dc97754b57d2fd00ac2b24dfa341abffc380b823211994c4efac7f13b9e90e"}, 591 | {file = "pydantic_core-2.20.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:33499e85e739a4b60c9dac710c20a08dc73cb3240c9a0e22325e671b27b70d24"}, 592 | {file = "pydantic_core-2.20.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:bebb4d6715c814597f85297c332297c6ce81e29436125ca59d1159b07f423eb1"}, 593 | {file = "pydantic_core-2.20.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:516d9227919612425c8ef1c9b869bbbee249bc91912c8aaffb66116c0b447ebd"}, 594 | {file = "pydantic_core-2.20.1-cp312-none-win32.whl", hash = "sha256:469f29f9093c9d834432034d33f5fe45699e664f12a13bf38c04967ce233d688"}, 595 | {file = "pydantic_core-2.20.1-cp312-none-win_amd64.whl", hash = "sha256:035ede2e16da7281041f0e626459bcae33ed998cca6a0a007a5ebb73414ac72d"}, 596 | {file = "pydantic_core-2.20.1-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:0827505a5c87e8aa285dc31e9ec7f4a17c81a813d45f70b1d9164e03a813a686"}, 597 | {file = "pydantic_core-2.20.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:19c0fa39fa154e7e0b7f82f88ef85faa2a4c23cc65aae2f5aea625e3c13c735a"}, 598 | {file = "pydantic_core-2.20.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4aa223cd1e36b642092c326d694d8bf59b71ddddc94cdb752bbbb1c5c91d833b"}, 599 | {file = "pydantic_core-2.20.1-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c336a6d235522a62fef872c6295a42ecb0c4e1d0f1a3e500fe949415761b8a19"}, 600 | {file = "pydantic_core-2.20.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7eb6a0587eded33aeefea9f916899d42b1799b7b14b8f8ff2753c0ac1741edac"}, 601 | {file = "pydantic_core-2.20.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:70c8daf4faca8da5a6d655f9af86faf6ec2e1768f4b8b9d0226c02f3d6209703"}, 602 | {file = "pydantic_core-2.20.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e9fa4c9bf273ca41f940bceb86922a7667cd5bf90e95dbb157cbb8441008482c"}, 603 | {file = "pydantic_core-2.20.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:11b71d67b4725e7e2a9f6e9c0ac1239bbc0c48cce3dc59f98635efc57d6dac83"}, 604 | {file = "pydantic_core-2.20.1-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:270755f15174fb983890c49881e93f8f1b80f0b5e3a3cc1394a255706cabd203"}, 605 | {file = "pydantic_core-2.20.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:c81131869240e3e568916ef4c307f8b99583efaa60a8112ef27a366eefba8ef0"}, 606 | {file = "pydantic_core-2.20.1-cp313-none-win32.whl", hash = "sha256:b91ced227c41aa29c672814f50dbb05ec93536abf8f43cd14ec9521ea09afe4e"}, 607 | {file = "pydantic_core-2.20.1-cp313-none-win_amd64.whl", hash = "sha256:65db0f2eefcaad1a3950f498aabb4875c8890438bc80b19362cf633b87a8ab20"}, 608 | {file = "pydantic_core-2.20.1-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:4745f4ac52cc6686390c40eaa01d48b18997cb130833154801a442323cc78f91"}, 609 | {file = "pydantic_core-2.20.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:a8ad4c766d3f33ba8fd692f9aa297c9058970530a32c728a2c4bfd2616d3358b"}, 610 | {file = "pydantic_core-2.20.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:41e81317dd6a0127cabce83c0c9c3fbecceae981c8391e6f1dec88a77c8a569a"}, 611 | {file = "pydantic_core-2.20.1-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:04024d270cf63f586ad41fff13fde4311c4fc13ea74676962c876d9577bcc78f"}, 612 | {file = "pydantic_core-2.20.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:eaad4ff2de1c3823fddf82f41121bdf453d922e9a238642b1dedb33c4e4f98ad"}, 613 | {file = "pydantic_core-2.20.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:26ab812fa0c845df815e506be30337e2df27e88399b985d0bb4e3ecfe72df31c"}, 614 | {file = "pydantic_core-2.20.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3c5ebac750d9d5f2706654c638c041635c385596caf68f81342011ddfa1e5598"}, 615 | {file = "pydantic_core-2.20.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2aafc5a503855ea5885559eae883978c9b6d8c8993d67766ee73d82e841300dd"}, 616 | {file = "pydantic_core-2.20.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:4868f6bd7c9d98904b748a2653031fc9c2f85b6237009d475b1008bfaeb0a5aa"}, 617 | {file = "pydantic_core-2.20.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:aa2f457b4af386254372dfa78a2eda2563680d982422641a85f271c859df1987"}, 618 | {file = "pydantic_core-2.20.1-cp38-none-win32.whl", hash = "sha256:225b67a1f6d602de0ce7f6c1c3ae89a4aa25d3de9be857999e9124f15dab486a"}, 619 | {file = "pydantic_core-2.20.1-cp38-none-win_amd64.whl", hash = "sha256:6b507132dcfc0dea440cce23ee2182c0ce7aba7054576efc65634f080dbe9434"}, 620 | {file = "pydantic_core-2.20.1-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:b03f7941783b4c4a26051846dea594628b38f6940a2fdc0df00b221aed39314c"}, 621 | {file = "pydantic_core-2.20.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1eedfeb6089ed3fad42e81a67755846ad4dcc14d73698c120a82e4ccf0f1f9f6"}, 622 | {file = "pydantic_core-2.20.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:635fee4e041ab9c479e31edda27fcf966ea9614fff1317e280d99eb3e5ab6fe2"}, 623 | {file = "pydantic_core-2.20.1-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:77bf3ac639c1ff567ae3b47f8d4cc3dc20f9966a2a6dd2311dcc055d3d04fb8a"}, 624 | {file = "pydantic_core-2.20.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7ed1b0132f24beeec5a78b67d9388656d03e6a7c837394f99257e2d55b461611"}, 625 | {file = "pydantic_core-2.20.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c6514f963b023aeee506678a1cf821fe31159b925c4b76fe2afa94cc70b3222b"}, 626 | {file = "pydantic_core-2.20.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10d4204d8ca33146e761c79f83cc861df20e7ae9f6487ca290a97702daf56006"}, 627 | {file = "pydantic_core-2.20.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2d036c7187b9422ae5b262badb87a20a49eb6c5238b2004e96d4da1231badef1"}, 628 | {file = "pydantic_core-2.20.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9ebfef07dbe1d93efb94b4700f2d278494e9162565a54f124c404a5656d7ff09"}, 629 | {file = "pydantic_core-2.20.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:6b9d9bb600328a1ce523ab4f454859e9d439150abb0906c5a1983c146580ebab"}, 630 | {file = "pydantic_core-2.20.1-cp39-none-win32.whl", hash = "sha256:784c1214cb6dd1e3b15dd8b91b9a53852aed16671cc3fbe4786f4f1db07089e2"}, 631 | {file = "pydantic_core-2.20.1-cp39-none-win_amd64.whl", hash = "sha256:d2fe69c5434391727efa54b47a1e7986bb0186e72a41b203df8f5b0a19a4f669"}, 632 | {file = "pydantic_core-2.20.1-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:a45f84b09ac9c3d35dfcf6a27fd0634d30d183205230a0ebe8373a0e8cfa0906"}, 633 | {file = "pydantic_core-2.20.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:d02a72df14dfdbaf228424573a07af10637bd490f0901cee872c4f434a735b94"}, 634 | {file = "pydantic_core-2.20.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d2b27e6af28f07e2f195552b37d7d66b150adbaa39a6d327766ffd695799780f"}, 635 | {file = "pydantic_core-2.20.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:084659fac3c83fd674596612aeff6041a18402f1e1bc19ca39e417d554468482"}, 636 | {file = "pydantic_core-2.20.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:242b8feb3c493ab78be289c034a1f659e8826e2233786e36f2893a950a719bb6"}, 637 | {file = "pydantic_core-2.20.1-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:38cf1c40a921d05c5edc61a785c0ddb4bed67827069f535d794ce6bcded919fc"}, 638 | {file = "pydantic_core-2.20.1-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:e0bbdd76ce9aa5d4209d65f2b27fc6e5ef1312ae6c5333c26db3f5ade53a1e99"}, 639 | {file = "pydantic_core-2.20.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:254ec27fdb5b1ee60684f91683be95e5133c994cc54e86a0b0963afa25c8f8a6"}, 640 | {file = "pydantic_core-2.20.1-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:407653af5617f0757261ae249d3fba09504d7a71ab36ac057c938572d1bc9331"}, 641 | {file = "pydantic_core-2.20.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:c693e916709c2465b02ca0ad7b387c4f8423d1db7b4649c551f27a529181c5ad"}, 642 | {file = "pydantic_core-2.20.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5b5ff4911aea936a47d9376fd3ab17e970cc543d1b68921886e7f64bd28308d1"}, 643 | {file = "pydantic_core-2.20.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:177f55a886d74f1808763976ac4efd29b7ed15c69f4d838bbd74d9d09cf6fa86"}, 644 | {file = "pydantic_core-2.20.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:964faa8a861d2664f0c7ab0c181af0bea66098b1919439815ca8803ef136fc4e"}, 645 | {file = "pydantic_core-2.20.1-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:4dd484681c15e6b9a977c785a345d3e378d72678fd5f1f3c0509608da24f2ac0"}, 646 | {file = "pydantic_core-2.20.1-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:f6d6cff3538391e8486a431569b77921adfcdef14eb18fbf19b7c0a5294d4e6a"}, 647 | {file = "pydantic_core-2.20.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:a6d511cc297ff0883bc3708b465ff82d7560193169a8b93260f74ecb0a5e08a7"}, 648 | {file = "pydantic_core-2.20.1.tar.gz", hash = "sha256:26ca695eeee5f9f1aeeb211ffc12f10bcb6f71e2989988fda61dabd65db878d4"}, 649 | ] 650 | 651 | [package.dependencies] 652 | typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0" 653 | 654 | [[package]] 655 | name = "pydantic-settings" 656 | version = "2.4.0" 657 | description = "Settings management using Pydantic" 658 | optional = false 659 | python-versions = ">=3.8" 660 | files = [ 661 | {file = "pydantic_settings-2.4.0-py3-none-any.whl", hash = "sha256:bb6849dc067f1687574c12a639e231f3a6feeed0a12d710c1382045c5db1c315"}, 662 | {file = "pydantic_settings-2.4.0.tar.gz", hash = "sha256:ed81c3a0f46392b4d7c0a565c05884e6e54b3456e6f0fe4d8814981172dc9a88"}, 663 | ] 664 | 665 | [package.dependencies] 666 | pydantic = ">=2.7.0" 667 | python-dotenv = ">=0.21.0" 668 | 669 | [package.extras] 670 | azure-key-vault = ["azure-identity (>=1.16.0)", "azure-keyvault-secrets (>=4.8.0)"] 671 | toml = ["tomli (>=2.0.1)"] 672 | yaml = ["pyyaml (>=6.0.1)"] 673 | 674 | [[package]] 675 | name = "pysocks" 676 | version = "1.7.1" 677 | description = "A Python SOCKS client module. See https://github.com/Anorov/PySocks for more information." 678 | optional = false 679 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" 680 | files = [ 681 | {file = "PySocks-1.7.1-py27-none-any.whl", hash = "sha256:08e69f092cc6dbe92a0fdd16eeb9b9ffbc13cadfe5ca4c7bd92ffb078b293299"}, 682 | {file = "PySocks-1.7.1-py3-none-any.whl", hash = "sha256:2725bd0a9925919b9b51739eea5f9e2bae91e83288108a9ad338b2e3a4435ee5"}, 683 | {file = "PySocks-1.7.1.tar.gz", hash = "sha256:3f8804571ebe159c380ac6de37643bb4685970655d3bba243530d6558b799aa0"}, 684 | ] 685 | 686 | [[package]] 687 | name = "python-dateutil" 688 | version = "2.9.0.post0" 689 | description = "Extensions to the standard Python datetime module" 690 | optional = false 691 | python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" 692 | files = [ 693 | {file = "python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3"}, 694 | {file = "python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427"}, 695 | ] 696 | 697 | [package.dependencies] 698 | six = ">=1.5" 699 | 700 | [[package]] 701 | name = "python-dotenv" 702 | version = "1.0.1" 703 | description = "Read key-value pairs from a .env file and set them as environment variables" 704 | optional = false 705 | python-versions = ">=3.8" 706 | files = [ 707 | {file = "python-dotenv-1.0.1.tar.gz", hash = "sha256:e324ee90a023d808f1959c46bcbc04446a10ced277783dc6ee09987c37ec10ca"}, 708 | {file = "python_dotenv-1.0.1-py3-none-any.whl", hash = "sha256:f7b63ef50f1b690dddf550d03497b66d609393b40b564ed0d674909a68ebf16a"}, 709 | ] 710 | 711 | [package.extras] 712 | cli = ["click (>=5.0)"] 713 | 714 | [[package]] 715 | name = "pytz" 716 | version = "2024.1" 717 | description = "World timezone definitions, modern and historical" 718 | optional = false 719 | python-versions = "*" 720 | files = [ 721 | {file = "pytz-2024.1-py2.py3-none-any.whl", hash = "sha256:328171f4e3623139da4983451950b28e95ac706e13f3f2630a879749e7a8b319"}, 722 | {file = "pytz-2024.1.tar.gz", hash = "sha256:2a29735ea9c18baf14b448846bde5a48030ed267578472d8955cd0e7443a9812"}, 723 | ] 724 | 725 | [[package]] 726 | name = "requests" 727 | version = "2.32.3" 728 | description = "Python HTTP for Humans." 729 | optional = false 730 | python-versions = ">=3.8" 731 | files = [ 732 | {file = "requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6"}, 733 | {file = "requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760"}, 734 | ] 735 | 736 | [package.dependencies] 737 | certifi = ">=2017.4.17" 738 | charset-normalizer = ">=2,<4" 739 | idna = ">=2.5,<4" 740 | urllib3 = ">=1.21.1,<3" 741 | 742 | [package.extras] 743 | socks = ["PySocks (>=1.5.6,!=1.5.7)"] 744 | use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] 745 | 746 | [[package]] 747 | name = "selenium" 748 | version = "4.23.1" 749 | description = "Official Python bindings for Selenium WebDriver" 750 | optional = false 751 | python-versions = ">=3.8" 752 | files = [ 753 | {file = "selenium-4.23.1-py3-none-any.whl", hash = "sha256:3a8d9f23dc636bd3840dd56f00c2739e32ec0c1e34a821dd553e15babef24477"}, 754 | {file = "selenium-4.23.1.tar.gz", hash = "sha256:128d099e66284437e7128d2279176ec7a06e6ec7426e167f5d34987166bd8f46"}, 755 | ] 756 | 757 | [package.dependencies] 758 | certifi = ">=2021.10.8" 759 | trio = ">=0.17,<1.0" 760 | trio-websocket = ">=0.9,<1.0" 761 | typing_extensions = ">=4.9,<5.0" 762 | urllib3 = {version = ">=1.26,<3", extras = ["socks"]} 763 | websocket-client = ">=1.8,<2.0" 764 | 765 | [[package]] 766 | name = "six" 767 | version = "1.16.0" 768 | description = "Python 2 and 3 compatibility utilities" 769 | optional = false 770 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" 771 | files = [ 772 | {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, 773 | {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, 774 | ] 775 | 776 | [[package]] 777 | name = "sniffio" 778 | version = "1.3.1" 779 | description = "Sniff out which async library your code is running under" 780 | optional = false 781 | python-versions = ">=3.7" 782 | files = [ 783 | {file = "sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2"}, 784 | {file = "sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc"}, 785 | ] 786 | 787 | [[package]] 788 | name = "sortedcontainers" 789 | version = "2.4.0" 790 | description = "Sorted Containers -- Sorted List, Sorted Dict, Sorted Set" 791 | optional = false 792 | python-versions = "*" 793 | files = [ 794 | {file = "sortedcontainers-2.4.0-py2.py3-none-any.whl", hash = "sha256:a163dcaede0f1c021485e957a39245190e74249897e2ae4b2aa38595db237ee0"}, 795 | {file = "sortedcontainers-2.4.0.tar.gz", hash = "sha256:25caa5a06cc30b6b83d11423433f65d1f9d76c4c6a0c90e3379eaa43b9bfdb88"}, 796 | ] 797 | 798 | [[package]] 799 | name = "soupsieve" 800 | version = "2.6" 801 | description = "A modern CSS selector implementation for Beautiful Soup." 802 | optional = false 803 | python-versions = ">=3.8" 804 | files = [ 805 | {file = "soupsieve-2.6-py3-none-any.whl", hash = "sha256:e72c4ff06e4fb6e4b5a9f0f55fe6e81514581fca1515028625d0f299c602ccc9"}, 806 | {file = "soupsieve-2.6.tar.gz", hash = "sha256:e2e68417777af359ec65daac1057404a3c8a5455bb8abc36f1a9866ab1a51abb"}, 807 | ] 808 | 809 | [[package]] 810 | name = "trio" 811 | version = "0.26.2" 812 | description = "A friendly Python library for async concurrency and I/O" 813 | optional = false 814 | python-versions = ">=3.8" 815 | files = [ 816 | {file = "trio-0.26.2-py3-none-any.whl", hash = "sha256:c5237e8133eb0a1d72f09a971a55c28ebe69e351c783fc64bc37db8db8bbe1d0"}, 817 | {file = "trio-0.26.2.tar.gz", hash = "sha256:0346c3852c15e5c7d40ea15972c4805689ef2cb8b5206f794c9c19450119f3a4"}, 818 | ] 819 | 820 | [package.dependencies] 821 | attrs = ">=23.2.0" 822 | cffi = {version = ">=1.14", markers = "os_name == \"nt\" and implementation_name != \"pypy\""} 823 | idna = "*" 824 | outcome = "*" 825 | sniffio = ">=1.3.0" 826 | sortedcontainers = "*" 827 | 828 | [[package]] 829 | name = "trio-websocket" 830 | version = "0.11.1" 831 | description = "WebSocket library for Trio" 832 | optional = false 833 | python-versions = ">=3.7" 834 | files = [ 835 | {file = "trio-websocket-0.11.1.tar.gz", hash = "sha256:18c11793647703c158b1f6e62de638acada927344d534e3c7628eedcb746839f"}, 836 | {file = "trio_websocket-0.11.1-py3-none-any.whl", hash = "sha256:520d046b0d030cf970b8b2b2e00c4c2245b3807853ecd44214acd33d74581638"}, 837 | ] 838 | 839 | [package.dependencies] 840 | trio = ">=0.11" 841 | wsproto = ">=0.14" 842 | 843 | [[package]] 844 | name = "typing-extensions" 845 | version = "4.12.2" 846 | description = "Backported and Experimental Type Hints for Python 3.8+" 847 | optional = false 848 | python-versions = ">=3.8" 849 | files = [ 850 | {file = "typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d"}, 851 | {file = "typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"}, 852 | ] 853 | 854 | [[package]] 855 | name = "tzdata" 856 | version = "2024.1" 857 | description = "Provider of IANA time zone data" 858 | optional = false 859 | python-versions = ">=2" 860 | files = [ 861 | {file = "tzdata-2024.1-py2.py3-none-any.whl", hash = "sha256:9068bc196136463f5245e51efda838afa15aaeca9903f49050dfa2679db4d252"}, 862 | {file = "tzdata-2024.1.tar.gz", hash = "sha256:2674120f8d891909751c38abcdfd386ac0a5a1127954fbc332af6b5ceae07efd"}, 863 | ] 864 | 865 | [[package]] 866 | name = "urllib3" 867 | version = "2.2.2" 868 | description = "HTTP library with thread-safe connection pooling, file post, and more." 869 | optional = false 870 | python-versions = ">=3.8" 871 | files = [ 872 | {file = "urllib3-2.2.2-py3-none-any.whl", hash = "sha256:a448b2f64d686155468037e1ace9f2d2199776e17f0a46610480d311f73e3472"}, 873 | {file = "urllib3-2.2.2.tar.gz", hash = "sha256:dd505485549a7a552833da5e6063639d0d177c04f23bc3864e41e5dc5f612168"}, 874 | ] 875 | 876 | [package.dependencies] 877 | pysocks = {version = ">=1.5.6,<1.5.7 || >1.5.7,<2.0", optional = true, markers = "extra == \"socks\""} 878 | 879 | [package.extras] 880 | brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"] 881 | h2 = ["h2 (>=4,<5)"] 882 | socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] 883 | zstd = ["zstandard (>=0.18.0)"] 884 | 885 | [[package]] 886 | name = "webdriver-manager" 887 | version = "4.0.2" 888 | description = "Library provides the way to automatically manage drivers for different browsers" 889 | optional = false 890 | python-versions = ">=3.7" 891 | files = [ 892 | {file = "webdriver_manager-4.0.2-py2.py3-none-any.whl", hash = "sha256:75908d92ecc45ff2b9953614459c633db8f9aa1ff30181cefe8696e312908129"}, 893 | {file = "webdriver_manager-4.0.2.tar.gz", hash = "sha256:efedf428f92fd6d5c924a0d054e6d1322dd77aab790e834ee767af392b35590f"}, 894 | ] 895 | 896 | [package.dependencies] 897 | packaging = "*" 898 | python-dotenv = "*" 899 | requests = "*" 900 | 901 | [[package]] 902 | name = "websocket-client" 903 | version = "1.8.0" 904 | description = "WebSocket client for Python with low level API options" 905 | optional = false 906 | python-versions = ">=3.8" 907 | files = [ 908 | {file = "websocket_client-1.8.0-py3-none-any.whl", hash = "sha256:17b44cc997f5c498e809b22cdf2d9c7a9e71c02c8cc2b6c56e7c2d1239bfa526"}, 909 | {file = "websocket_client-1.8.0.tar.gz", hash = "sha256:3239df9f44da632f96012472805d40a23281a991027ce11d2f45a6f24ac4c3da"}, 910 | ] 911 | 912 | [package.extras] 913 | docs = ["Sphinx (>=6.0)", "myst-parser (>=2.0.0)", "sphinx-rtd-theme (>=1.1.0)"] 914 | optional = ["python-socks", "wsaccel"] 915 | test = ["websockets"] 916 | 917 | [[package]] 918 | name = "wsproto" 919 | version = "1.2.0" 920 | description = "WebSockets state-machine based protocol implementation" 921 | optional = false 922 | python-versions = ">=3.7.0" 923 | files = [ 924 | {file = "wsproto-1.2.0-py3-none-any.whl", hash = "sha256:b9acddd652b585d75b20477888c56642fdade28bdfd3579aa24a4d2c037dd736"}, 925 | {file = "wsproto-1.2.0.tar.gz", hash = "sha256:ad565f26ecb92588a3e43bc3d96164de84cd9902482b130d0ddbaa9664a85065"}, 926 | ] 927 | 928 | [package.dependencies] 929 | h11 = ">=0.9.0,<1" 930 | 931 | [metadata] 932 | lock-version = "2.0" 933 | python-versions = "^3.11" 934 | content-hash = "50b045445dc2e321e202e7d0585b5b1f994bea2806ee77b674853057bb3b6bea" 935 | --------------------------------------------------------------------------------