├── src ├── __init__.py ├── logger.py ├── date_utils.py ├── types.py ├── config.py ├── feature_store_api.py ├── dataflow.py ├── technical_indicators.py └── flow_steps.py ├── .gitignore ├── images ├── header.png └── feature_pipeline.png ├── setup-ec2.sh ├── set_environment_variables.sh ├── pyproject.toml ├── Makefile ├── scripts └── insert_data_to_feature_group.py ├── README.md └── poetry.lock /src/__init__.py: -------------------------------------------------------------------------------- 1 | __version__ = '0.1.0' 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | setup-ec2-prod.sh 2 | .env 3 | .venv/ 4 | *.tar 5 | __pycache__/ 6 | .DS_Store -------------------------------------------------------------------------------- /images/header.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Paulescu/bytewax-hopsworks-example/HEAD/images/header.png -------------------------------------------------------------------------------- /images/feature_pipeline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Paulescu/bytewax-hopsworks-example/HEAD/images/feature_pipeline.png -------------------------------------------------------------------------------- /src/logger.py: -------------------------------------------------------------------------------- 1 | import logging 2 | 3 | def get_logger() -> logging.Logger: 4 | """_summary_ 5 | 6 | Returns: 7 | logging.Logger: _description_ 8 | """ 9 | logger = logging.getLogger('dataflow') 10 | logger.setLevel(logging.INFO) 11 | return logger 12 | -------------------------------------------------------------------------------- /setup-ec2.sh: -------------------------------------------------------------------------------- 1 | # remove this package to avoid the following error: 2 | # pip cannot uninstall : "It is a distutils installed project" 3 | apt autoremove -y python3-pyasn1-modules/focal 4 | apt autoremove -y python3-pexpect/focal 5 | apt autoremove -y python3-entrypoints/focal 6 | 7 | # pip install pip --upgrade 8 | # pip install pyopenssl --upgrade -------------------------------------------------------------------------------- /set_environment_variables.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo "Please enter HOPSWORKS_PROJECT_NAME:" 4 | read HOPSWORKS_PROJECT_NAME 5 | 6 | echo "Please enter HOPSWORKS_API_KEY:" 7 | read HOPSWORKS_API_KEY 8 | 9 | export HOPSWORKS_PROJECT_NAME=$HOPSWORKS_PROJECT_NAME 10 | export HOPSWORKS_API_KEY=$HOPSWORKS_API_KEY 11 | 12 | echo "Variables set as environment variables" -------------------------------------------------------------------------------- /src/date_utils.py: -------------------------------------------------------------------------------- 1 | from datetime import datetime, timezone 2 | 3 | def str2epoch(x: str) -> int: 4 | return str2datetime(x).timestamp() 5 | 6 | def str2datetime(s: str) -> datetime: 7 | return datetime.strptime(s, "%Y-%m-%dT%H:%M:%S.%fZ").replace(tzinfo=timezone.utc) 8 | 9 | def epoch2datetime(epoch: int) -> datetime: 10 | return datetime.fromtimestamp(epoch).replace(tzinfo=timezone.utc) -------------------------------------------------------------------------------- /src/types.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | from dataclasses import dataclass 3 | 4 | @dataclass 5 | class Ticker: 6 | product_id : str 7 | ts_unix : int 8 | price : float 9 | size : float 10 | 11 | @dataclass 12 | class FeatureGroupMetadata: 13 | name: str 14 | version: int 15 | description: str 16 | primary_key: List[str] 17 | event_time: str 18 | online_enabled: bool 19 | -------------------------------------------------------------------------------- /src/config.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | from src.types import FeatureGroupMetadata 4 | 5 | # load Feature Store credentials from environment variables 6 | HOPSWORKS_PROJECT_NAME = os.environ['HOPSWORKS_PROJECT_NAME'] 7 | HOPSWORKS_API_KEY = os.environ['HOPSWORKS_API_KEY'] 8 | 9 | WINDOW_SECONDS = 30 10 | PRODUCT_IDS = [ 11 | "ETH-USD", 12 | # "BTC-USD", 13 | ] 14 | 15 | FEATURE_GROUP_METADATA = FeatureGroupMetadata( 16 | name=f'ohlc_{WINDOW_SECONDS}_sec', 17 | version=1, 18 | description=f"OHLC data with technical indicators every {WINDOW_SECONDS} seconds", 19 | primary_key=['time'], # TODO: add product_id as key, 20 | event_time='time', 21 | online_enabled=True, 22 | ) 23 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.poetry] 2 | name = "src" 3 | version = "0.1.0" 4 | description = "" 5 | authors = ["Pau "] 6 | 7 | [tool.poetry.dependencies] 8 | python = ">=3.9,<3.10" 9 | ta = "^0.10.2" 10 | bytewax = "^0.15.1" 11 | websocket-client = "^1.5.1" 12 | hopsworks = "^3.0.5" 13 | pyOpenSSL = "^23.1.1" 14 | retry = "^0.9.2" 15 | 16 | [tool.poetry.dev-dependencies] 17 | pytest = "^5.2" 18 | jupyter = "^1.0.0" 19 | pip-tools = "^6.12.3" 20 | pylint = "^2.17.1" 21 | black = "^23.1.0" 22 | isort = "^5.12.0" 23 | 24 | [build-system] 25 | requires = ["poetry-core>=1.0.0"] 26 | build-backend = "poetry.core.masonry.api" 27 | 28 | [tool.pylint.messages_control] 29 | disable = [ 30 | "missing-module-docstring", 31 | ] 32 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: deploy delete list project-files run 2 | 3 | # install Poetry and Python dependencies 4 | init: 5 | curl -sSL https://install.python-poetry.org | python3 - 6 | poetry install 7 | 8 | # run the feature-pipeline locally 9 | run: 10 | poetry run python src/dataflow.py 11 | 12 | # generate a tar file with project files to send to AWS EC2 instance 13 | project-files: 14 | tar \ 15 | --exclude={'.git','.gitignore','requirements.txt','poetry.lock','README.md','Makefile','setup-ec2.sh','.venv','*.tar','.DS_Store','__pycache__','images'} \ 16 | -vzcf project-files.tar -C . . 17 | 18 | # deploy the feature-pipeline to an EC2 instance on AWS 19 | deploy: project-files 20 | waxctl aws deploy project-files.tar \ 21 | -f src/dataflow.py \ 22 | --system-setup-file-name ./setup-ec2.sh \ 23 | --region us-east-1 \ 24 | -t t2.micro \ 25 | --name "bytewax2" \ 26 | --python-package \ 27 | --debug \ 28 | -E HOPSWORKS_PROJECT_NAME=${HOPSWORKS_PROJECT_NAME},HOPSWORKS_API_KEY=${HOPSWORKS_API_KEY} 29 | 30 | # list all bytewax deployments 31 | list: 32 | waxctl aws ls --verbose --name "bytewax2" 33 | 34 | # stop the feature-pipeline and delete the EC2 instance 35 | delete: 36 | waxctl aws delete --name "bytewax2" --yes -------------------------------------------------------------------------------- /scripts/insert_data_to_feature_group.py: -------------------------------------------------------------------------------- 1 | from time import sleep 2 | 3 | # import hopsworks 4 | 5 | from src.feature_store_api import get_feature_group 6 | from src.config import FEATURE_GROUP_METADATA 7 | import src.config as config 8 | 9 | # project = hopsworks.login( 10 | # project=config.HOPSWORKS_PROJECT_NAME, 11 | # api_key_value=config.HOPSWORKS_API_KEY 12 | # ) 13 | # print(f'{config.HOPSWORKS_PROJECT_NAME=}') 14 | # print(f'{config.HOPSWORKS_API_KEY=}') 15 | # feature_store = project.get_feature_store() 16 | 17 | print(f'{FEATURE_GROUP_METADATA=}') 18 | 19 | feature_group = get_feature_group(FEATURE_GROUP_METADATA) 20 | 21 | data = [ 22 | {'time': 1, 'open': 45}, 23 | {'time': 2, 'open': 47}, 24 | {'time': 3, 'open': 47}, 25 | {'time': 4, 'open': 47}, 26 | {'time': 5, 'open': 47}, 27 | {'time': 6, 'open': 47}, 28 | {'time': 7, 'open': 47}, 29 | ] 30 | import pandas as pd 31 | 32 | job = None 33 | for d in data: 34 | job, _ = feature_group.insert(pd.DataFrame.from_records([d]), 35 | write_options={"start_offline_backfill": False}) 36 | 37 | import hsfs 38 | job_api = hsfs.core.job_api.JobApi() 39 | print(f'Launching job {job.name}') 40 | job_api.launch(name=job.name) -------------------------------------------------------------------------------- /src/feature_store_api.py: -------------------------------------------------------------------------------- 1 | import hsfs 2 | import hopsworks 3 | 4 | import src.config as config 5 | from src.types import FeatureGroupMetadata 6 | 7 | 8 | def get_feature_store() -> hsfs.feature_store.FeatureStore: 9 | """Connects to Hopsworks and returns a pointer to the feature store 10 | 11 | Returns: 12 | hsfs.feature_store.FeatureStore: pointer to the feature store 13 | """ 14 | project = hopsworks.login( 15 | project=config.HOPSWORKS_PROJECT_NAME, 16 | api_key_value=config.HOPSWORKS_API_KEY 17 | ) 18 | return project.get_feature_store() 19 | 20 | 21 | def get_feature_group( 22 | # name: str, 23 | # version: Optional[int] = 1 24 | feature_group_metadata: FeatureGroupMetadata 25 | ) -> hsfs.feature_group.FeatureGroup: 26 | """Connects to the feature store and returns a pointer to the given 27 | feature group `name` 28 | 29 | Args: 30 | name (str): name of the feature group 31 | version (Optional[int], optional): _description_. Defaults to 1. 32 | 33 | Returns: 34 | hsfs.feature_group.FeatureGroup: pointer to the feature group 35 | """ 36 | return get_feature_store().get_or_create_feature_group( 37 | name=feature_group_metadata.name, 38 | version=feature_group_metadata.version, 39 | description=feature_group_metadata.description, 40 | primary_key=feature_group_metadata.primary_key, 41 | event_time=feature_group_metadata.event_time, 42 | online_enabled=feature_group_metadata.online_enabled 43 | ) -------------------------------------------------------------------------------- /src/dataflow.py: -------------------------------------------------------------------------------- 1 | # pylint: disable=missing-module-docstring 2 | from argparse import ArgumentParser 3 | 4 | from bytewax.dataflow import Dataflow 5 | from bytewax.execution import run_main 6 | from bytewax.outputs import StdOutputConfig 7 | 8 | from src import config 9 | from src.flow_steps import ( 10 | connect_to_input_socket, 11 | parse_string_to_dict, 12 | set_product_id_as_key, 13 | add_tumbling_window, 14 | aggregate_raw_trades_as_ohlc, 15 | compute_tech_indicators, 16 | tuple_to_dict, 17 | save_output_to_feature_store, 18 | ) 19 | from src.logger import get_logger 20 | 21 | def get_dataflow( 22 | window_seconds: int, 23 | ) -> Dataflow: 24 | """Constructs and returns a ByteWax Dataflow 25 | 26 | Args: 27 | window_seconds (int) 28 | 29 | Returns: 30 | Dataflow: 31 | """ 32 | flow = Dataflow() 33 | connect_to_input_socket(flow) 34 | parse_string_to_dict(flow) 35 | set_product_id_as_key(flow) 36 | add_tumbling_window(flow, window_seconds) 37 | aggregate_raw_trades_as_ohlc(flow) 38 | compute_tech_indicators(flow) 39 | tuple_to_dict(flow) 40 | return flow 41 | 42 | if __name__ == "__main__": 43 | 44 | logger = get_logger() 45 | 46 | logger.info('Parsing command line arguments...') 47 | parser = ArgumentParser() 48 | parser.add_argument('--dev', action='store_true') 49 | parser.set_defaults(dev=False) 50 | args = parser.parse_args() 51 | 52 | # Test inputs/outputs for debugging 53 | # WINDOW_SECONDS = 5 54 | logger.info('Generating dataflow') 55 | test_flow = get_dataflow(window_seconds=config.WINDOW_SECONDS) 56 | 57 | if args.dev: 58 | test_flow.capture(StdOutputConfig()) 59 | else: 60 | from src.config import FEATURE_GROUP_METADATA 61 | save_output_to_feature_store(test_flow, FEATURE_GROUP_METADATA) 62 | 63 | logger.info('Running dataflow') 64 | run_main(test_flow) 65 | -------------------------------------------------------------------------------- /src/technical_indicators.py: -------------------------------------------------------------------------------- 1 | from typing import Dict, Tuple 2 | 3 | import numpy as np 4 | import pandas as pd 5 | 6 | def get_bb_bands_talib(close_prices: np.array, window_size: int) -> Tuple[float, float, float]: 7 | """_summary_ 8 | 9 | Args: 10 | close_prices (np.array): _description_ 11 | 12 | Returns: 13 | Tuple[float, float, float]: _description_ 14 | """ 15 | from talib import stream 16 | 17 | upper_band, mid_band, lower_band = \ 18 | stream.BBANDS(close_prices, timeperiod=window_size) 19 | return upper_band, mid_band, lower_band 20 | 21 | def get_bb_bands_ta(close_prices: np.array, window_size: int) -> Tuple[float, float, float]: 22 | """_summary_ 23 | 24 | Args: 25 | close_prices (np.array): _description_ 26 | 27 | Returns: 28 | Tuple[float, float, float]: _description_ 29 | """ 30 | from ta.volatility import BollingerBands 31 | 32 | indicator_bb = BollingerBands(close=pd.Series(close_prices), window=window_size, window_dev=2) 33 | 34 | mid_band = indicator_bb.bollinger_mavg().values[-1] 35 | upper_band = indicator_bb.bollinger_hband().values[-1] 36 | lower_band = indicator_bb.bollinger_lband().values[-1] 37 | 38 | return upper_band, mid_band, lower_band 39 | 40 | 41 | class BollingerBands: 42 | 43 | def __init__(self, window_size: int): 44 | 45 | self.last_n = np.empty(0, dtype=np.double) 46 | self.n = window_size * 2 47 | self.window_size = window_size 48 | 49 | def _push(self, value: float): 50 | 51 | self.last_n = np.insert(self.last_n, 0, value) 52 | try: 53 | self.last_n = np.delete(self.last_n, self.n) 54 | except IndexError: 55 | pass 56 | 57 | def compute(self, data: Dict): 58 | 59 | self._push(data['close']) 60 | 61 | # compute technical indicator 62 | close_prices = self.last_n[::-1] 63 | 64 | upper_band, mid_band, lower_band = get_bb_bands_ta( 65 | close_prices, window_size=self.window_size) 66 | 67 | output = { 68 | 'upper_band': upper_band, 69 | 'mid_band': mid_band, 70 | 'lower_band': lower_band, 71 | **data 72 | } 73 | return self, output 74 | 75 | if __name__ == '__main__': 76 | 77 | # Test inputs for debugging 78 | inputs = [ 79 | {'time': 1678450252.412037, 'open': 1385.42, 'high': 1385.42, 'low': 1385.32, 'close': 1385.32, 'volume': 3.9128633300000004}, 80 | {'time': 1678450255.154885, 'open': 1385.32, 'high': 1385.45, 'low': 1385.32, 'close': 1385.36, 'volume': 4.51889748}, 81 | {'time': 1678450261.314386, 'open': 1385.32, 'high': 1385.49, 'low': 1385.32, 'close': 1385.49, 'volume': 0.64300852}, 82 | {'time': 1678450265.527894, 'open': 1385.49, 'high': 1385.49, 'low': 1385.32, 'close': 1385.39, 'volume': 5.140847330000001}, 83 | {'time': 1678450270.373147, 'open': 1385.21, 'high': 1385.23, 'low': 1385.19, 'close': 1385.19, 'volume': 1.43794472} 84 | ] 85 | 86 | bb = BollingerBands(3) 87 | outputs = [] 88 | for i in inputs: 89 | _, out = bb.compute(i) 90 | print(f'{out=}') -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 |

Compute and store real-time features for crypto trading with Python

3 | 4 |
5 | 6 |
7 | Let's connect 🤗 8 |
9 | Twitter • 10 | LinkedIn • 11 | Newsletter 12 |
13 |
14 | 15 |
16 | 17 |

18 | 19 |

20 | 21 | 22 | #### Table of contents 23 | 1. [What is this repo about?](#what-is-this-repo-about) 24 | 2. [How to run this code](#how-to-run-this-code) 25 | 3. [Wannna build real-world ML products?](#wannna-build-real-world-ml-products) 26 | 27 | 28 | ## What is this repo about? 29 | This repository shows how to 30 | 31 | * **fetch** real-time trade data (aka *raw data*) from the [Coinbase Websocket API](https://help.coinbase.com/en/cloud/websocket-feeds/exchange) 32 | * **transform** trade data into OHLC data (aka *features*) in real-time using [Bytewax](https://bytewax.io/), and 33 | * **store** these features in a serverless Feature Store like [Hopsworks](https://www.hopsworks.ai/). 34 | 35 | This repository is a natural continuation of [this previous project](https://github.com/Paulescu/real-time-ohlc-with-bytewax) where we built a 36 | Streamlit app with real-time feature engineering, but lacked state persistence: after each re-load of the Streamlit app, we lost all features generated up to that point. 37 | 38 | In this project we add *state* to our system through a a Feature Store. We use Hopsworks because 39 | - it is serverless, so we do not need to handle infrastructure 40 | - it has a very generous free tier, with up to 25GB of free storage. 41 | 42 | 43 | ## How to run this code 44 | 45 | 1. Create a Python virtual environment with the project dependencies with 46 | ``` 47 | $ make init 48 | ``` 49 | 50 | 2. Set your Hopsworks project name and API key as environment variables by running the following script (to generate these head to hopsworks.ai, create a free account, create a project and generate an API key for free) 51 | ``` 52 | $ . ./set_environment_variables.sh 53 | ``` 54 | 55 | 3. To run the feature pipeline locally 56 | ``` 57 | $ make run 58 | ``` 59 | 60 | 4. To deploy the feature pipeline on an AWS EC2 instance you first need to have an AWS account and the `aws-cli` tool installed in your local system. Then run the following command to deploy your feature pipeline on an EC2 instance 61 | ``` 62 | $ make deploy 63 | ``` 64 | 65 | 5. Feature pipeline logs are send to AWS CloudWatch. Run the following command to grab the URL where you can see the logs. 66 | ``` 67 | $ make list 68 | ``` 69 | 70 | 6. To shutdown the feature pipeline on AWS and free resources run 71 | ``` 72 | $ make delete 73 | ``` 74 | 75 | > ℹ️ **Implementation details** 76 | > 77 | >* We use Bytewax as our stream-processing engine and the [`waxctl`](https://bytewax.io/>docs/deployment/waxctl-aws) command line tool to deploy our dataflow to EC2. 78 | > 79 | >* If you want to deploy the pipeline to a Kubernetes cluster, you will need to adjust 80 | > the arguments passed to `waxctl` in the `Makefile`. Check the documentation [here](https://bytewax.io/docs/deployment/waxctl) 81 | > to learn how. 82 | 83 | ## Wannna build real-world ML products? 84 | 85 | Check the [Real-World ML Program](https://realworldmachinelearning.carrd.co/), a hands-on, 3-hour course where you will learn 86 | how to design, build, [deploy](https://taxi-demand-predictor.streamlit.app/), and [monitor](https://taxi-demand-predictor-monitoring.streamlit.app/) complete ML products. -------------------------------------------------------------------------------- /src/flow_steps.py: -------------------------------------------------------------------------------- 1 | from typing import Tuple, Dict, List, Generator, Any 2 | import json 3 | from datetime import datetime, timedelta, timezone 4 | import logging 5 | 6 | import numpy as np 7 | import pandas as pd 8 | from websocket import create_connection 9 | from bytewax.inputs import ManualInputConfig 10 | from bytewax.dataflow import Dataflow 11 | from bytewax.window import EventClockConfig, TumblingWindowConfig 12 | from bytewax.outputs import ManualOutputConfig 13 | import hsfs 14 | 15 | from src.config import PRODUCT_IDS 16 | from src.types import Ticker, FeatureGroupMetadata 17 | from src.date_utils import str2epoch, epoch2datetime 18 | from src.feature_store_api import get_feature_group 19 | from src.logger import get_logger 20 | 21 | logger = get_logger() 22 | 23 | def connect_to_input_socket(flow: Dataflow): 24 | """Connects the given dataflow to the Coinbase websocket 25 | 26 | Args: 27 | flow (Dataflow): _description_ 28 | """ 29 | def ws_input(product_ids: List[str], state) -> Generator[Tuple[Any, Any], None, None]: 30 | """Python generator that yields data coming for the websocket for the 31 | given `product_ids` 32 | 33 | Args: 34 | product_ids (List[str]): _description_ 35 | state (_type_): _description_ 36 | 37 | Yields: 38 | Generator[Tuple[Any, Any]]: _description_ 39 | """ 40 | ws = create_connection("wss://ws-feed.pro.coinbase.com") 41 | ws.send( 42 | json.dumps( 43 | { 44 | "type": "subscribe", 45 | "product_ids": product_ids, 46 | "channels": ["ticker"], 47 | } 48 | ) 49 | ) 50 | # The first msg is just a confirmation that we have subscribed. 51 | print(ws.recv()) 52 | while True: 53 | yield state, ws.recv() 54 | 55 | def input_builder(worker_index, worker_count, resume_state): 56 | """Returns Python generator for each worker 57 | 58 | Args: 59 | worker_index (_type_): _description_ 60 | worker_count (_type_): _description_ 61 | resume_state (_type_): _description_ 62 | 63 | Returns: 64 | _type_: _description_ 65 | """ 66 | state = resume_state or None 67 | prods_per_worker = int(len(PRODUCT_IDS) / worker_count) 68 | product_ids = PRODUCT_IDS[ 69 | int(worker_index * prods_per_worker) : int( 70 | worker_index * prods_per_worker + prods_per_worker 71 | ) 72 | ] 73 | return ws_input(product_ids, state) 74 | 75 | flow.input("input", ManualInputConfig(input_builder)) 76 | 77 | def parse_string_to_dict(flow: Dataflow): 78 | 79 | flow.map(json.loads) 80 | 81 | def set_product_id_as_key(flow: Dataflow): 82 | 83 | def key_on_product(data: Dict) -> Tuple[str, Ticker]: 84 | """Transform input `data` into a Tuple[product_id, ticker_data] 85 | where `ticker_data` is a `Ticker` object. 86 | 87 | Args: 88 | data (Dict): _description_ 89 | 90 | Returns: 91 | Tuple[str, Ticker]: _description_ 92 | """ 93 | ticker = Ticker( 94 | product_id=data['product_id'], 95 | ts_unix=str2epoch(data['time']), 96 | price=data['price'], 97 | size=data['last_size'] 98 | ) 99 | return (data["product_id"], ticker) 100 | 101 | flow.map(key_on_product) 102 | 103 | def add_tumbling_window(flow: Dataflow, window_seconds: int): 104 | 105 | def get_event_time(ticker: Ticker) -> datetime: 106 | """ 107 | This function instructs the event clock on how to retrieve the 108 | event's datetime from the input. 109 | """ 110 | return epoch2datetime(ticker.ts_unix) 111 | 112 | def build_array() -> np.array: 113 | """_summary_ 114 | 115 | Returns: 116 | np.array: _description_ 117 | """ 118 | return np.empty((0,3)) 119 | 120 | def acc_values(previous_data: np.array, ticker: Ticker) -> np.array: 121 | """ 122 | This is the accumulator function, and outputs a numpy array of time and price 123 | """ 124 | return np.insert(previous_data, 0, 125 | np.array((ticker.ts_unix, ticker.price, ticker.size)), 0) 126 | 127 | # Configure the `fold_window` operator to use the event time 128 | cc = EventClockConfig(get_event_time, wait_for_system_duration=timedelta(seconds=10)) 129 | 130 | start_at = datetime.now(timezone.utc) 131 | start_at = start_at - timedelta( 132 | seconds=start_at.second, microseconds=start_at.microsecond 133 | ) 134 | wc = TumblingWindowConfig(start_at=start_at,length=timedelta(seconds=window_seconds)) 135 | 136 | flow.fold_window(f"{window_seconds}_sec", cc, wc, build_array, acc_values) 137 | 138 | def aggregate_raw_trades_as_ohlc(flow: Dataflow): 139 | 140 | # compute OHLC for the window 141 | def calculate_features(ticker_data: Tuple[str, np.array]) -> Tuple[str, Dict]: 142 | """Aggregate trade data in window 143 | 144 | Args: 145 | ticker__data (Tuple[str, np.array]): product_id, data 146 | 147 | Returns: 148 | Tuple[str, Dict]: product_id, Dict with keys 149 | - time 150 | - open 151 | - high 152 | - low 153 | - close 154 | - volume 155 | """ 156 | ticker, data = ticker_data 157 | ohlc = { 158 | "time": data[-1][0], 159 | "open": data[:,1][-1], 160 | "high": np.amax(data[:,1]), 161 | "low":np.amin(data[:,1]), 162 | "close":data[:,1][0], 163 | "volume": np.sum(data[:,2]) 164 | } 165 | return (ticker, ohlc) 166 | 167 | flow.map(calculate_features) 168 | 169 | def compute_tech_indicators(flow: Dataflow): 170 | 171 | # compute technical-indicators 172 | from src.technical_indicators import BollingerBands 173 | flow.stateful_map( 174 | "technical_indicators", 175 | lambda: BollingerBands(3), 176 | BollingerBands.compute 177 | ) 178 | 179 | def tuple_to_dict(flow: Dataflow): 180 | 181 | def _tuple_to_dict(key__dict: Tuple[str, Dict]) -> Dict: 182 | key, dict = key__dict 183 | dict['product_id'] = key 184 | 185 | # TODO: fix this upstream 186 | dict['time'] = int(dict['time']) 187 | 188 | return dict 189 | 190 | flow.map(_tuple_to_dict) 191 | 192 | 193 | from retry import retry 194 | from requests.exceptions import ConnectionError 195 | 196 | @retry(ConnectionError, tries=3, delay=10) 197 | def insert_data_to_feature_group( 198 | feature_group: hsfs.feature_group.FeatureGroup, 199 | data: pd.DataFrame 200 | ) -> hsfs.core.job.Job: 201 | try: 202 | job, _ = feature_group.insert( 203 | data, 204 | write_options={"start_offline_backfill": False}) 205 | return job 206 | 207 | except ConnectionError as e: 208 | logger.error(f"Connection error: {e}") 209 | logger.error("Retrying in 10 seconds...") 210 | raise e 211 | 212 | def save_output_to_feature_store( 213 | flow: Dataflow, 214 | feature_group_metadata: FeatureGroupMetadata 215 | ): 216 | 217 | class HopsworksOutputConfig(ManualOutputConfig): 218 | """Write output of a Dataflow to a Hopsworks Feature Group 219 | 220 | Args: 221 | 222 | feature_group_metadata 223 | 224 | Returns: 225 | 226 | Config object. Pass this as the `output_config` argument of the 227 | `bytewax.dataflow.Dataflow.output` operator. 228 | """ # noqa 229 | 230 | max_buffer_size = 1 #10 231 | # MAX_PARALLEL_EXECUTIONS = 5 232 | 233 | def __new__(cls, feature_group_metadata: FeatureGroupMetadata): 234 | """In classes defined by PyO3 we can only use __new__, not __init__""" 235 | 236 | cls.buffer_size = 0 237 | cls.job = None 238 | 239 | def output_builder(wi, wc): 240 | feature_group = get_feature_group(feature_group_metadata) 241 | # print(f"Saving features to {feature_group_metadata.name}") 242 | job_api = hsfs.core.job_api.JobApi() 243 | 244 | def output_handler(item: Dict): 245 | 246 | df = pd.DataFrame.from_records([item]) 247 | 248 | cls.buffer_size += 1 249 | # cls.job, _ = feature_group.insert( 250 | # df, 251 | # write_options={"start_offline_backfill": False} 252 | # ) 253 | cls.job = insert_data_to_feature_group(feature_group, df) 254 | # logger.info(f'{type(cls.job)=}') 255 | 256 | # check number of jobs currently running. 257 | # n_parallel_executions = len(cls.job.get_executions()) 258 | # if n_parallel_executions < cls.MAX_PARALLEL_EXECUTIONS: 259 | if cls.buffer_size % cls.max_buffer_size == 0: 260 | get_logger().info(f'Launching backfill job {cls.job.name}') 261 | # job_api = hsfs.core.job_api.JobApi() 262 | job_api.launch(name=cls.job.name) 263 | cls.buffer_size = 0 264 | cls.job = None 265 | 266 | return output_handler 267 | 268 | return super().__new__(cls, output_builder) 269 | 270 | flow.capture(HopsworksOutputConfig(feature_group_metadata)) -------------------------------------------------------------------------------- /poetry.lock: -------------------------------------------------------------------------------- 1 | [[package]] 2 | name = "altair" 3 | version = "4.2.2" 4 | description = "Altair: A declarative statistical visualization library for Python." 5 | category = "main" 6 | optional = false 7 | python-versions = ">=3.7" 8 | 9 | [package.dependencies] 10 | entrypoints = "*" 11 | jinja2 = "*" 12 | jsonschema = ">=3.0" 13 | numpy = "*" 14 | pandas = ">=0.18" 15 | toolz = "*" 16 | 17 | [package.extras] 18 | dev = ["black", "docutils", "ipython", "flake8", "pytest", "sphinx", "mistune (<2.0.0)", "m2r", "vega-datasets", "recommonmark"] 19 | 20 | [[package]] 21 | name = "anyio" 22 | version = "3.6.2" 23 | description = "High level compatibility layer for multiple asynchronous event loop implementations" 24 | category = "dev" 25 | optional = false 26 | python-versions = ">=3.6.2" 27 | 28 | [package.dependencies] 29 | idna = ">=2.8" 30 | sniffio = ">=1.1" 31 | 32 | [package.extras] 33 | doc = ["packaging", "sphinx-rtd-theme", "sphinx-autodoc-typehints (>=1.2.0)"] 34 | test = ["coverage[toml] (>=4.5)", "hypothesis (>=4.0)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "contextlib2", "uvloop (<0.15)", "mock (>=4)", "uvloop (>=0.15)"] 35 | trio = ["trio (>=0.16,<0.22)"] 36 | 37 | [[package]] 38 | name = "appnope" 39 | version = "0.1.3" 40 | description = "Disable App Nap on macOS >= 10.9" 41 | category = "main" 42 | optional = false 43 | python-versions = "*" 44 | 45 | [[package]] 46 | name = "argon2-cffi" 47 | version = "21.3.0" 48 | description = "The secure Argon2 password hashing algorithm." 49 | category = "dev" 50 | optional = false 51 | python-versions = ">=3.6" 52 | 53 | [package.dependencies] 54 | argon2-cffi-bindings = "*" 55 | 56 | [package.extras] 57 | dev = ["pre-commit", "cogapp", "tomli", "coverage[toml] (>=5.0.2)", "hypothesis", "pytest", "sphinx", "sphinx-notfound-page", "furo"] 58 | docs = ["sphinx", "sphinx-notfound-page", "furo"] 59 | tests = ["coverage[toml] (>=5.0.2)", "hypothesis", "pytest"] 60 | 61 | [[package]] 62 | name = "argon2-cffi-bindings" 63 | version = "21.2.0" 64 | description = "Low-level CFFI bindings for Argon2" 65 | category = "dev" 66 | optional = false 67 | python-versions = ">=3.6" 68 | 69 | [package.dependencies] 70 | cffi = ">=1.0.1" 71 | 72 | [package.extras] 73 | dev = ["pytest", "cogapp", "pre-commit", "wheel"] 74 | tests = ["pytest"] 75 | 76 | [[package]] 77 | name = "arrow" 78 | version = "1.2.3" 79 | description = "Better dates & times for Python" 80 | category = "dev" 81 | optional = false 82 | python-versions = ">=3.6" 83 | 84 | [package.dependencies] 85 | python-dateutil = ">=2.7.0" 86 | 87 | [[package]] 88 | name = "astroid" 89 | version = "2.15.1" 90 | description = "An abstract syntax tree for Python with inference support." 91 | category = "dev" 92 | optional = false 93 | python-versions = ">=3.7.2" 94 | 95 | [package.dependencies] 96 | lazy-object-proxy = ">=1.4.0" 97 | typing-extensions = {version = ">=4.0.0", markers = "python_version < \"3.11\""} 98 | wrapt = {version = ">=1.11,<2", markers = "python_version < \"3.11\""} 99 | 100 | [[package]] 101 | name = "asttokens" 102 | version = "2.2.1" 103 | description = "Annotate AST trees with source code positions" 104 | category = "main" 105 | optional = false 106 | python-versions = "*" 107 | 108 | [package.dependencies] 109 | six = "*" 110 | 111 | [package.extras] 112 | test = ["astroid", "pytest"] 113 | 114 | [[package]] 115 | name = "atomicwrites" 116 | version = "1.4.1" 117 | description = "Atomic file writes." 118 | category = "dev" 119 | optional = false 120 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" 121 | 122 | [[package]] 123 | name = "attrs" 124 | version = "22.2.0" 125 | description = "Classes Without Boilerplate" 126 | category = "main" 127 | optional = false 128 | python-versions = ">=3.6" 129 | 130 | [package.extras] 131 | cov = ["attrs", "coverage-enable-subprocess", "coverage[toml] (>=5.3)"] 132 | dev = ["attrs"] 133 | docs = ["furo", "sphinx", "myst-parser", "zope.interface", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier"] 134 | tests = ["attrs", "zope.interface"] 135 | tests-no-zope = ["hypothesis", "pympler", "pytest (>=4.3.0)", "pytest-xdist", "cloudpickle", "mypy (>=0.971,<0.990)", "pytest-mypy-plugins"] 136 | tests_no_zope = ["hypothesis", "pympler", "pytest (>=4.3.0)", "pytest-xdist", "cloudpickle", "mypy (>=0.971,<0.990)", "pytest-mypy-plugins"] 137 | 138 | [[package]] 139 | name = "avro" 140 | version = "1.10.2" 141 | description = "Avro is a serialization and RPC framework." 142 | category = "main" 143 | optional = false 144 | python-versions = ">=2.7" 145 | 146 | [package.extras] 147 | snappy = ["python-snappy"] 148 | zstandard = ["zstandard"] 149 | 150 | [[package]] 151 | name = "backcall" 152 | version = "0.2.0" 153 | description = "Specifications for callback functions passed in to an API" 154 | category = "main" 155 | optional = false 156 | python-versions = "*" 157 | 158 | [[package]] 159 | name = "beautifulsoup4" 160 | version = "4.11.2" 161 | description = "Screen-scraping library" 162 | category = "dev" 163 | optional = false 164 | python-versions = ">=3.6.0" 165 | 166 | [package.dependencies] 167 | soupsieve = ">1.2" 168 | 169 | [package.extras] 170 | html5lib = ["html5lib"] 171 | lxml = ["lxml"] 172 | 173 | [[package]] 174 | name = "black" 175 | version = "23.1.0" 176 | description = "The uncompromising code formatter." 177 | category = "dev" 178 | optional = false 179 | python-versions = ">=3.7" 180 | 181 | [package.dependencies] 182 | click = ">=8.0.0" 183 | mypy-extensions = ">=0.4.3" 184 | packaging = ">=22.0" 185 | pathspec = ">=0.9.0" 186 | platformdirs = ">=2" 187 | tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} 188 | typing-extensions = {version = ">=3.10.0.0", markers = "python_version < \"3.10\""} 189 | 190 | [package.extras] 191 | colorama = ["colorama (>=0.4.3)"] 192 | d = ["aiohttp (>=3.7.4)"] 193 | jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] 194 | uvloop = ["uvloop (>=0.15.2)"] 195 | 196 | [[package]] 197 | name = "bleach" 198 | version = "6.0.0" 199 | description = "An easy safelist-based HTML-sanitizing tool." 200 | category = "dev" 201 | optional = false 202 | python-versions = ">=3.7" 203 | 204 | [package.dependencies] 205 | six = ">=1.9.0" 206 | webencodings = "*" 207 | 208 | [package.extras] 209 | css = ["tinycss2 (>=1.1.0,<1.2)"] 210 | 211 | [[package]] 212 | name = "boto3" 213 | version = "1.26.91" 214 | description = "The AWS SDK for Python" 215 | category = "main" 216 | optional = false 217 | python-versions = ">= 3.7" 218 | 219 | [package.dependencies] 220 | botocore = ">=1.29.91,<1.30.0" 221 | jmespath = ">=0.7.1,<2.0.0" 222 | s3transfer = ">=0.6.0,<0.7.0" 223 | 224 | [package.extras] 225 | crt = ["botocore[crt] (>=1.21.0,<2.0a0)"] 226 | 227 | [[package]] 228 | name = "botocore" 229 | version = "1.29.94" 230 | description = "Low-level, data-driven core of boto 3." 231 | category = "main" 232 | optional = false 233 | python-versions = ">= 3.7" 234 | 235 | [package.dependencies] 236 | jmespath = ">=0.7.1,<2.0.0" 237 | python-dateutil = ">=2.1,<3.0.0" 238 | urllib3 = ">=1.25.4,<1.27" 239 | 240 | [package.extras] 241 | crt = ["awscrt (==0.16.9)"] 242 | 243 | [[package]] 244 | name = "build" 245 | version = "0.10.0" 246 | description = "A simple, correct Python build frontend" 247 | category = "dev" 248 | optional = false 249 | python-versions = ">= 3.7" 250 | 251 | [package.dependencies] 252 | colorama = {version = "*", markers = "os_name == \"nt\""} 253 | packaging = ">=19.0" 254 | pyproject_hooks = "*" 255 | tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} 256 | 257 | [package.extras] 258 | test = ["pytest (>=6.2.4)", "filelock (>=3)", "pytest-cov (>=2.12)", "pytest-mock (>=2)", "pytest-rerunfailures (>=9.1)", "pytest-xdist (>=1.34)", "toml (>=0.10.0)", "wheel (>=0.36.0)", "setuptools (>=42.0.0)", "setuptools (>=56.0.0)"] 259 | docs = ["furo (>=2021.08.31)", "sphinx (>=4.0,<5.0)", "sphinx-argparse-cli (>=1.5)", "sphinx-autodoc-typehints (>=1.10)"] 260 | typing = ["importlib-metadata (>=5.1)", "mypy (==0.991)", "tomli", "typing-extensions (>=3.7.4.3)"] 261 | virtualenv = ["virtualenv (>=20.0.35)"] 262 | 263 | [[package]] 264 | name = "bytewax" 265 | version = "0.15.1" 266 | description = "" 267 | category = "main" 268 | optional = false 269 | python-versions = ">=3.7" 270 | 271 | [package.dependencies] 272 | dill = ">=0.3.5" 273 | multiprocess = ">=0.70" 274 | 275 | [package.extras] 276 | dev = ["bytewax", "black (==22.3.0)", "flake8 (==4.0.1)", "isort (==5.10.1)", "pre-commit (==2.19.0)"] 277 | test = ["pytest (==7.1.0)", "myst-docutils (==0.17.0)"] 278 | docs = ["pdoc3 (==0.10.0)"] 279 | bigquery = ["google-cloud-bigquery (<=3.3.5)"] 280 | dynamodb = ["boto3 (>=1.15.0)"] 281 | 282 | [[package]] 283 | name = "certifi" 284 | version = "2022.12.7" 285 | description = "Python package for providing Mozilla's CA Bundle." 286 | category = "main" 287 | optional = false 288 | python-versions = ">=3.6" 289 | 290 | [[package]] 291 | name = "cffi" 292 | version = "1.15.1" 293 | description = "Foreign Function Interface for Python calling C code." 294 | category = "main" 295 | optional = false 296 | python-versions = "*" 297 | 298 | [package.dependencies] 299 | pycparser = "*" 300 | 301 | [[package]] 302 | name = "charset-normalizer" 303 | version = "3.1.0" 304 | description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." 305 | category = "main" 306 | optional = false 307 | python-versions = ">=3.7.0" 308 | 309 | [[package]] 310 | name = "click" 311 | version = "8.1.3" 312 | description = "Composable command line interface toolkit" 313 | category = "main" 314 | optional = false 315 | python-versions = ">=3.7" 316 | 317 | [package.dependencies] 318 | colorama = {version = "*", markers = "platform_system == \"Windows\""} 319 | 320 | [[package]] 321 | name = "colorama" 322 | version = "0.4.6" 323 | description = "Cross-platform colored terminal text." 324 | category = "main" 325 | optional = false 326 | python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" 327 | 328 | [[package]] 329 | name = "comm" 330 | version = "0.1.2" 331 | description = "Jupyter Python Comm implementation, for usage in ipykernel, xeus-python etc." 332 | category = "main" 333 | optional = false 334 | python-versions = ">=3.6" 335 | 336 | [package.dependencies] 337 | traitlets = ">=5.3" 338 | 339 | [package.extras] 340 | test = ["pytest"] 341 | 342 | [[package]] 343 | name = "confluent-kafka" 344 | version = "1.8.2" 345 | description = "Confluent's Python client for Apache Kafka" 346 | category = "main" 347 | optional = false 348 | python-versions = "*" 349 | 350 | [package.extras] 351 | avro = ["requests", "fastavro (>=0.23.0,<1.0)", "avro (==1.10.0)", "fastavro (>=1.0)", "avro-python3 (==1.10.0)"] 352 | dev = ["pytest-timeout", "flake8", "requests", "pytest (==4.6.4)", "fastavro (>=0.23.0,<1.0)", "avro (==1.10.0)", "fastavro (>=1.0)", "avro-python3 (==1.10.0)", "pytest"] 353 | doc = ["sphinx", "sphinx-rtd-theme", "requests", "fastavro (>=0.23.0,<1.0)", "avro (==1.10.0)", "fastavro (>=1.0)", "avro-python3 (==1.10.0)"] 354 | json = ["jsonschema", "requests", "pyrsistent (==0.16.1)", "pyrsistent"] 355 | protobuf = ["protobuf", "requests"] 356 | schema-registry = ["requests"] 357 | 358 | [[package]] 359 | name = "cryptography" 360 | version = "39.0.2" 361 | description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." 362 | category = "main" 363 | optional = false 364 | python-versions = ">=3.6" 365 | 366 | [package.dependencies] 367 | cffi = ">=1.12" 368 | 369 | [package.extras] 370 | docs = ["sphinx (>=5.3.0)", "sphinx-rtd-theme (>=1.1.1)"] 371 | docstest = ["pyenchant (>=1.6.11)", "twine (>=1.12.0)", "sphinxcontrib-spelling (>=4.0.1)"] 372 | pep8test = ["black", "ruff", "mypy", "types-pytz", "types-requests", "check-manifest"] 373 | sdist = ["setuptools-rust (>=0.11.4)"] 374 | ssh = ["bcrypt (>=3.1.5)"] 375 | test = ["pytest (>=6.2.0)", "pytest-shard (>=0.1.2)", "pytest-benchmark", "pytest-cov", "pytest-subtests", "pytest-xdist", "pretend", "iso8601", "pytz", "hypothesis (>=1.11.4,!=3.79.2)"] 376 | test-randomorder = ["pytest-randomly"] 377 | tox = ["tox"] 378 | 379 | [[package]] 380 | name = "debugpy" 381 | version = "1.6.6" 382 | description = "An implementation of the Debug Adapter Protocol for Python" 383 | category = "main" 384 | optional = false 385 | python-versions = ">=3.7" 386 | 387 | [[package]] 388 | name = "decorator" 389 | version = "5.1.1" 390 | description = "Decorators for Humans" 391 | category = "main" 392 | optional = false 393 | python-versions = ">=3.5" 394 | 395 | [[package]] 396 | name = "defusedxml" 397 | version = "0.7.1" 398 | description = "XML bomb protection for Python stdlib modules" 399 | category = "dev" 400 | optional = false 401 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" 402 | 403 | [[package]] 404 | name = "dill" 405 | version = "0.3.6" 406 | description = "serialize all of python" 407 | category = "main" 408 | optional = false 409 | python-versions = ">=3.7" 410 | 411 | [package.extras] 412 | graph = ["objgraph (>=1.7.2)"] 413 | 414 | [[package]] 415 | name = "entrypoints" 416 | version = "0.4" 417 | description = "Discover and load entry points from installed packages." 418 | category = "main" 419 | optional = false 420 | python-versions = ">=3.6" 421 | 422 | [[package]] 423 | name = "executing" 424 | version = "1.2.0" 425 | description = "Get the currently executing AST node of a frame, and other information" 426 | category = "main" 427 | optional = false 428 | python-versions = "*" 429 | 430 | [package.extras] 431 | tests = ["asttokens", "pytest", "littleutils", "rich"] 432 | 433 | [[package]] 434 | name = "fastavro" 435 | version = "1.4.11" 436 | description = "Fast read/write of AVRO files" 437 | category = "main" 438 | optional = false 439 | python-versions = ">=3.7" 440 | 441 | [package.extras] 442 | codecs = ["python-snappy", "zstandard", "lz4"] 443 | lz4 = ["lz4"] 444 | snappy = ["python-snappy"] 445 | zstandard = ["zstandard"] 446 | 447 | [[package]] 448 | name = "fastjsonschema" 449 | version = "2.16.3" 450 | description = "Fastest Python implementation of JSON schema" 451 | category = "main" 452 | optional = false 453 | python-versions = "*" 454 | 455 | [package.extras] 456 | devel = ["colorama", "jsonschema", "json-spec", "pylint", "pytest", "pytest-benchmark", "pytest-cache", "validictory"] 457 | 458 | [[package]] 459 | name = "fqdn" 460 | version = "1.5.1" 461 | description = "Validates fully-qualified domain names against RFC 1123, so that they are acceptable to modern bowsers" 462 | category = "dev" 463 | optional = false 464 | python-versions = ">=2.7, !=3.0, !=3.1, !=3.2, !=3.3, !=3.4, <4" 465 | 466 | [[package]] 467 | name = "furl" 468 | version = "2.1.3" 469 | description = "URL manipulation made simple." 470 | category = "main" 471 | optional = false 472 | python-versions = "*" 473 | 474 | [package.dependencies] 475 | orderedmultidict = ">=1.0.1" 476 | six = ">=1.8.0" 477 | 478 | [[package]] 479 | name = "future" 480 | version = "0.18.3" 481 | description = "Clean single-source support for Python 3 and 2" 482 | category = "main" 483 | optional = false 484 | python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" 485 | 486 | [[package]] 487 | name = "great-expectations" 488 | version = "0.14.12" 489 | description = "Always know what to expect from your data." 490 | category = "main" 491 | optional = false 492 | python-versions = "*" 493 | 494 | [package.dependencies] 495 | altair = ">=4.0.0,<5" 496 | Click = ">=7.1.2" 497 | colorama = ">=0.4.3" 498 | cryptography = ">=3.2" 499 | importlib-metadata = ">=1.7.0" 500 | ipywidgets = ">=7.5.1" 501 | jinja2 = ">=2.10,<3.1.0" 502 | jsonpatch = ">=1.22" 503 | jsonschema = ">=2.5.1" 504 | mistune = ">=0.8.4,<2.0.0" 505 | nbformat = ">=5.0" 506 | numpy = ">=1.14.1" 507 | packaging = "*" 508 | pandas = ">=0.23.0" 509 | pyparsing = ">=2.4,<3" 510 | python-dateutil = ">=2.8.1" 511 | pytz = ">=2021.3" 512 | requests = ">=2.20" 513 | "ruamel.yaml" = ">=0.16,<0.17.18" 514 | scipy = ">=0.19.0" 515 | termcolor = ">=1.1.0" 516 | tqdm = ">=4.59.0" 517 | typing-extensions = ">=3.10.0.0" 518 | tzlocal = ">=1.2" 519 | urllib3 = ">=1.25.4,<1.27" 520 | 521 | [package.extras] 522 | arrow = ["feather-format (>=0.4.1)", "pyarrow (>=0.12.0)"] 523 | athena = ["pyathena (>=1.11)"] 524 | aws_secrets = ["boto3 (==1.17.106)"] 525 | azure = ["azure-identity (>=1.0.0)", "azure-keyvault-secrets (>=4.0.0)", "azure-storage-blob (>=12.5.0)"] 526 | azure_secrets = ["azure-identity (>=1.0.0)", "azure-keyvault-secrets (>=4.0.0)", "azure-storage-blob (>=12.5.0)"] 527 | bigquery = ["gcsfs (>=0.5.1)", "google-cloud-secret-manager (>=1.0.0)", "google-cloud-storage (>=1.28.0)", "sqlalchemy-bigquery (>=1.3.0)"] 528 | dremio = ["pyarrow (>=0.12.0)", "pyodbc (>=4.0.30)", "sqlalchemy-dremio (>=1.2.1)"] 529 | excel = ["openpyxl (>=3.0.7)", "xlrd (>=1.1.0,<2.0.0)"] 530 | gcp = ["gcsfs (>=0.5.1)", "google-cloud-secret-manager (>=1.0.0)", "google-cloud-storage (>=1.28.0)", "sqlalchemy-bigquery (>=1.3.0)"] 531 | mssql = ["pyodbc (>=4.0.30)"] 532 | mysql = ["PyMySQL (>=0.9.3,<0.10)"] 533 | pagerduty = ["pypd (==1.1.0)"] 534 | postgresql = ["psycopg2-binary (>=2.7.6)"] 535 | redshift = ["psycopg2-binary (>=2.7.6)", "sqlalchemy-redshift (>=0.7.7)"] 536 | s3 = ["boto3 (==1.17.106)"] 537 | snowflake = ["snowflake-connector-python (==2.5.0)", "snowflake-sqlalchemy (>=1.2.3)"] 538 | spark = ["pyspark (>=2.3.2)"] 539 | sqlalchemy = ["sqlalchemy (>=1.3.18,<1.4.10)"] 540 | teradata = ["teradatasqlalchemy (==17.0.0.1)"] 541 | 542 | [[package]] 543 | name = "greenlet" 544 | version = "2.0.2" 545 | description = "Lightweight in-process concurrent programming" 546 | category = "main" 547 | optional = false 548 | python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*" 549 | 550 | [package.extras] 551 | docs = ["sphinx", "docutils (<0.18)"] 552 | test = ["objgraph", "psutil"] 553 | 554 | [[package]] 555 | name = "hopsworks" 556 | version = "3.0.5" 557 | description = "HOPSWORKS: An environment independent client to interact with the Hopsworks API" 558 | category = "main" 559 | optional = false 560 | python-versions = "*" 561 | 562 | [package.dependencies] 563 | boto3 = "*" 564 | furl = "*" 565 | hsfs = {version = ">=3.0.0,<3.1.0", extras = ["python"]} 566 | hsml = ">=3.0.0,<3.1.0" 567 | mock = "*" 568 | pyhumps = "1.6.1" 569 | pyjks = "*" 570 | requests = "*" 571 | tqdm = "*" 572 | 573 | [package.extras] 574 | dev = ["black", "flake8", "pytest"] 575 | docs = ["keras_autodoc @ git+https://git@github.com/moritzmeister/keras-autodoc@split-tags-properties", "markdown-include", "markdown (==3.3.7)", "mike (==1.1.2)", "mkdocs-material (==8.2.8)", "mkdocs (==1.3.0)", "pymdown-extensions", "sphinx (==3.5.4)"] 576 | 577 | [[package]] 578 | name = "hsfs" 579 | version = "3.0.5" 580 | description = "HSFS: An environment independent client to interact with the Hopsworks Featurestore" 581 | category = "main" 582 | optional = false 583 | python-versions = ">=3.7,<3.10" 584 | 585 | [package.dependencies] 586 | avro = "1.10.2" 587 | boto3 = "*" 588 | confluent-kafka = {version = "1.8.2", optional = true, markers = "extra == \"python\""} 589 | fastavro = {version = "1.4.11", optional = true, markers = "extra == \"python\""} 590 | furl = "*" 591 | great_expectations = "0.14.12" 592 | markupsafe = "<2.1.0" 593 | mock = "*" 594 | numpy = "*" 595 | pandas = ">=1.2.0" 596 | pyarrow = {version = "*", optional = true, markers = "extra == \"python\""} 597 | pyhopshive = {version = "*", extras = ["thrift"], optional = true, markers = "extra == \"python\""} 598 | pyhumps = "1.6.1" 599 | pyjks = "*" 600 | PyMySQL = {version = "*", extras = ["rsa"]} 601 | requests = "*" 602 | sqlalchemy = "*" 603 | tqdm = {version = "*", optional = true, markers = "extra == \"python\""} 604 | 605 | [package.extras] 606 | dev = ["black", "flake8", "moto", "pytest (==7.1.2)"] 607 | docs = ["keras_autodoc @ git+https://git@github.com/moritzmeister/keras-autodoc@split-tags-properties", "markdown-include", "markdown (==3.3.7)", "mike (==1.1.2)", "mkdocs-jupyter (==0.21.0)", "mkdocs-material (==8.2.8)", "mkdocs (==1.3.0)", "pymdown-extensions", "sphinx (==3.5.4)"] 608 | hive = ["confluent-kafka (==1.8.2)", "fastavro (==1.4.11)", "pyarrow", "pyhopshive"] 609 | python = ["confluent-kafka (==1.8.2)", "fastavro (==1.4.11)", "pyarrow", "pyhopshive", "tqdm"] 610 | 611 | [[package]] 612 | name = "hsml" 613 | version = "3.0.3" 614 | description = "HSML: An environment independent client to interact with the Hopsworks Model Registry" 615 | category = "main" 616 | optional = false 617 | python-versions = "*" 618 | 619 | [package.dependencies] 620 | boto3 = "*" 621 | furl = "*" 622 | mock = "*" 623 | numpy = "*" 624 | pandas = "*" 625 | pyhumps = "1.6.1" 626 | pyjks = "*" 627 | requests = "*" 628 | tqdm = "*" 629 | 630 | [package.extras] 631 | dev = ["black", "flake8", "pytest"] 632 | docs = ["keras_autodoc @ git+https://git@github.com/logicalclocks/keras-autodoc@split-tags-properties", "markdown-include", "markdown (==3.3.7)", "mike (==1.1.2)", "mkdocs-material (==8.2.8)", "mkdocs (==1.3.0)", "pymdown-extensions", "sphinx (==3.5.4)"] 633 | 634 | [[package]] 635 | name = "idna" 636 | version = "3.4" 637 | description = "Internationalized Domain Names in Applications (IDNA)" 638 | category = "main" 639 | optional = false 640 | python-versions = ">=3.5" 641 | 642 | [[package]] 643 | name = "importlib-metadata" 644 | version = "6.0.0" 645 | description = "Read metadata from Python packages" 646 | category = "main" 647 | optional = false 648 | python-versions = ">=3.7" 649 | 650 | [package.dependencies] 651 | zipp = ">=0.5" 652 | 653 | [package.extras] 654 | docs = ["sphinx (>=3.5)", "jaraco.packaging (>=9)", "rst.linker (>=1.9)", "furo", "sphinx-lint", "jaraco.tidelift (>=1.4)"] 655 | perf = ["ipython"] 656 | testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "flake8 (<5)", "pytest-cov", "pytest-enabler (>=1.3)", "packaging", "pyfakefs", "flufl.flake8", "pytest-perf (>=0.9.2)", "pytest-black (>=0.3.7)", "pytest-mypy (>=0.9.1)", "pytest-flake8", "importlib-resources (>=1.3)"] 657 | 658 | [[package]] 659 | name = "ipykernel" 660 | version = "6.21.3" 661 | description = "IPython Kernel for Jupyter" 662 | category = "main" 663 | optional = false 664 | python-versions = ">=3.8" 665 | 666 | [package.dependencies] 667 | appnope = {version = "*", markers = "platform_system == \"Darwin\""} 668 | comm = ">=0.1.1" 669 | debugpy = ">=1.6.5" 670 | ipython = ">=7.23.1" 671 | jupyter-client = ">=6.1.12" 672 | jupyter-core = ">=4.12,<5.0.0 || >=5.1.0" 673 | matplotlib-inline = ">=0.1" 674 | nest-asyncio = "*" 675 | packaging = "*" 676 | psutil = "*" 677 | pyzmq = ">=20" 678 | tornado = ">=6.1" 679 | traitlets = ">=5.4.0" 680 | 681 | [package.extras] 682 | cov = ["coverage", "curio", "matplotlib", "pytest-cov", "trio"] 683 | docs = ["myst-parser", "pydata-sphinx-theme", "sphinx", "sphinx-autodoc-typehints", "sphinxcontrib-github-alt", "sphinxcontrib-spelling", "trio"] 684 | pyqt5 = ["pyqt5"] 685 | pyside6 = ["pyside6"] 686 | test = ["flaky", "ipyparallel", "pre-commit", "pytest-asyncio", "pytest-cov", "pytest-timeout", "pytest (>=7.0)"] 687 | 688 | [[package]] 689 | name = "ipython" 690 | version = "8.11.0" 691 | description = "IPython: Productive Interactive Computing" 692 | category = "main" 693 | optional = false 694 | python-versions = ">=3.8" 695 | 696 | [package.dependencies] 697 | appnope = {version = "*", markers = "sys_platform == \"darwin\""} 698 | backcall = "*" 699 | colorama = {version = "*", markers = "sys_platform == \"win32\""} 700 | decorator = "*" 701 | jedi = ">=0.16" 702 | matplotlib-inline = "*" 703 | pexpect = {version = ">4.3", markers = "sys_platform != \"win32\""} 704 | pickleshare = "*" 705 | prompt-toolkit = ">=3.0.30,<3.0.37 || >3.0.37,<3.1.0" 706 | pygments = ">=2.4.0" 707 | stack-data = "*" 708 | traitlets = ">=5" 709 | 710 | [package.extras] 711 | all = ["black", "ipykernel", "setuptools (>=18.5)", "sphinx (>=1.3)", "sphinx-rtd-theme", "docrepr", "matplotlib", "stack-data", "pytest (<7)", "typing-extensions", "pytest (<7.1)", "pytest-asyncio", "testpath", "nbconvert", "nbformat", "ipywidgets", "notebook", "ipyparallel", "qtconsole", "curio", "matplotlib (!=3.2.0)", "numpy (>=1.21)", "pandas", "trio"] 712 | black = ["black"] 713 | doc = ["ipykernel", "setuptools (>=18.5)", "sphinx (>=1.3)", "sphinx-rtd-theme", "docrepr", "matplotlib", "stack-data", "pytest (<7)", "typing-extensions", "pytest (<7.1)", "pytest-asyncio", "testpath"] 714 | kernel = ["ipykernel"] 715 | nbconvert = ["nbconvert"] 716 | nbformat = ["nbformat"] 717 | notebook = ["ipywidgets", "notebook"] 718 | parallel = ["ipyparallel"] 719 | qtconsole = ["qtconsole"] 720 | test = ["pytest (<7.1)", "pytest-asyncio", "testpath"] 721 | test_extra = ["pytest (<7.1)", "pytest-asyncio", "testpath", "curio", "matplotlib (!=3.2.0)", "nbformat", "numpy (>=1.21)", "pandas", "trio"] 722 | 723 | [[package]] 724 | name = "ipython-genutils" 725 | version = "0.2.0" 726 | description = "Vestigial utilities from IPython" 727 | category = "dev" 728 | optional = false 729 | python-versions = "*" 730 | 731 | [[package]] 732 | name = "ipywidgets" 733 | version = "8.0.4" 734 | description = "Jupyter interactive widgets" 735 | category = "main" 736 | optional = false 737 | python-versions = ">=3.7" 738 | 739 | [package.dependencies] 740 | ipykernel = ">=4.5.1" 741 | ipython = ">=6.1.0" 742 | jupyterlab-widgets = ">=3.0,<4.0" 743 | traitlets = ">=4.3.1" 744 | widgetsnbextension = ">=4.0,<5.0" 745 | 746 | [package.extras] 747 | test = ["jsonschema", "pytest (>=3.6.0)", "pytest-cov", "pytz"] 748 | 749 | [[package]] 750 | name = "isoduration" 751 | version = "20.11.0" 752 | description = "Operations with ISO 8601 durations" 753 | category = "dev" 754 | optional = false 755 | python-versions = ">=3.7" 756 | 757 | [package.dependencies] 758 | arrow = ">=0.15.0" 759 | 760 | [[package]] 761 | name = "isort" 762 | version = "5.12.0" 763 | description = "A Python utility / library to sort Python imports." 764 | category = "dev" 765 | optional = false 766 | python-versions = ">=3.8.0" 767 | 768 | [package.extras] 769 | colors = ["colorama (>=0.4.3)"] 770 | requirements-deprecated-finder = ["pip-api", "pipreqs"] 771 | pipfile-deprecated-finder = ["pip-shims (>=0.5.2)", "pipreqs", "requirementslib"] 772 | plugins = ["setuptools"] 773 | 774 | [[package]] 775 | name = "javaobj-py3" 776 | version = "0.4.3" 777 | description = "Module for serializing and de-serializing Java objects." 778 | category = "main" 779 | optional = false 780 | python-versions = "*" 781 | 782 | [[package]] 783 | name = "jedi" 784 | version = "0.18.2" 785 | description = "An autocompletion tool for Python that can be used for text editors." 786 | category = "main" 787 | optional = false 788 | python-versions = ">=3.6" 789 | 790 | [package.dependencies] 791 | parso = ">=0.8.0,<0.9.0" 792 | 793 | [package.extras] 794 | docs = ["Jinja2 (==2.11.3)", "MarkupSafe (==1.1.1)", "Pygments (==2.8.1)", "alabaster (==0.7.12)", "babel (==2.9.1)", "chardet (==4.0.0)", "commonmark (==0.8.1)", "docutils (==0.17.1)", "future (==0.18.2)", "idna (==2.10)", "imagesize (==1.2.0)", "mock (==1.0.1)", "packaging (==20.9)", "pyparsing (==2.4.7)", "pytz (==2021.1)", "readthedocs-sphinx-ext (==2.1.4)", "recommonmark (==0.5.0)", "requests (==2.25.1)", "six (==1.15.0)", "snowballstemmer (==2.1.0)", "sphinx-rtd-theme (==0.4.3)", "sphinx (==1.8.5)", "sphinxcontrib-serializinghtml (==1.1.4)", "sphinxcontrib-websupport (==1.2.4)", "urllib3 (==1.26.4)"] 795 | qa = ["flake8 (==3.8.3)", "mypy (==0.782)"] 796 | testing = ["Django (<3.1)", "attrs", "colorama", "docopt", "pytest (<7.0.0)"] 797 | 798 | [[package]] 799 | name = "jinja2" 800 | version = "3.0.3" 801 | description = "A very fast and expressive template engine." 802 | category = "main" 803 | optional = false 804 | python-versions = ">=3.6" 805 | 806 | [package.dependencies] 807 | MarkupSafe = ">=2.0" 808 | 809 | [package.extras] 810 | i18n = ["Babel (>=2.7)"] 811 | 812 | [[package]] 813 | name = "jmespath" 814 | version = "1.0.1" 815 | description = "JSON Matching Expressions" 816 | category = "main" 817 | optional = false 818 | python-versions = ">=3.7" 819 | 820 | [[package]] 821 | name = "jsonpatch" 822 | version = "1.32" 823 | description = "Apply JSON-Patches (RFC 6902)" 824 | category = "main" 825 | optional = false 826 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" 827 | 828 | [package.dependencies] 829 | jsonpointer = ">=1.9" 830 | 831 | [[package]] 832 | name = "jsonpointer" 833 | version = "2.3" 834 | description = "Identify specific nodes in a JSON document (RFC 6901)" 835 | category = "main" 836 | optional = false 837 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" 838 | 839 | [[package]] 840 | name = "jsonschema" 841 | version = "4.17.3" 842 | description = "An implementation of JSON Schema validation for Python" 843 | category = "main" 844 | optional = false 845 | python-versions = ">=3.7" 846 | 847 | [package.dependencies] 848 | attrs = ">=17.4.0" 849 | fqdn = {version = "*", optional = true, markers = "extra == \"format-nongpl\""} 850 | idna = {version = "*", optional = true, markers = "extra == \"format-nongpl\""} 851 | isoduration = {version = "*", optional = true, markers = "extra == \"format-nongpl\""} 852 | jsonpointer = {version = ">1.13", optional = true, markers = "extra == \"format-nongpl\""} 853 | pyrsistent = ">=0.14.0,<0.17.0 || >0.17.0,<0.17.1 || >0.17.1,<0.17.2 || >0.17.2" 854 | rfc3339-validator = {version = "*", optional = true, markers = "extra == \"format-nongpl\""} 855 | rfc3986-validator = {version = ">0.1.0", optional = true, markers = "extra == \"format-nongpl\""} 856 | uri-template = {version = "*", optional = true, markers = "extra == \"format-nongpl\""} 857 | webcolors = {version = ">=1.11", optional = true, markers = "extra == \"format-nongpl\""} 858 | 859 | [package.extras] 860 | format = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3987", "uri-template", "webcolors (>=1.11)"] 861 | format-nongpl = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3986-validator (>0.1.0)", "uri-template", "webcolors (>=1.11)"] 862 | 863 | [[package]] 864 | name = "jupyter" 865 | version = "1.0.0" 866 | description = "Jupyter metapackage. Install all the Jupyter components in one go." 867 | category = "dev" 868 | optional = false 869 | python-versions = "*" 870 | 871 | [package.dependencies] 872 | ipykernel = "*" 873 | ipywidgets = "*" 874 | jupyter-console = "*" 875 | nbconvert = "*" 876 | notebook = "*" 877 | qtconsole = "*" 878 | 879 | [[package]] 880 | name = "jupyter-client" 881 | version = "8.0.3" 882 | description = "Jupyter protocol implementation and client libraries" 883 | category = "main" 884 | optional = false 885 | python-versions = ">=3.8" 886 | 887 | [package.dependencies] 888 | importlib-metadata = {version = ">=4.8.3", markers = "python_version < \"3.10\""} 889 | jupyter-core = ">=4.12,<5.0.0 || >=5.1.0" 890 | python-dateutil = ">=2.8.2" 891 | pyzmq = ">=23.0" 892 | tornado = ">=6.2" 893 | traitlets = ">=5.3" 894 | 895 | [package.extras] 896 | docs = ["ipykernel", "myst-parser", "pydata-sphinx-theme", "sphinx-autodoc-typehints", "sphinx (>=4)", "sphinxcontrib-github-alt", "sphinxcontrib-spelling"] 897 | test = ["codecov", "coverage", "ipykernel (>=6.14)", "mypy", "paramiko", "pre-commit", "pytest", "pytest-cov", "pytest-jupyter[client] (>=0.4.1)", "pytest-timeout"] 898 | 899 | [[package]] 900 | name = "jupyter-console" 901 | version = "6.6.3" 902 | description = "Jupyter terminal console" 903 | category = "dev" 904 | optional = false 905 | python-versions = ">=3.7" 906 | 907 | [package.dependencies] 908 | ipykernel = ">=6.14" 909 | ipython = "*" 910 | jupyter-client = ">=7.0.0" 911 | jupyter-core = ">=4.12,<5.0.0 || >=5.1.0" 912 | prompt-toolkit = ">=3.0.30" 913 | pygments = "*" 914 | pyzmq = ">=17" 915 | traitlets = ">=5.4" 916 | 917 | [package.extras] 918 | test = ["flaky", "pexpect", "pytest"] 919 | 920 | [[package]] 921 | name = "jupyter-core" 922 | version = "5.2.0" 923 | description = "Jupyter core package. A base package on which Jupyter projects rely." 924 | category = "main" 925 | optional = false 926 | python-versions = ">=3.8" 927 | 928 | [package.dependencies] 929 | platformdirs = ">=2.5" 930 | pywin32 = {version = ">=1.0", markers = "sys_platform == \"win32\" and platform_python_implementation != \"PyPy\""} 931 | traitlets = ">=5.3" 932 | 933 | [package.extras] 934 | docs = ["myst-parser", "sphinx-autodoc-typehints", "sphinxcontrib-github-alt", "sphinxcontrib-spelling", "traitlets"] 935 | test = ["ipykernel", "pre-commit", "pytest", "pytest-cov", "pytest-timeout"] 936 | 937 | [[package]] 938 | name = "jupyter-events" 939 | version = "0.6.3" 940 | description = "Jupyter Event System library" 941 | category = "dev" 942 | optional = false 943 | python-versions = ">=3.7" 944 | 945 | [package.dependencies] 946 | jsonschema = {version = ">=3.2.0", extras = ["format-nongpl"]} 947 | python-json-logger = ">=2.0.4" 948 | pyyaml = ">=5.3" 949 | rfc3339-validator = "*" 950 | rfc3986-validator = ">=0.1.1" 951 | traitlets = ">=5.3" 952 | 953 | [package.extras] 954 | cli = ["click", "rich"] 955 | docs = ["jupyterlite-sphinx", "myst-parser", "pydata-sphinx-theme", "sphinxcontrib-spelling"] 956 | test = ["click", "coverage", "pre-commit", "pytest-asyncio (>=0.19.0)", "pytest-console-scripts", "pytest-cov", "pytest (>=7.0)", "rich"] 957 | 958 | [[package]] 959 | name = "jupyter-server" 960 | version = "2.4.0" 961 | description = "The backend—i.e. core services, APIs, and REST endpoints—to Jupyter web applications." 962 | category = "dev" 963 | optional = false 964 | python-versions = ">=3.8" 965 | 966 | [package.dependencies] 967 | anyio = ">=3.1.0" 968 | argon2-cffi = "*" 969 | jinja2 = "*" 970 | jupyter-client = ">=7.4.4" 971 | jupyter-core = ">=4.12,<5.0.0 || >=5.1.0" 972 | jupyter-events = ">=0.4.0" 973 | jupyter-server-terminals = "*" 974 | nbconvert = ">=6.4.4" 975 | nbformat = ">=5.3.0" 976 | packaging = "*" 977 | prometheus-client = "*" 978 | pywinpty = {version = "*", markers = "os_name == \"nt\""} 979 | pyzmq = ">=24" 980 | send2trash = "*" 981 | terminado = ">=0.8.3" 982 | tornado = ">=6.2.0" 983 | traitlets = ">=5.6.0" 984 | websocket-client = "*" 985 | 986 | [package.extras] 987 | docs = ["docutils (<0.20)", "ipykernel", "jinja2", "jupyter-client", "jupyter-server", "mistune (<1.0.0)", "myst-parser", "nbformat", "prometheus-client", "pydata-sphinx-theme", "send2trash", "sphinx-autodoc-typehints", "sphinxcontrib-github-alt", "sphinxcontrib-openapi", "sphinxcontrib-spelling", "sphinxemoji", "tornado", "typing-extensions"] 988 | test = ["ipykernel", "pre-commit", "pytest-console-scripts", "pytest-jupyter[server] (>=0.4)", "pytest-timeout", "pytest (>=7.0)", "requests"] 989 | 990 | [[package]] 991 | name = "jupyter-server-terminals" 992 | version = "0.4.4" 993 | description = "A Jupyter Server Extension Providing Terminals." 994 | category = "dev" 995 | optional = false 996 | python-versions = ">=3.8" 997 | 998 | [package.dependencies] 999 | pywinpty = {version = ">=2.0.3", markers = "os_name == \"nt\""} 1000 | terminado = ">=0.8.3" 1001 | 1002 | [package.extras] 1003 | docs = ["jinja2", "jupyter-server", "mistune (<3.0)", "myst-parser", "nbformat", "packaging", "pydata-sphinx-theme", "sphinxcontrib-github-alt", "sphinxcontrib-openapi", "sphinxcontrib-spelling", "sphinxemoji", "tornado"] 1004 | test = ["coverage", "jupyter-server (>=2.0.0)", "pytest-cov", "pytest-jupyter[server] (>=0.5.3)", "pytest-timeout", "pytest (>=7.0)"] 1005 | 1006 | [[package]] 1007 | name = "jupyterlab-pygments" 1008 | version = "0.2.2" 1009 | description = "Pygments theme using JupyterLab CSS variables" 1010 | category = "dev" 1011 | optional = false 1012 | python-versions = ">=3.7" 1013 | 1014 | [[package]] 1015 | name = "jupyterlab-widgets" 1016 | version = "3.0.5" 1017 | description = "Jupyter interactive widgets for JupyterLab" 1018 | category = "main" 1019 | optional = false 1020 | python-versions = ">=3.7" 1021 | 1022 | [[package]] 1023 | name = "lazy-object-proxy" 1024 | version = "1.9.0" 1025 | description = "A fast and thorough lazy object proxy." 1026 | category = "dev" 1027 | optional = false 1028 | python-versions = ">=3.7" 1029 | 1030 | [[package]] 1031 | name = "lxml" 1032 | version = "4.9.2" 1033 | description = "Powerful and Pythonic XML processing library combining libxml2/libxslt with the ElementTree API." 1034 | category = "dev" 1035 | optional = false 1036 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, != 3.4.*" 1037 | 1038 | [package.extras] 1039 | cssselect = ["cssselect (>=0.7)"] 1040 | html5 = ["html5lib"] 1041 | htmlsoup = ["beautifulsoup4"] 1042 | source = ["Cython (>=0.29.7)"] 1043 | 1044 | [[package]] 1045 | name = "markupsafe" 1046 | version = "2.0.1" 1047 | description = "Safely add untrusted strings to HTML/XML markup." 1048 | category = "main" 1049 | optional = false 1050 | python-versions = ">=3.6" 1051 | 1052 | [[package]] 1053 | name = "matplotlib-inline" 1054 | version = "0.1.6" 1055 | description = "Inline Matplotlib backend for Jupyter" 1056 | category = "main" 1057 | optional = false 1058 | python-versions = ">=3.5" 1059 | 1060 | [package.dependencies] 1061 | traitlets = "*" 1062 | 1063 | [[package]] 1064 | name = "mccabe" 1065 | version = "0.7.0" 1066 | description = "McCabe checker, plugin for flake8" 1067 | category = "dev" 1068 | optional = false 1069 | python-versions = ">=3.6" 1070 | 1071 | [[package]] 1072 | name = "mistune" 1073 | version = "0.8.4" 1074 | description = "The fastest markdown parser in pure Python" 1075 | category = "main" 1076 | optional = false 1077 | python-versions = "*" 1078 | 1079 | [[package]] 1080 | name = "mock" 1081 | version = "5.0.1" 1082 | description = "Rolling backport of unittest.mock for all Pythons" 1083 | category = "main" 1084 | optional = false 1085 | python-versions = ">=3.6" 1086 | 1087 | [package.extras] 1088 | build = ["twine", "wheel", "blurb"] 1089 | docs = ["sphinx"] 1090 | test = ["pytest", "pytest-cov"] 1091 | 1092 | [[package]] 1093 | name = "more-itertools" 1094 | version = "9.1.0" 1095 | description = "More routines for operating on iterables, beyond itertools" 1096 | category = "dev" 1097 | optional = false 1098 | python-versions = ">=3.7" 1099 | 1100 | [[package]] 1101 | name = "multiprocess" 1102 | version = "0.70.14" 1103 | description = "better multiprocessing and multithreading in python" 1104 | category = "main" 1105 | optional = false 1106 | python-versions = ">=3.7" 1107 | 1108 | [package.dependencies] 1109 | dill = ">=0.3.6" 1110 | 1111 | [[package]] 1112 | name = "mypy-extensions" 1113 | version = "1.0.0" 1114 | description = "Type system extensions for programs checked with the mypy type checker." 1115 | category = "dev" 1116 | optional = false 1117 | python-versions = ">=3.5" 1118 | 1119 | [[package]] 1120 | name = "nbclassic" 1121 | version = "0.5.3" 1122 | description = "Jupyter Notebook as a Jupyter Server extension." 1123 | category = "dev" 1124 | optional = false 1125 | python-versions = ">=3.7" 1126 | 1127 | [package.dependencies] 1128 | argon2-cffi = "*" 1129 | ipykernel = "*" 1130 | ipython-genutils = "*" 1131 | jinja2 = "*" 1132 | jupyter-client = ">=6.1.1" 1133 | jupyter-core = ">=4.6.1" 1134 | jupyter-server = ">=1.8" 1135 | nbconvert = ">=5" 1136 | nbformat = "*" 1137 | nest-asyncio = ">=1.5" 1138 | notebook-shim = ">=0.1.0" 1139 | prometheus-client = "*" 1140 | pyzmq = ">=17" 1141 | Send2Trash = ">=1.8.0" 1142 | terminado = ">=0.8.3" 1143 | tornado = ">=6.1" 1144 | traitlets = ">=4.2.1" 1145 | 1146 | [package.extras] 1147 | docs = ["sphinx", "nbsphinx", "sphinxcontrib-github-alt", "sphinx-rtd-theme", "myst-parser"] 1148 | json-logging = ["json-logging"] 1149 | test = ["pytest", "coverage", "requests", "testpath", "nbval", "pytest-playwright", "pytest-cov", "pytest-jupyter", "pytest-tornasync", "requests-unixsocket"] 1150 | 1151 | [[package]] 1152 | name = "nbclient" 1153 | version = "0.7.2" 1154 | description = "A client library for executing notebooks. Formerly nbconvert's ExecutePreprocessor." 1155 | category = "dev" 1156 | optional = false 1157 | python-versions = ">=3.7.0" 1158 | 1159 | [package.dependencies] 1160 | jupyter-client = ">=6.1.12" 1161 | jupyter-core = ">=4.12,<5.0.0 || >=5.1.0" 1162 | nbformat = ">=5.1" 1163 | traitlets = ">=5.3" 1164 | 1165 | [package.extras] 1166 | dev = ["pre-commit"] 1167 | docs = ["autodoc-traits", "mock", "moto", "myst-parser", "nbclient", "sphinx-book-theme", "sphinx (>=1.7)"] 1168 | test = ["ipykernel", "ipython", "ipywidgets", "nbconvert (>=7.0.0)", "pytest-asyncio", "pytest-cov (>=4.0)", "pytest (>=7.0)", "testpath", "xmltodict"] 1169 | 1170 | [[package]] 1171 | name = "nbconvert" 1172 | version = "6.5.4" 1173 | description = "Converting Jupyter Notebooks" 1174 | category = "dev" 1175 | optional = false 1176 | python-versions = ">=3.7" 1177 | 1178 | [package.dependencies] 1179 | beautifulsoup4 = "*" 1180 | bleach = "*" 1181 | defusedxml = "*" 1182 | entrypoints = ">=0.2.2" 1183 | jinja2 = ">=3.0" 1184 | jupyter-core = ">=4.7" 1185 | jupyterlab-pygments = "*" 1186 | lxml = "*" 1187 | MarkupSafe = ">=2.0" 1188 | mistune = ">=0.8.1,<2" 1189 | nbclient = ">=0.5.0" 1190 | nbformat = ">=5.1" 1191 | packaging = "*" 1192 | pandocfilters = ">=1.4.1" 1193 | pygments = ">=2.4.1" 1194 | tinycss2 = "*" 1195 | traitlets = ">=5.0" 1196 | 1197 | [package.extras] 1198 | all = ["pytest", "pytest-cov", "pytest-dependency", "ipykernel", "ipywidgets (>=7)", "pre-commit", "pyppeteer (>=1,<1.1)", "tornado (>=6.1)", "sphinx (>=1.5.1)", "sphinx-rtd-theme", "nbsphinx (>=0.2.12)", "ipython"] 1199 | docs = ["sphinx (>=1.5.1)", "sphinx-rtd-theme", "nbsphinx (>=0.2.12)", "ipython"] 1200 | serve = ["tornado (>=6.1)"] 1201 | test = ["pytest", "pytest-cov", "pytest-dependency", "ipykernel", "ipywidgets (>=7)", "pre-commit", "pyppeteer (>=1,<1.1)"] 1202 | webpdf = ["pyppeteer (>=1,<1.1)"] 1203 | 1204 | [[package]] 1205 | name = "nbformat" 1206 | version = "5.7.3" 1207 | description = "The Jupyter Notebook format" 1208 | category = "main" 1209 | optional = false 1210 | python-versions = ">=3.7" 1211 | 1212 | [package.dependencies] 1213 | fastjsonschema = "*" 1214 | jsonschema = ">=2.6" 1215 | jupyter-core = "*" 1216 | traitlets = ">=5.1" 1217 | 1218 | [package.extras] 1219 | docs = ["myst-parser", "pydata-sphinx-theme", "sphinx", "sphinxcontrib-github-alt", "sphinxcontrib-spelling"] 1220 | test = ["pep440", "pre-commit", "pytest", "testpath"] 1221 | 1222 | [[package]] 1223 | name = "nest-asyncio" 1224 | version = "1.5.6" 1225 | description = "Patch asyncio to allow nested event loops" 1226 | category = "main" 1227 | optional = false 1228 | python-versions = ">=3.5" 1229 | 1230 | [[package]] 1231 | name = "notebook" 1232 | version = "6.5.3" 1233 | description = "A web-based notebook environment for interactive computing" 1234 | category = "dev" 1235 | optional = false 1236 | python-versions = ">=3.7" 1237 | 1238 | [package.dependencies] 1239 | argon2-cffi = "*" 1240 | ipykernel = "*" 1241 | ipython-genutils = "*" 1242 | jinja2 = "*" 1243 | jupyter-client = ">=5.3.4" 1244 | jupyter-core = ">=4.6.1" 1245 | nbclassic = ">=0.4.7" 1246 | nbconvert = ">=5" 1247 | nbformat = "*" 1248 | nest-asyncio = ">=1.5" 1249 | prometheus-client = "*" 1250 | pyzmq = ">=17" 1251 | Send2Trash = ">=1.8.0" 1252 | terminado = ">=0.8.3" 1253 | tornado = ">=6.1" 1254 | traitlets = ">=4.2.1" 1255 | 1256 | [package.extras] 1257 | docs = ["sphinx", "nbsphinx", "sphinxcontrib-github-alt", "sphinx-rtd-theme", "myst-parser"] 1258 | json-logging = ["json-logging"] 1259 | test = ["pytest", "coverage", "requests", "testpath", "nbval", "selenium (==4.1.5)", "pytest-cov", "requests-unixsocket"] 1260 | 1261 | [[package]] 1262 | name = "notebook-shim" 1263 | version = "0.2.2" 1264 | description = "A shim layer for notebook traits and config" 1265 | category = "dev" 1266 | optional = false 1267 | python-versions = ">=3.7" 1268 | 1269 | [package.dependencies] 1270 | jupyter-server = ">=1.8,<3" 1271 | 1272 | [package.extras] 1273 | test = ["pytest", "pytest-console-scripts", "pytest-tornasync"] 1274 | 1275 | [[package]] 1276 | name = "numpy" 1277 | version = "1.24.2" 1278 | description = "Fundamental package for array computing in Python" 1279 | category = "main" 1280 | optional = false 1281 | python-versions = ">=3.8" 1282 | 1283 | [[package]] 1284 | name = "orderedmultidict" 1285 | version = "1.0.1" 1286 | description = "Ordered Multivalue Dictionary" 1287 | category = "main" 1288 | optional = false 1289 | python-versions = "*" 1290 | 1291 | [package.dependencies] 1292 | six = ">=1.8.0" 1293 | 1294 | [[package]] 1295 | name = "packaging" 1296 | version = "23.0" 1297 | description = "Core utilities for Python packages" 1298 | category = "main" 1299 | optional = false 1300 | python-versions = ">=3.7" 1301 | 1302 | [[package]] 1303 | name = "pandas" 1304 | version = "1.5.3" 1305 | description = "Powerful data structures for data analysis, time series, and statistics" 1306 | category = "main" 1307 | optional = false 1308 | python-versions = ">=3.8" 1309 | 1310 | [package.dependencies] 1311 | numpy = {version = ">=1.20.3", markers = "python_version < \"3.10\""} 1312 | python-dateutil = ">=2.8.1" 1313 | pytz = ">=2020.1" 1314 | 1315 | [package.extras] 1316 | test = ["hypothesis (>=5.5.3)", "pytest (>=6.0)", "pytest-xdist (>=1.31)"] 1317 | 1318 | [[package]] 1319 | name = "pandocfilters" 1320 | version = "1.5.0" 1321 | description = "Utilities for writing pandoc filters in python" 1322 | category = "dev" 1323 | optional = false 1324 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" 1325 | 1326 | [[package]] 1327 | name = "parso" 1328 | version = "0.8.3" 1329 | description = "A Python Parser" 1330 | category = "main" 1331 | optional = false 1332 | python-versions = ">=3.6" 1333 | 1334 | [package.extras] 1335 | qa = ["flake8 (==3.8.3)", "mypy (==0.782)"] 1336 | testing = ["docopt", "pytest (<6.0.0)"] 1337 | 1338 | [[package]] 1339 | name = "pathspec" 1340 | version = "0.11.1" 1341 | description = "Utility library for gitignore style pattern matching of file paths." 1342 | category = "dev" 1343 | optional = false 1344 | python-versions = ">=3.7" 1345 | 1346 | [[package]] 1347 | name = "pexpect" 1348 | version = "4.8.0" 1349 | description = "Pexpect allows easy control of interactive console applications." 1350 | category = "main" 1351 | optional = false 1352 | python-versions = "*" 1353 | 1354 | [package.dependencies] 1355 | ptyprocess = ">=0.5" 1356 | 1357 | [[package]] 1358 | name = "pickleshare" 1359 | version = "0.7.5" 1360 | description = "Tiny 'shelve'-like database with concurrency support" 1361 | category = "main" 1362 | optional = false 1363 | python-versions = "*" 1364 | 1365 | [[package]] 1366 | name = "pip-tools" 1367 | version = "6.12.3" 1368 | description = "pip-tools keeps your pinned dependencies fresh." 1369 | category = "dev" 1370 | optional = false 1371 | python-versions = ">=3.7" 1372 | 1373 | [package.dependencies] 1374 | build = "*" 1375 | click = ">=8" 1376 | 1377 | [package.extras] 1378 | coverage = ["pytest-cov"] 1379 | testing = ["pytest (>=7.2.0)", "pytest-rerunfailures", "pytest-xdist", "flit-core (>=2,<4)", "poetry-core (>=1.0.0)"] 1380 | 1381 | [[package]] 1382 | name = "platformdirs" 1383 | version = "2.6.2" 1384 | description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." 1385 | category = "main" 1386 | optional = false 1387 | python-versions = ">=3.7" 1388 | 1389 | [package.extras] 1390 | docs = ["furo (>=2022.12.7)", "proselint (>=0.13)", "sphinx-autodoc-typehints (>=1.19.5)", "sphinx (>=5.3)"] 1391 | test = ["appdirs (==1.4.4)", "covdefaults (>=2.2.2)", "pytest-cov (>=4)", "pytest-mock (>=3.10)", "pytest (>=7.2)"] 1392 | 1393 | [[package]] 1394 | name = "pluggy" 1395 | version = "0.13.1" 1396 | description = "plugin and hook calling mechanisms for python" 1397 | category = "dev" 1398 | optional = false 1399 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" 1400 | 1401 | [package.extras] 1402 | dev = ["pre-commit", "tox"] 1403 | 1404 | [[package]] 1405 | name = "prometheus-client" 1406 | version = "0.16.0" 1407 | description = "Python client for the Prometheus monitoring system." 1408 | category = "dev" 1409 | optional = false 1410 | python-versions = ">=3.6" 1411 | 1412 | [package.extras] 1413 | twisted = ["twisted"] 1414 | 1415 | [[package]] 1416 | name = "prompt-toolkit" 1417 | version = "3.0.38" 1418 | description = "Library for building powerful interactive command lines in Python" 1419 | category = "main" 1420 | optional = false 1421 | python-versions = ">=3.7.0" 1422 | 1423 | [package.dependencies] 1424 | wcwidth = "*" 1425 | 1426 | [[package]] 1427 | name = "psutil" 1428 | version = "5.9.4" 1429 | description = "Cross-platform lib for process and system monitoring in Python." 1430 | category = "main" 1431 | optional = false 1432 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" 1433 | 1434 | [package.extras] 1435 | test = ["ipaddress", "mock", "enum34", "pywin32", "wmi"] 1436 | 1437 | [[package]] 1438 | name = "ptyprocess" 1439 | version = "0.7.0" 1440 | description = "Run a subprocess in a pseudo terminal" 1441 | category = "main" 1442 | optional = false 1443 | python-versions = "*" 1444 | 1445 | [[package]] 1446 | name = "pure-eval" 1447 | version = "0.2.2" 1448 | description = "Safely evaluate AST nodes without side effects" 1449 | category = "main" 1450 | optional = false 1451 | python-versions = "*" 1452 | 1453 | [package.extras] 1454 | tests = ["pytest"] 1455 | 1456 | [[package]] 1457 | name = "py" 1458 | version = "1.11.0" 1459 | description = "library with cross-python path, ini-parsing, io, code, log facilities" 1460 | category = "main" 1461 | optional = false 1462 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" 1463 | 1464 | [[package]] 1465 | name = "pyarrow" 1466 | version = "11.0.0" 1467 | description = "Python library for Apache Arrow" 1468 | category = "main" 1469 | optional = false 1470 | python-versions = ">=3.7" 1471 | 1472 | [package.dependencies] 1473 | numpy = ">=1.16.6" 1474 | 1475 | [[package]] 1476 | name = "pyasn1" 1477 | version = "0.4.8" 1478 | description = "ASN.1 types and codecs" 1479 | category = "main" 1480 | optional = false 1481 | python-versions = "*" 1482 | 1483 | [[package]] 1484 | name = "pyasn1-modules" 1485 | version = "0.2.8" 1486 | description = "A collection of ASN.1-based protocols modules." 1487 | category = "main" 1488 | optional = false 1489 | python-versions = "*" 1490 | 1491 | [package.dependencies] 1492 | pyasn1 = ">=0.4.6,<0.5.0" 1493 | 1494 | [[package]] 1495 | name = "pycparser" 1496 | version = "2.21" 1497 | description = "C parser in Python" 1498 | category = "main" 1499 | optional = false 1500 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" 1501 | 1502 | [[package]] 1503 | name = "pycryptodomex" 1504 | version = "3.17" 1505 | description = "Cryptographic library for Python" 1506 | category = "main" 1507 | optional = false 1508 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" 1509 | 1510 | [[package]] 1511 | name = "pygments" 1512 | version = "2.14.0" 1513 | description = "Pygments is a syntax highlighting package written in Python." 1514 | category = "main" 1515 | optional = false 1516 | python-versions = ">=3.6" 1517 | 1518 | [package.extras] 1519 | plugins = ["importlib-metadata"] 1520 | 1521 | [[package]] 1522 | name = "pyhopshive" 1523 | version = "0.6.4.1.dev0" 1524 | description = "Python interface to Hops Hive" 1525 | category = "main" 1526 | optional = false 1527 | python-versions = "*" 1528 | 1529 | [package.dependencies] 1530 | future = "*" 1531 | pyjks = "*" 1532 | python-dateutil = "*" 1533 | thrift = {version = ">=0.10.0", optional = true, markers = "extra == \"thrift\""} 1534 | 1535 | [package.extras] 1536 | hive = ["sasl (>=0.2.1)", "thrift (>=0.10.0)", "thrift_sasl (>=0.1.0)"] 1537 | presto = ["requests (>=1.0.0)"] 1538 | sqlalchemy = ["sqlalchemy (>=0.8.7)"] 1539 | thrift = ["thrift (>=0.10.0)"] 1540 | 1541 | [[package]] 1542 | name = "pyhumps" 1543 | version = "1.6.1" 1544 | description = "🐫 Convert strings (and dictionary keys) between snake case, camel case and pascal case in Python. Inspired by Humps for Node" 1545 | category = "main" 1546 | optional = false 1547 | python-versions = "*" 1548 | 1549 | [[package]] 1550 | name = "pyjks" 1551 | version = "20.0.0" 1552 | description = "Pure-Python Java Keystore (JKS) library" 1553 | category = "main" 1554 | optional = false 1555 | python-versions = "*" 1556 | 1557 | [package.dependencies] 1558 | javaobj-py3 = "*" 1559 | pyasn1 = ">=0.3.5" 1560 | pyasn1-modules = "*" 1561 | pycryptodomex = "*" 1562 | twofish = "*" 1563 | 1564 | [[package]] 1565 | name = "pylint" 1566 | version = "2.17.1" 1567 | description = "python code static checker" 1568 | category = "dev" 1569 | optional = false 1570 | python-versions = ">=3.7.2" 1571 | 1572 | [package.dependencies] 1573 | astroid = ">=2.15.0,<=2.17.0-dev0" 1574 | colorama = {version = ">=0.4.5", markers = "sys_platform == \"win32\""} 1575 | dill = {version = ">=0.2", markers = "python_version < \"3.11\""} 1576 | isort = ">=4.2.5,<6" 1577 | mccabe = ">=0.6,<0.8" 1578 | platformdirs = ">=2.2.0" 1579 | tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} 1580 | tomlkit = ">=0.10.1" 1581 | typing-extensions = {version = ">=3.10.0", markers = "python_version < \"3.10\""} 1582 | 1583 | [package.extras] 1584 | spelling = ["pyenchant (>=3.2,<4.0)"] 1585 | testutils = ["gitpython (>3)"] 1586 | 1587 | [[package]] 1588 | name = "pymysql" 1589 | version = "1.0.3" 1590 | description = "Pure Python MySQL Driver" 1591 | category = "main" 1592 | optional = false 1593 | python-versions = ">=3.7" 1594 | 1595 | [package.dependencies] 1596 | cryptography = {version = "*", optional = true, markers = "extra == \"rsa\""} 1597 | 1598 | [package.extras] 1599 | ed25519 = ["PyNaCl (>=1.4.0)"] 1600 | rsa = ["cryptography"] 1601 | 1602 | [[package]] 1603 | name = "pyopenssl" 1604 | version = "23.1.1" 1605 | description = "Python wrapper module around the OpenSSL library" 1606 | category = "main" 1607 | optional = false 1608 | python-versions = ">=3.6" 1609 | 1610 | [package.dependencies] 1611 | cryptography = ">=38.0.0,<41" 1612 | 1613 | [package.extras] 1614 | docs = ["sphinx (!=5.2.0,!=5.2.0.post0)", "sphinx-rtd-theme"] 1615 | test = ["flaky", "pretend", "pytest (>=3.0.1)"] 1616 | 1617 | [[package]] 1618 | name = "pyparsing" 1619 | version = "2.4.7" 1620 | description = "Python parsing module" 1621 | category = "main" 1622 | optional = false 1623 | python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" 1624 | 1625 | [[package]] 1626 | name = "pyproject-hooks" 1627 | version = "1.0.0" 1628 | description = "Wrappers to call pyproject.toml-based build backend hooks." 1629 | category = "dev" 1630 | optional = false 1631 | python-versions = ">=3.7" 1632 | 1633 | [package.dependencies] 1634 | tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} 1635 | 1636 | [[package]] 1637 | name = "pyrsistent" 1638 | version = "0.19.3" 1639 | description = "Persistent/Functional/Immutable data structures" 1640 | category = "main" 1641 | optional = false 1642 | python-versions = ">=3.7" 1643 | 1644 | [[package]] 1645 | name = "pytest" 1646 | version = "5.4.3" 1647 | description = "pytest: simple powerful testing with Python" 1648 | category = "dev" 1649 | optional = false 1650 | python-versions = ">=3.5" 1651 | 1652 | [package.dependencies] 1653 | atomicwrites = {version = ">=1.0", markers = "sys_platform == \"win32\""} 1654 | attrs = ">=17.4.0" 1655 | colorama = {version = "*", markers = "sys_platform == \"win32\""} 1656 | more-itertools = ">=4.0.0" 1657 | packaging = "*" 1658 | pluggy = ">=0.12,<1.0" 1659 | py = ">=1.5.0" 1660 | wcwidth = "*" 1661 | 1662 | [package.extras] 1663 | checkqa-mypy = ["mypy (==v0.761)"] 1664 | testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "requests", "xmlschema"] 1665 | 1666 | [[package]] 1667 | name = "python-dateutil" 1668 | version = "2.8.2" 1669 | description = "Extensions to the standard Python datetime module" 1670 | category = "main" 1671 | optional = false 1672 | python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" 1673 | 1674 | [package.dependencies] 1675 | six = ">=1.5" 1676 | 1677 | [[package]] 1678 | name = "python-json-logger" 1679 | version = "2.0.7" 1680 | description = "A python library adding a json log formatter" 1681 | category = "dev" 1682 | optional = false 1683 | python-versions = ">=3.6" 1684 | 1685 | [[package]] 1686 | name = "pytz" 1687 | version = "2022.7.1" 1688 | description = "World timezone definitions, modern and historical" 1689 | category = "main" 1690 | optional = false 1691 | python-versions = "*" 1692 | 1693 | [[package]] 1694 | name = "pytz-deprecation-shim" 1695 | version = "0.1.0.post0" 1696 | description = "Shims to make deprecation of pytz easier" 1697 | category = "main" 1698 | optional = false 1699 | python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7" 1700 | 1701 | [package.dependencies] 1702 | tzdata = {version = "*", markers = "python_version >= \"3.6\""} 1703 | 1704 | [[package]] 1705 | name = "pywin32" 1706 | version = "305" 1707 | description = "Python for Window Extensions" 1708 | category = "main" 1709 | optional = false 1710 | python-versions = "*" 1711 | 1712 | [[package]] 1713 | name = "pywinpty" 1714 | version = "2.0.10" 1715 | description = "Pseudo terminal support for Windows from Python." 1716 | category = "dev" 1717 | optional = false 1718 | python-versions = ">=3.7" 1719 | 1720 | [[package]] 1721 | name = "pyyaml" 1722 | version = "5.4.1" 1723 | description = "YAML parser and emitter for Python" 1724 | category = "dev" 1725 | optional = false 1726 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" 1727 | 1728 | [[package]] 1729 | name = "pyzmq" 1730 | version = "25.0.1" 1731 | description = "Python bindings for 0MQ" 1732 | category = "main" 1733 | optional = false 1734 | python-versions = ">=3.6" 1735 | 1736 | [package.dependencies] 1737 | cffi = {version = "*", markers = "implementation_name == \"pypy\""} 1738 | 1739 | [[package]] 1740 | name = "qtconsole" 1741 | version = "5.4.1" 1742 | description = "Jupyter Qt console" 1743 | category = "dev" 1744 | optional = false 1745 | python-versions = ">= 3.7" 1746 | 1747 | [package.dependencies] 1748 | ipykernel = ">=4.1" 1749 | ipython-genutils = "*" 1750 | jupyter-client = ">=4.1" 1751 | jupyter-core = "*" 1752 | packaging = "*" 1753 | pygments = "*" 1754 | pyzmq = ">=17.1" 1755 | qtpy = ">=2.0.1" 1756 | traitlets = "<5.2.1 || >5.2.1,<5.2.2 || >5.2.2" 1757 | 1758 | [package.extras] 1759 | doc = ["Sphinx (>=1.3)"] 1760 | test = ["flaky", "pytest", "pytest-qt"] 1761 | 1762 | [[package]] 1763 | name = "qtpy" 1764 | version = "2.3.0" 1765 | description = "Provides an abstraction layer on top of the various Qt bindings (PyQt5/6 and PySide2/6)." 1766 | category = "dev" 1767 | optional = false 1768 | python-versions = ">=3.7" 1769 | 1770 | [package.dependencies] 1771 | packaging = "*" 1772 | 1773 | [package.extras] 1774 | test = ["pytest (>=6,!=7.0.0,!=7.0.1)", "pytest-cov (>=3.0.0)", "pytest-qt"] 1775 | 1776 | [[package]] 1777 | name = "requests" 1778 | version = "2.28.2" 1779 | description = "Python HTTP for Humans." 1780 | category = "main" 1781 | optional = false 1782 | python-versions = ">=3.7, <4" 1783 | 1784 | [package.dependencies] 1785 | certifi = ">=2017.4.17" 1786 | charset-normalizer = ">=2,<4" 1787 | idna = ">=2.5,<4" 1788 | urllib3 = ">=1.21.1,<1.27" 1789 | 1790 | [package.extras] 1791 | socks = ["PySocks (>=1.5.6,!=1.5.7)"] 1792 | use_chardet_on_py3 = ["chardet (>=3.0.2,<6)"] 1793 | 1794 | [[package]] 1795 | name = "retry" 1796 | version = "0.9.2" 1797 | description = "Easy to use retry decorator." 1798 | category = "main" 1799 | optional = false 1800 | python-versions = "*" 1801 | 1802 | [package.dependencies] 1803 | decorator = ">=3.4.2" 1804 | py = ">=1.4.26,<2.0.0" 1805 | 1806 | [[package]] 1807 | name = "rfc3339-validator" 1808 | version = "0.1.4" 1809 | description = "A pure python RFC3339 validator" 1810 | category = "dev" 1811 | optional = false 1812 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" 1813 | 1814 | [package.dependencies] 1815 | six = "*" 1816 | 1817 | [[package]] 1818 | name = "rfc3986-validator" 1819 | version = "0.1.1" 1820 | description = "Pure python rfc3986 validator" 1821 | category = "dev" 1822 | optional = false 1823 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" 1824 | 1825 | [[package]] 1826 | name = "ruamel.yaml" 1827 | version = "0.17.17" 1828 | description = "ruamel.yaml is a YAML parser/emitter that supports roundtrip preservation of comments, seq/map flow style, and map key order" 1829 | category = "main" 1830 | optional = false 1831 | python-versions = ">=3" 1832 | 1833 | [package.dependencies] 1834 | "ruamel.yaml.clib" = {version = ">=0.1.2", markers = "platform_python_implementation == \"CPython\" and python_version < \"3.10\""} 1835 | 1836 | [package.extras] 1837 | docs = ["ryd"] 1838 | jinja2 = ["ruamel.yaml.jinja2 (>=0.2)"] 1839 | 1840 | [[package]] 1841 | name = "ruamel.yaml.clib" 1842 | version = "0.2.7" 1843 | description = "C version of reader, parser and emitter for ruamel.yaml derived from libyaml" 1844 | category = "main" 1845 | optional = false 1846 | python-versions = ">=3.5" 1847 | 1848 | [[package]] 1849 | name = "s3transfer" 1850 | version = "0.6.0" 1851 | description = "An Amazon S3 Transfer Manager" 1852 | category = "main" 1853 | optional = false 1854 | python-versions = ">= 3.7" 1855 | 1856 | [package.dependencies] 1857 | botocore = ">=1.12.36,<2.0a.0" 1858 | 1859 | [package.extras] 1860 | crt = ["botocore[crt] (>=1.20.29,<2.0a.0)"] 1861 | 1862 | [[package]] 1863 | name = "scipy" 1864 | version = "1.10.1" 1865 | description = "Fundamental algorithms for scientific computing in Python" 1866 | category = "main" 1867 | optional = false 1868 | python-versions = "<3.12,>=3.8" 1869 | 1870 | [package.dependencies] 1871 | numpy = ">=1.19.5,<1.27.0" 1872 | 1873 | [package.extras] 1874 | test = ["pytest", "pytest-cov", "pytest-timeout", "pytest-xdist", "asv", "mpmath", "gmpy2", "threadpoolctl", "scikit-umfpack", "pooch"] 1875 | doc = ["sphinx (!=4.1.0)", "pydata-sphinx-theme (==0.9.0)", "sphinx-design (>=0.2.0)", "matplotlib (>2)", "numpydoc"] 1876 | dev = ["mypy", "typing-extensions", "pycodestyle", "flake8", "rich-click", "click", "doit (>=0.36.0)", "pydevtool"] 1877 | 1878 | [[package]] 1879 | name = "send2trash" 1880 | version = "1.8.0" 1881 | description = "Send file to trash natively under Mac OS X, Windows and Linux." 1882 | category = "dev" 1883 | optional = false 1884 | python-versions = "*" 1885 | 1886 | [package.extras] 1887 | nativelib = ["pyobjc-framework-cocoa", "pywin32"] 1888 | objc = ["pyobjc-framework-cocoa"] 1889 | win32 = ["pywin32"] 1890 | 1891 | [[package]] 1892 | name = "six" 1893 | version = "1.16.0" 1894 | description = "Python 2 and 3 compatibility utilities" 1895 | category = "main" 1896 | optional = false 1897 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" 1898 | 1899 | [[package]] 1900 | name = "sniffio" 1901 | version = "1.3.0" 1902 | description = "Sniff out which async library your code is running under" 1903 | category = "dev" 1904 | optional = false 1905 | python-versions = ">=3.7" 1906 | 1907 | [[package]] 1908 | name = "soupsieve" 1909 | version = "2.4" 1910 | description = "A modern CSS selector implementation for Beautiful Soup." 1911 | category = "dev" 1912 | optional = false 1913 | python-versions = ">=3.7" 1914 | 1915 | [[package]] 1916 | name = "sqlalchemy" 1917 | version = "2.0.6" 1918 | description = "Database Abstraction Library" 1919 | category = "main" 1920 | optional = false 1921 | python-versions = ">=3.7" 1922 | 1923 | [package.dependencies] 1924 | greenlet = {version = "!=0.4.17", markers = "platform_machine == \"aarch64\" or platform_machine == \"ppc64le\" or platform_machine == \"x86_64\" or platform_machine == \"amd64\" or platform_machine == \"AMD64\" or platform_machine == \"win32\" or platform_machine == \"WIN32\""} 1925 | typing-extensions = ">=4.2.0" 1926 | 1927 | [package.extras] 1928 | aiomysql = ["greenlet (!=0.4.17)", "aiomysql"] 1929 | aiosqlite = ["greenlet (!=0.4.17)", "aiosqlite", "typing-extensions (!=3.10.0.1)"] 1930 | asyncio = ["greenlet (!=0.4.17)"] 1931 | asyncmy = ["greenlet (!=0.4.17)", "asyncmy (>=0.2.3,!=0.2.4,!=0.2.6)"] 1932 | mariadb_connector = ["mariadb (>=1.0.1,!=1.1.2,!=1.1.5)"] 1933 | mssql = ["pyodbc"] 1934 | mssql_pymssql = ["pymssql"] 1935 | mssql_pyodbc = ["pyodbc"] 1936 | mypy = ["mypy (>=0.910)"] 1937 | mysql = ["mysqlclient (>=1.4.0)"] 1938 | mysql_connector = ["mysql-connector-python"] 1939 | oracle = ["cx-oracle (>=7)"] 1940 | oracle_oracledb = ["oracledb (>=1.0.1)"] 1941 | postgresql = ["psycopg2 (>=2.7)"] 1942 | postgresql_asyncpg = ["greenlet (!=0.4.17)", "asyncpg"] 1943 | postgresql_pg8000 = ["pg8000 (>=1.29.1)"] 1944 | postgresql_psycopg = ["psycopg (>=3.0.7)"] 1945 | postgresql_psycopg2binary = ["psycopg2-binary"] 1946 | postgresql_psycopg2cffi = ["psycopg2cffi"] 1947 | pymysql = ["pymysql"] 1948 | sqlcipher = ["sqlcipher3-binary"] 1949 | 1950 | [[package]] 1951 | name = "stack-data" 1952 | version = "0.6.2" 1953 | description = "Extract data from python stack frames and tracebacks for informative displays" 1954 | category = "main" 1955 | optional = false 1956 | python-versions = "*" 1957 | 1958 | [package.dependencies] 1959 | asttokens = ">=2.1.0" 1960 | executing = ">=1.2.0" 1961 | pure-eval = "*" 1962 | 1963 | [package.extras] 1964 | tests = ["pytest", "typeguard", "pygments", "littleutils", "cython"] 1965 | 1966 | [[package]] 1967 | name = "ta" 1968 | version = "0.10.2" 1969 | description = "Technical Analysis Library in Python" 1970 | category = "main" 1971 | optional = false 1972 | python-versions = "*" 1973 | 1974 | [package.dependencies] 1975 | numpy = "*" 1976 | pandas = "*" 1977 | 1978 | [[package]] 1979 | name = "termcolor" 1980 | version = "2.2.0" 1981 | description = "ANSI color formatting for output in terminal" 1982 | category = "main" 1983 | optional = false 1984 | python-versions = ">=3.7" 1985 | 1986 | [package.extras] 1987 | tests = ["pytest", "pytest-cov"] 1988 | 1989 | [[package]] 1990 | name = "terminado" 1991 | version = "0.17.1" 1992 | description = "Tornado websocket backend for the Xterm.js Javascript terminal emulator library." 1993 | category = "dev" 1994 | optional = false 1995 | python-versions = ">=3.7" 1996 | 1997 | [package.dependencies] 1998 | ptyprocess = {version = "*", markers = "os_name != \"nt\""} 1999 | pywinpty = {version = ">=1.1.0", markers = "os_name == \"nt\""} 2000 | tornado = ">=6.1.0" 2001 | 2002 | [package.extras] 2003 | docs = ["myst-parser", "pydata-sphinx-theme", "sphinx"] 2004 | test = ["pre-commit", "pytest-timeout", "pytest (>=7.0)"] 2005 | 2006 | [[package]] 2007 | name = "thrift" 2008 | version = "0.16.0" 2009 | description = "Python bindings for the Apache Thrift RPC system" 2010 | category = "main" 2011 | optional = false 2012 | python-versions = "*" 2013 | 2014 | [package.dependencies] 2015 | six = ">=1.7.2" 2016 | 2017 | [package.extras] 2018 | all = ["tornado (>=4.0)", "twisted"] 2019 | tornado = ["tornado (>=4.0)"] 2020 | twisted = ["twisted"] 2021 | 2022 | [[package]] 2023 | name = "tinycss2" 2024 | version = "1.2.1" 2025 | description = "A tiny CSS parser" 2026 | category = "dev" 2027 | optional = false 2028 | python-versions = ">=3.7" 2029 | 2030 | [package.dependencies] 2031 | webencodings = ">=0.4" 2032 | 2033 | [package.extras] 2034 | doc = ["sphinx", "sphinx-rtd-theme"] 2035 | test = ["pytest", "isort", "flake8"] 2036 | 2037 | [[package]] 2038 | name = "tomli" 2039 | version = "2.0.1" 2040 | description = "A lil' TOML parser" 2041 | category = "dev" 2042 | optional = false 2043 | python-versions = ">=3.7" 2044 | 2045 | [[package]] 2046 | name = "tomlkit" 2047 | version = "0.11.7" 2048 | description = "Style preserving TOML library" 2049 | category = "dev" 2050 | optional = false 2051 | python-versions = ">=3.7" 2052 | 2053 | [[package]] 2054 | name = "toolz" 2055 | version = "0.12.0" 2056 | description = "List processing tools and functional utilities" 2057 | category = "main" 2058 | optional = false 2059 | python-versions = ">=3.5" 2060 | 2061 | [[package]] 2062 | name = "tornado" 2063 | version = "6.2" 2064 | description = "Tornado is a Python web framework and asynchronous networking library, originally developed at FriendFeed." 2065 | category = "main" 2066 | optional = false 2067 | python-versions = ">= 3.7" 2068 | 2069 | [[package]] 2070 | name = "tqdm" 2071 | version = "4.65.0" 2072 | description = "Fast, Extensible Progress Meter" 2073 | category = "main" 2074 | optional = false 2075 | python-versions = ">=3.7" 2076 | 2077 | [package.dependencies] 2078 | colorama = {version = "*", markers = "platform_system == \"Windows\""} 2079 | 2080 | [package.extras] 2081 | dev = ["py-make (>=0.1.0)", "twine", "wheel"] 2082 | notebook = ["ipywidgets (>=6)"] 2083 | slack = ["slack-sdk"] 2084 | telegram = ["requests"] 2085 | 2086 | [[package]] 2087 | name = "traitlets" 2088 | version = "5.9.0" 2089 | description = "Traitlets Python configuration system" 2090 | category = "main" 2091 | optional = false 2092 | python-versions = ">=3.7" 2093 | 2094 | [package.extras] 2095 | docs = ["myst-parser", "pydata-sphinx-theme", "sphinx"] 2096 | test = ["argcomplete (>=2.0)", "pre-commit", "pytest", "pytest-mock"] 2097 | 2098 | [[package]] 2099 | name = "twofish" 2100 | version = "0.3.0" 2101 | description = "Bindings for the Twofish implementation by Niels Ferguson" 2102 | category = "main" 2103 | optional = false 2104 | python-versions = "*" 2105 | 2106 | [[package]] 2107 | name = "typing-extensions" 2108 | version = "4.5.0" 2109 | description = "Backported and Experimental Type Hints for Python 3.7+" 2110 | category = "main" 2111 | optional = false 2112 | python-versions = ">=3.7" 2113 | 2114 | [[package]] 2115 | name = "tzdata" 2116 | version = "2022.7" 2117 | description = "Provider of IANA time zone data" 2118 | category = "main" 2119 | optional = false 2120 | python-versions = ">=2" 2121 | 2122 | [[package]] 2123 | name = "tzlocal" 2124 | version = "4.2" 2125 | description = "tzinfo object for the local timezone" 2126 | category = "main" 2127 | optional = false 2128 | python-versions = ">=3.6" 2129 | 2130 | [package.dependencies] 2131 | pytz-deprecation-shim = "*" 2132 | tzdata = {version = "*", markers = "platform_system == \"Windows\""} 2133 | 2134 | [package.extras] 2135 | devenv = ["black", "pyroma", "pytest-cov", "zest.releaser"] 2136 | test = ["pytest-mock (>=3.3)", "pytest (>=4.3)"] 2137 | 2138 | [[package]] 2139 | name = "uri-template" 2140 | version = "1.2.0" 2141 | description = "RFC 6570 URI Template Processor" 2142 | category = "dev" 2143 | optional = false 2144 | python-versions = ">=3.6" 2145 | 2146 | [package.extras] 2147 | dev = ["mypy", "flake8 (<4.0.0)", "flake8-annotations", "flake8-bugbear", "flake8-commas", "flake8-comprehensions", "flake8-continuation", "flake8-datetimez", "flake8-docstrings", "flake8-import-order", "flake8-literal", "flake8-noqa", "flake8-requirements", "flake8-type-annotations", "flake8-use-fstring", "pep8-naming"] 2148 | 2149 | [[package]] 2150 | name = "urllib3" 2151 | version = "1.26.15" 2152 | description = "HTTP library with thread-safe connection pooling, file post, and more." 2153 | category = "main" 2154 | optional = false 2155 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" 2156 | 2157 | [package.extras] 2158 | brotli = ["brotlicffi (>=0.8.0)", "brotli (>=1.0.9)", "brotlipy (>=0.6.0)"] 2159 | secure = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "certifi", "urllib3-secure-extra", "ipaddress"] 2160 | socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] 2161 | 2162 | [[package]] 2163 | name = "wcwidth" 2164 | version = "0.2.6" 2165 | description = "Measures the displayed width of unicode strings in a terminal" 2166 | category = "main" 2167 | optional = false 2168 | python-versions = "*" 2169 | 2170 | [[package]] 2171 | name = "webcolors" 2172 | version = "1.12" 2173 | description = "A library for working with color names and color values formats defined by HTML and CSS." 2174 | category = "dev" 2175 | optional = false 2176 | python-versions = ">=3.7" 2177 | 2178 | [[package]] 2179 | name = "webencodings" 2180 | version = "0.5.1" 2181 | description = "Character encoding aliases for legacy web content" 2182 | category = "dev" 2183 | optional = false 2184 | python-versions = "*" 2185 | 2186 | [[package]] 2187 | name = "websocket-client" 2188 | version = "1.5.1" 2189 | description = "WebSocket client for Python with low level API options" 2190 | category = "main" 2191 | optional = false 2192 | python-versions = ">=3.7" 2193 | 2194 | [package.extras] 2195 | docs = ["Sphinx (>=3.4)", "sphinx-rtd-theme (>=0.5)"] 2196 | optional = ["python-socks", "wsaccel"] 2197 | test = ["websockets"] 2198 | 2199 | [[package]] 2200 | name = "widgetsnbextension" 2201 | version = "4.0.5" 2202 | description = "Jupyter interactive widgets for Jupyter Notebook" 2203 | category = "main" 2204 | optional = false 2205 | python-versions = ">=3.7" 2206 | 2207 | [[package]] 2208 | name = "wrapt" 2209 | version = "1.15.0" 2210 | description = "Module for decorators, wrappers and monkey patching." 2211 | category = "dev" 2212 | optional = false 2213 | python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" 2214 | 2215 | [[package]] 2216 | name = "zipp" 2217 | version = "3.15.0" 2218 | description = "Backport of pathlib-compatible object wrapper for zip files" 2219 | category = "main" 2220 | optional = false 2221 | python-versions = ">=3.7" 2222 | 2223 | [package.extras] 2224 | docs = ["sphinx (>=3.5)", "jaraco.packaging (>=9)", "rst.linker (>=1.9)", "furo", "sphinx-lint", "jaraco.tidelift (>=1.4)"] 2225 | testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "flake8 (<5)", "pytest-cov", "pytest-enabler (>=1.3)", "jaraco.itertools", "jaraco.functools", "more-itertools", "big-o", "pytest-black (>=0.3.7)", "pytest-mypy (>=0.9.1)", "pytest-flake8"] 2226 | 2227 | [metadata] 2228 | lock-version = "1.1" 2229 | python-versions = ">=3.9,<3.10" 2230 | content-hash = "35831ec252abfbe40d8461ebec7d4a446108374735d65a955502a06bae0ae838" 2231 | 2232 | [metadata.files] 2233 | altair = [] 2234 | anyio = [] 2235 | appnope = [ 2236 | {file = "appnope-0.1.3-py2.py3-none-any.whl", hash = "sha256:265a455292d0bd8a72453494fa24df5a11eb18373a60c7c0430889f22548605e"}, 2237 | {file = "appnope-0.1.3.tar.gz", hash = "sha256:02bd91c4de869fbb1e1c50aafc4098827a7a54ab2f39d9dcba6c9547ed920e24"}, 2238 | ] 2239 | argon2-cffi = [ 2240 | {file = "argon2-cffi-21.3.0.tar.gz", hash = "sha256:d384164d944190a7dd7ef22c6aa3ff197da12962bd04b17f64d4e93d934dba5b"}, 2241 | {file = "argon2_cffi-21.3.0-py3-none-any.whl", hash = "sha256:8c976986f2c5c0e5000919e6de187906cfd81fb1c72bf9d88c01177e77da7f80"}, 2242 | ] 2243 | argon2-cffi-bindings = [ 2244 | {file = "argon2-cffi-bindings-21.2.0.tar.gz", hash = "sha256:bb89ceffa6c791807d1305ceb77dbfacc5aa499891d2c55661c6459651fc39e3"}, 2245 | {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:ccb949252cb2ab3a08c02024acb77cfb179492d5701c7cbdbfd776124d4d2367"}, 2246 | {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9524464572e12979364b7d600abf96181d3541da11e23ddf565a32e70bd4dc0d"}, 2247 | {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b746dba803a79238e925d9046a63aa26bf86ab2a2fe74ce6b009a1c3f5c8f2ae"}, 2248 | {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:58ed19212051f49a523abb1dbe954337dc82d947fb6e5a0da60f7c8471a8476c"}, 2249 | {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:bd46088725ef7f58b5a1ef7ca06647ebaf0eb4baff7d1d0d177c6cc8744abd86"}, 2250 | {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-musllinux_1_1_i686.whl", hash = "sha256:8cd69c07dd875537a824deec19f978e0f2078fdda07fd5c42ac29668dda5f40f"}, 2251 | {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:f1152ac548bd5b8bcecfb0b0371f082037e47128653df2e8ba6e914d384f3c3e"}, 2252 | {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-win32.whl", hash = "sha256:603ca0aba86b1349b147cab91ae970c63118a0f30444d4bc80355937c950c082"}, 2253 | {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-win_amd64.whl", hash = "sha256:b2ef1c30440dbbcba7a5dc3e319408b59676e2e039e2ae11a8775ecf482b192f"}, 2254 | {file = "argon2_cffi_bindings-21.2.0-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:e415e3f62c8d124ee16018e491a009937f8cf7ebf5eb430ffc5de21b900dad93"}, 2255 | {file = "argon2_cffi_bindings-21.2.0-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:3e385d1c39c520c08b53d63300c3ecc28622f076f4c2b0e6d7e796e9f6502194"}, 2256 | {file = "argon2_cffi_bindings-21.2.0-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2c3e3cc67fdb7d82c4718f19b4e7a87123caf8a93fde7e23cf66ac0337d3cb3f"}, 2257 | {file = "argon2_cffi_bindings-21.2.0-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6a22ad9800121b71099d0fb0a65323810a15f2e292f2ba450810a7316e128ee5"}, 2258 | {file = "argon2_cffi_bindings-21.2.0-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f9f8b450ed0547e3d473fdc8612083fd08dd2120d6ac8f73828df9b7d45bb351"}, 2259 | {file = "argon2_cffi_bindings-21.2.0-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:93f9bf70084f97245ba10ee36575f0c3f1e7d7724d67d8e5b08e61787c320ed7"}, 2260 | {file = "argon2_cffi_bindings-21.2.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:3b9ef65804859d335dc6b31582cad2c5166f0c3e7975f324d9ffaa34ee7e6583"}, 2261 | {file = "argon2_cffi_bindings-21.2.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d4966ef5848d820776f5f562a7d45fdd70c2f330c961d0d745b784034bd9f48d"}, 2262 | {file = "argon2_cffi_bindings-21.2.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:20ef543a89dee4db46a1a6e206cd015360e5a75822f76df533845c3cbaf72670"}, 2263 | {file = "argon2_cffi_bindings-21.2.0-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ed2937d286e2ad0cc79a7087d3c272832865f779430e0cc2b4f3718d3159b0cb"}, 2264 | {file = "argon2_cffi_bindings-21.2.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:5e00316dabdaea0b2dd82d141cc66889ced0cdcbfa599e8b471cf22c620c329a"}, 2265 | ] 2266 | arrow = [] 2267 | astroid = [] 2268 | asttokens = [] 2269 | atomicwrites = [] 2270 | attrs = [] 2271 | avro = [] 2272 | backcall = [ 2273 | {file = "backcall-0.2.0-py2.py3-none-any.whl", hash = "sha256:fbbce6a29f263178a1f7915c1940bde0ec2b2a967566fe1c65c1dfb7422bd255"}, 2274 | {file = "backcall-0.2.0.tar.gz", hash = "sha256:5cbdbf27be5e7cfadb448baf0aa95508f91f2bbc6c6437cd9cd06e2a4c215e1e"}, 2275 | ] 2276 | beautifulsoup4 = [] 2277 | black = [] 2278 | bleach = [] 2279 | boto3 = [] 2280 | botocore = [] 2281 | build = [] 2282 | bytewax = [] 2283 | certifi = [] 2284 | cffi = [] 2285 | charset-normalizer = [] 2286 | click = [ 2287 | {file = "click-8.1.3-py3-none-any.whl", hash = "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48"}, 2288 | {file = "click-8.1.3.tar.gz", hash = "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e"}, 2289 | ] 2290 | colorama = [] 2291 | comm = [] 2292 | confluent-kafka = [] 2293 | cryptography = [] 2294 | debugpy = [] 2295 | decorator = [ 2296 | {file = "decorator-5.1.1-py3-none-any.whl", hash = "sha256:b8c3f85900b9dc423225913c5aace94729fe1fa9763b38939a95226f02d37186"}, 2297 | {file = "decorator-5.1.1.tar.gz", hash = "sha256:637996211036b6385ef91435e4fae22989472f9d571faba8927ba8253acbc330"}, 2298 | ] 2299 | defusedxml = [ 2300 | {file = "defusedxml-0.7.1-py2.py3-none-any.whl", hash = "sha256:a352e7e428770286cc899e2542b6cdaedb2b4953ff269a210103ec58f6198a61"}, 2301 | {file = "defusedxml-0.7.1.tar.gz", hash = "sha256:1bb3032db185915b62d7c6209c5a8792be6a32ab2fedacc84e01b52c51aa3e69"}, 2302 | ] 2303 | dill = [] 2304 | entrypoints = [ 2305 | {file = "entrypoints-0.4-py3-none-any.whl", hash = "sha256:f174b5ff827504fd3cd97cc3f8649f3693f51538c7e4bdf3ef002c8429d42f9f"}, 2306 | {file = "entrypoints-0.4.tar.gz", hash = "sha256:b706eddaa9218a19ebcd67b56818f05bb27589b1ca9e8d797b74affad4ccacd4"}, 2307 | ] 2308 | executing = [] 2309 | fastavro = [] 2310 | fastjsonschema = [] 2311 | fqdn = [ 2312 | {file = "fqdn-1.5.1-py3-none-any.whl", hash = "sha256:3a179af3761e4df6eb2e026ff9e1a3033d3587bf980a0b1b2e1e5d08d7358014"}, 2313 | {file = "fqdn-1.5.1.tar.gz", hash = "sha256:105ed3677e767fb5ca086a0c1f4bb66ebc3c100be518f0e0d755d9eae164d89f"}, 2314 | ] 2315 | furl = [] 2316 | future = [] 2317 | great-expectations = [] 2318 | greenlet = [] 2319 | hopsworks = [] 2320 | hsfs = [] 2321 | hsml = [] 2322 | idna = [] 2323 | importlib-metadata = [] 2324 | ipykernel = [] 2325 | ipython = [] 2326 | ipython-genutils = [ 2327 | {file = "ipython_genutils-0.2.0-py2.py3-none-any.whl", hash = "sha256:72dd37233799e619666c9f639a9da83c34013a73e8bbc79a7a6348d93c61fab8"}, 2328 | {file = "ipython_genutils-0.2.0.tar.gz", hash = "sha256:eb2e116e75ecef9d4d228fdc66af54269afa26ab4463042e33785b887c628ba8"}, 2329 | ] 2330 | ipywidgets = [] 2331 | isoduration = [ 2332 | {file = "isoduration-20.11.0-py3-none-any.whl", hash = "sha256:b2904c2a4228c3d44f409c8ae8e2370eb21a26f7ac2ec5446df141dde3452042"}, 2333 | {file = "isoduration-20.11.0.tar.gz", hash = "sha256:ac2f9015137935279eac671f94f89eb00584f940f5dc49462a0c4ee692ba1bd9"}, 2334 | ] 2335 | isort = [] 2336 | javaobj-py3 = [] 2337 | jedi = [] 2338 | jinja2 = [ 2339 | {file = "Jinja2-3.0.3-py3-none-any.whl", hash = "sha256:077ce6014f7b40d03b47d1f1ca4b0fc8328a692bd284016f806ed0eaca390ad8"}, 2340 | {file = "Jinja2-3.0.3.tar.gz", hash = "sha256:611bb273cd68f3b993fabdc4064fc858c5b47a973cb5aa7999ec1ba405c87cd7"}, 2341 | ] 2342 | jmespath = [] 2343 | jsonpatch = [] 2344 | jsonpointer = [] 2345 | jsonschema = [] 2346 | jupyter = [ 2347 | {file = "jupyter-1.0.0-py2.py3-none-any.whl", hash = "sha256:5b290f93b98ffbc21c0c7e749f054b3267782166d72fa5e3ed1ed4eaf34a2b78"}, 2348 | {file = "jupyter-1.0.0.tar.gz", hash = "sha256:d9dc4b3318f310e34c82951ea5d6683f67bed7def4b259fafbfe4f1beb1d8e5f"}, 2349 | {file = "jupyter-1.0.0.zip", hash = "sha256:3e1f86076bbb7c8c207829390305a2b1fe836d471ed54be66a3b8c41e7f46cc7"}, 2350 | ] 2351 | jupyter-client = [] 2352 | jupyter-console = [] 2353 | jupyter-core = [] 2354 | jupyter-events = [] 2355 | jupyter-server = [] 2356 | jupyter-server-terminals = [] 2357 | jupyterlab-pygments = [ 2358 | {file = "jupyterlab_pygments-0.2.2-py2.py3-none-any.whl", hash = "sha256:2405800db07c9f770863bcf8049a529c3dd4d3e28536638bd7c1c01d2748309f"}, 2359 | {file = "jupyterlab_pygments-0.2.2.tar.gz", hash = "sha256:7405d7fde60819d905a9fa8ce89e4cd830e318cdad22a0030f7a901da705585d"}, 2360 | ] 2361 | jupyterlab-widgets = [] 2362 | lazy-object-proxy = [] 2363 | lxml = [] 2364 | markupsafe = [ 2365 | {file = "MarkupSafe-2.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:f9081981fe268bd86831e5c75f7de206ef275defcb82bc70740ae6dc507aee51"}, 2366 | {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:0955295dd5eec6cb6cc2fe1698f4c6d84af2e92de33fbcac4111913cd100a6ff"}, 2367 | {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:0446679737af14f45767963a1a9ef7620189912317d095f2d9ffa183a4d25d2b"}, 2368 | {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:f826e31d18b516f653fe296d967d700fddad5901ae07c622bb3705955e1faa94"}, 2369 | {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:fa130dd50c57d53368c9d59395cb5526eda596d3ffe36666cd81a44d56e48872"}, 2370 | {file = "MarkupSafe-2.0.1-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:905fec760bd2fa1388bb5b489ee8ee5f7291d692638ea5f67982d968366bef9f"}, 2371 | {file = "MarkupSafe-2.0.1-cp36-cp36m-win32.whl", hash = "sha256:6c4ca60fa24e85fe25b912b01e62cb969d69a23a5d5867682dd3e80b5b02581d"}, 2372 | {file = "MarkupSafe-2.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:b2f4bf27480f5e5e8ce285a8c8fd176c0b03e93dcc6646477d4630e83440c6a9"}, 2373 | {file = "MarkupSafe-2.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0717a7390a68be14b8c793ba258e075c6f4ca819f15edfc2a3a027c823718567"}, 2374 | {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:6557b31b5e2c9ddf0de32a691f2312a32f77cd7681d8af66c2692efdbef84c18"}, 2375 | {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:49e3ceeabbfb9d66c3aef5af3a60cc43b85c33df25ce03d0031a608b0a8b2e3f"}, 2376 | {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:d7f9850398e85aba693bb640262d3611788b1f29a79f0c93c565694658f4071f"}, 2377 | {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:6a7fae0dd14cf60ad5ff42baa2e95727c3d81ded453457771d02b7d2b3f9c0c2"}, 2378 | {file = "MarkupSafe-2.0.1-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:b7f2d075102dc8c794cbde1947378051c4e5180d52d276987b8d28a3bd58c17d"}, 2379 | {file = "MarkupSafe-2.0.1-cp37-cp37m-win32.whl", hash = "sha256:a30e67a65b53ea0a5e62fe23682cfe22712e01f453b95233b25502f7c61cb415"}, 2380 | {file = "MarkupSafe-2.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:611d1ad9a4288cf3e3c16014564df047fe08410e628f89805e475368bd304914"}, 2381 | {file = "MarkupSafe-2.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:be98f628055368795d818ebf93da628541e10b75b41c559fdf36d104c5787066"}, 2382 | {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:1d609f577dc6e1aa17d746f8bd3c31aa4d258f4070d61b2aa5c4166c1539de35"}, 2383 | {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:7d91275b0245b1da4d4cfa07e0faedd5b0812efc15b702576d103293e252af1b"}, 2384 | {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:01a9b8ea66f1658938f65b93a85ebe8bc016e6769611be228d797c9d998dd298"}, 2385 | {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:47ab1e7b91c098ab893b828deafa1203de86d0bc6ab587b160f78fe6c4011f75"}, 2386 | {file = "MarkupSafe-2.0.1-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:97383d78eb34da7e1fa37dd273c20ad4320929af65d156e35a5e2d89566d9dfb"}, 2387 | {file = "MarkupSafe-2.0.1-cp38-cp38-win32.whl", hash = "sha256:023cb26ec21ece8dc3907c0e8320058b2e0cb3c55cf9564da612bc325bed5e64"}, 2388 | {file = "MarkupSafe-2.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:984d76483eb32f1bcb536dc27e4ad56bba4baa70be32fa87152832cdd9db0833"}, 2389 | {file = "MarkupSafe-2.0.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:2ef54abee730b502252bcdf31b10dacb0a416229b72c18b19e24a4509f273d26"}, 2390 | {file = "MarkupSafe-2.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3c112550557578c26af18a1ccc9e090bfe03832ae994343cfdacd287db6a6ae7"}, 2391 | {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux1_i686.whl", hash = "sha256:53edb4da6925ad13c07b6d26c2a852bd81e364f95301c66e930ab2aef5b5ddd8"}, 2392 | {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:f5653a225f31e113b152e56f154ccbe59eeb1c7487b39b9d9f9cdb58e6c79dc5"}, 2393 | {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:4efca8f86c54b22348a5467704e3fec767b2db12fc39c6d963168ab1d3fc9135"}, 2394 | {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:ab3ef638ace319fa26553db0624c4699e31a28bb2a835c5faca8f8acf6a5a902"}, 2395 | {file = "MarkupSafe-2.0.1-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:f8ba0e8349a38d3001fae7eadded3f6606f0da5d748ee53cc1dab1d6527b9509"}, 2396 | {file = "MarkupSafe-2.0.1-cp39-cp39-win32.whl", hash = "sha256:10f82115e21dc0dfec9ab5c0223652f7197feb168c940f3ef61563fc2d6beb74"}, 2397 | {file = "MarkupSafe-2.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:693ce3f9e70a6cf7d2fb9e6c9d8b204b6b39897a2c4a1aa65728d5ac97dcc1d8"}, 2398 | {file = "MarkupSafe-2.0.1.tar.gz", hash = "sha256:594c67807fb16238b30c44bdf74f36c02cdf22d1c8cda91ef8a0ed8dabf5620a"}, 2399 | ] 2400 | matplotlib-inline = [] 2401 | mccabe = [] 2402 | mistune = [ 2403 | {file = "mistune-0.8.4-py2.py3-none-any.whl", hash = "sha256:88a1051873018da288eee8538d476dffe1262495144b33ecb586c4ab266bb8d4"}, 2404 | {file = "mistune-0.8.4.tar.gz", hash = "sha256:59a3429db53c50b5c6bcc8a07f8848cb00d7dc8bdb431a4ab41920d201d4756e"}, 2405 | ] 2406 | mock = [] 2407 | more-itertools = [] 2408 | multiprocess = [] 2409 | mypy-extensions = [] 2410 | nbclassic = [] 2411 | nbclient = [] 2412 | nbconvert = [] 2413 | nbformat = [] 2414 | nest-asyncio = [] 2415 | notebook = [] 2416 | notebook-shim = [] 2417 | numpy = [] 2418 | orderedmultidict = [ 2419 | {file = "orderedmultidict-1.0.1-py2.py3-none-any.whl", hash = "sha256:43c839a17ee3cdd62234c47deca1a8508a3f2ca1d0678a3bf791c87cf84adbf3"}, 2420 | {file = "orderedmultidict-1.0.1.tar.gz", hash = "sha256:04070bbb5e87291cc9bfa51df413677faf2141c73c61d2a5f7b26bea3cd882ad"}, 2421 | ] 2422 | packaging = [] 2423 | pandas = [] 2424 | pandocfilters = [ 2425 | {file = "pandocfilters-1.5.0-py2.py3-none-any.whl", hash = "sha256:33aae3f25fd1a026079f5d27bdd52496f0e0803b3469282162bafdcbdf6ef14f"}, 2426 | {file = "pandocfilters-1.5.0.tar.gz", hash = "sha256:0b679503337d233b4339a817bfc8c50064e2eff681314376a47cb582305a7a38"}, 2427 | ] 2428 | parso = [ 2429 | {file = "parso-0.8.3-py2.py3-none-any.whl", hash = "sha256:c001d4636cd3aecdaf33cbb40aebb59b094be2a74c556778ef5576c175e19e75"}, 2430 | {file = "parso-0.8.3.tar.gz", hash = "sha256:8c07be290bb59f03588915921e29e8a50002acaf2cdc5fa0e0114f91709fafa0"}, 2431 | ] 2432 | pathspec = [] 2433 | pexpect = [ 2434 | {file = "pexpect-4.8.0-py2.py3-none-any.whl", hash = "sha256:0b48a55dcb3c05f3329815901ea4fc1537514d6ba867a152b581d69ae3710937"}, 2435 | {file = "pexpect-4.8.0.tar.gz", hash = "sha256:fc65a43959d153d0114afe13997d439c22823a27cefceb5ff35c2178c6784c0c"}, 2436 | ] 2437 | pickleshare = [ 2438 | {file = "pickleshare-0.7.5-py2.py3-none-any.whl", hash = "sha256:9649af414d74d4df115d5d718f82acb59c9d418196b7b4290ed47a12ce62df56"}, 2439 | {file = "pickleshare-0.7.5.tar.gz", hash = "sha256:87683d47965c1da65cdacaf31c8441d12b8044cdec9aca500cd78fc2c683afca"}, 2440 | ] 2441 | pip-tools = [] 2442 | platformdirs = [] 2443 | pluggy = [ 2444 | {file = "pluggy-0.13.1-py2.py3-none-any.whl", hash = "sha256:966c145cd83c96502c3c3868f50408687b38434af77734af1e9ca461a4081d2d"}, 2445 | {file = "pluggy-0.13.1.tar.gz", hash = "sha256:15b2acde666561e1298d71b523007ed7364de07029219b604cf808bfa1c765b0"}, 2446 | ] 2447 | prometheus-client = [] 2448 | prompt-toolkit = [] 2449 | psutil = [] 2450 | ptyprocess = [ 2451 | {file = "ptyprocess-0.7.0-py2.py3-none-any.whl", hash = "sha256:4b41f3967fce3af57cc7e94b888626c18bf37a083e3651ca8feeb66d492fef35"}, 2452 | {file = "ptyprocess-0.7.0.tar.gz", hash = "sha256:5c5d0a3b48ceee0b48485e0c26037c0acd7d29765ca3fbb5cb3831d347423220"}, 2453 | ] 2454 | pure-eval = [ 2455 | {file = "pure_eval-0.2.2-py3-none-any.whl", hash = "sha256:01eaab343580944bc56080ebe0a674b39ec44a945e6d09ba7db3cb8cec289350"}, 2456 | {file = "pure_eval-0.2.2.tar.gz", hash = "sha256:2b45320af6dfaa1750f543d714b6d1c520a1688dec6fd24d339063ce0aaa9ac3"}, 2457 | ] 2458 | py = [ 2459 | {file = "py-1.11.0-py2.py3-none-any.whl", hash = "sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378"}, 2460 | {file = "py-1.11.0.tar.gz", hash = "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719"}, 2461 | ] 2462 | pyarrow = [] 2463 | pyasn1 = [ 2464 | {file = "pyasn1-0.4.8-py2.4.egg", hash = "sha256:fec3e9d8e36808a28efb59b489e4528c10ad0f480e57dcc32b4de5c9d8c9fdf3"}, 2465 | {file = "pyasn1-0.4.8-py2.5.egg", hash = "sha256:0458773cfe65b153891ac249bcf1b5f8f320b7c2ce462151f8fa74de8934becf"}, 2466 | {file = "pyasn1-0.4.8-py2.6.egg", hash = "sha256:5c9414dcfede6e441f7e8f81b43b34e834731003427e5b09e4e00e3172a10f00"}, 2467 | {file = "pyasn1-0.4.8-py2.7.egg", hash = "sha256:6e7545f1a61025a4e58bb336952c5061697da694db1cae97b116e9c46abcf7c8"}, 2468 | {file = "pyasn1-0.4.8-py2.py3-none-any.whl", hash = "sha256:39c7e2ec30515947ff4e87fb6f456dfc6e84857d34be479c9d4a4ba4bf46aa5d"}, 2469 | {file = "pyasn1-0.4.8-py3.1.egg", hash = "sha256:78fa6da68ed2727915c4767bb386ab32cdba863caa7dbe473eaae45f9959da86"}, 2470 | {file = "pyasn1-0.4.8-py3.2.egg", hash = "sha256:08c3c53b75eaa48d71cf8c710312316392ed40899cb34710d092e96745a358b7"}, 2471 | {file = "pyasn1-0.4.8-py3.3.egg", hash = "sha256:03840c999ba71680a131cfaee6fab142e1ed9bbd9c693e285cc6aca0d555e576"}, 2472 | {file = "pyasn1-0.4.8-py3.4.egg", hash = "sha256:7ab8a544af125fb704feadb008c99a88805126fb525280b2270bb25cc1d78a12"}, 2473 | {file = "pyasn1-0.4.8-py3.5.egg", hash = "sha256:e89bf84b5437b532b0803ba5c9a5e054d21fec423a89952a74f87fa2c9b7bce2"}, 2474 | {file = "pyasn1-0.4.8-py3.6.egg", hash = "sha256:014c0e9976956a08139dc0712ae195324a75e142284d5f87f1a87ee1b068a359"}, 2475 | {file = "pyasn1-0.4.8-py3.7.egg", hash = "sha256:99fcc3c8d804d1bc6d9a099921e39d827026409a58f2a720dcdb89374ea0c776"}, 2476 | {file = "pyasn1-0.4.8.tar.gz", hash = "sha256:aef77c9fb94a3ac588e87841208bdec464471d9871bd5050a287cc9a475cd0ba"}, 2477 | ] 2478 | pyasn1-modules = [ 2479 | {file = "pyasn1-modules-0.2.8.tar.gz", hash = "sha256:905f84c712230b2c592c19470d3ca8d552de726050d1d1716282a1f6146be65e"}, 2480 | {file = "pyasn1_modules-0.2.8-py2.4.egg", hash = "sha256:0fe1b68d1e486a1ed5473f1302bd991c1611d319bba158e98b106ff86e1d7199"}, 2481 | {file = "pyasn1_modules-0.2.8-py2.5.egg", hash = "sha256:fe0644d9ab041506b62782e92b06b8c68cca799e1a9636ec398675459e031405"}, 2482 | {file = "pyasn1_modules-0.2.8-py2.6.egg", hash = "sha256:a99324196732f53093a84c4369c996713eb8c89d360a496b599fb1a9c47fc3eb"}, 2483 | {file = "pyasn1_modules-0.2.8-py2.7.egg", hash = "sha256:0845a5582f6a02bb3e1bde9ecfc4bfcae6ec3210dd270522fee602365430c3f8"}, 2484 | {file = "pyasn1_modules-0.2.8-py2.py3-none-any.whl", hash = "sha256:a50b808ffeb97cb3601dd25981f6b016cbb3d31fbf57a8b8a87428e6158d0c74"}, 2485 | {file = "pyasn1_modules-0.2.8-py3.1.egg", hash = "sha256:f39edd8c4ecaa4556e989147ebf219227e2cd2e8a43c7e7fcb1f1c18c5fd6a3d"}, 2486 | {file = "pyasn1_modules-0.2.8-py3.2.egg", hash = "sha256:b80486a6c77252ea3a3e9b1e360bc9cf28eaac41263d173c032581ad2f20fe45"}, 2487 | {file = "pyasn1_modules-0.2.8-py3.3.egg", hash = "sha256:65cebbaffc913f4fe9e4808735c95ea22d7a7775646ab690518c056784bc21b4"}, 2488 | {file = "pyasn1_modules-0.2.8-py3.4.egg", hash = "sha256:15b7c67fabc7fc240d87fb9aabf999cf82311a6d6fb2c70d00d3d0604878c811"}, 2489 | {file = "pyasn1_modules-0.2.8-py3.5.egg", hash = "sha256:426edb7a5e8879f1ec54a1864f16b882c2837bfd06eee62f2c982315ee2473ed"}, 2490 | {file = "pyasn1_modules-0.2.8-py3.6.egg", hash = "sha256:cbac4bc38d117f2a49aeedec4407d23e8866ea4ac27ff2cf7fb3e5b570df19e0"}, 2491 | {file = "pyasn1_modules-0.2.8-py3.7.egg", hash = "sha256:c29a5e5cc7a3f05926aff34e097e84f8589cd790ce0ed41b67aed6857b26aafd"}, 2492 | ] 2493 | pycparser = [ 2494 | {file = "pycparser-2.21-py2.py3-none-any.whl", hash = "sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9"}, 2495 | {file = "pycparser-2.21.tar.gz", hash = "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206"}, 2496 | ] 2497 | pycryptodomex = [] 2498 | pygments = [] 2499 | pyhopshive = [] 2500 | pyhumps = [] 2501 | pyjks = [] 2502 | pylint = [] 2503 | pymysql = [] 2504 | pyopenssl = [] 2505 | pyparsing = [ 2506 | {file = "pyparsing-2.4.7-py2.py3-none-any.whl", hash = "sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b"}, 2507 | {file = "pyparsing-2.4.7.tar.gz", hash = "sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1"}, 2508 | ] 2509 | pyproject-hooks = [] 2510 | pyrsistent = [] 2511 | pytest = [ 2512 | {file = "pytest-5.4.3-py3-none-any.whl", hash = "sha256:5c0db86b698e8f170ba4582a492248919255fcd4c79b1ee64ace34301fb589a1"}, 2513 | {file = "pytest-5.4.3.tar.gz", hash = "sha256:7979331bfcba207414f5e1263b5a0f8f521d0f457318836a7355531ed1a4c7d8"}, 2514 | ] 2515 | python-dateutil = [ 2516 | {file = "python-dateutil-2.8.2.tar.gz", hash = "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86"}, 2517 | {file = "python_dateutil-2.8.2-py2.py3-none-any.whl", hash = "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9"}, 2518 | ] 2519 | python-json-logger = [] 2520 | pytz = [] 2521 | pytz-deprecation-shim = [ 2522 | {file = "pytz_deprecation_shim-0.1.0.post0-py2.py3-none-any.whl", hash = "sha256:8314c9692a636c8eb3bda879b9f119e350e93223ae83e70e80c31675a0fdc1a6"}, 2523 | {file = "pytz_deprecation_shim-0.1.0.post0.tar.gz", hash = "sha256:af097bae1b616dde5c5744441e2ddc69e74dfdcb0c263129610d85b87445a59d"}, 2524 | ] 2525 | pywin32 = [] 2526 | pywinpty = [] 2527 | pyyaml = [ 2528 | {file = "PyYAML-5.4.1-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:3b2b1824fe7112845700f815ff6a489360226a5609b96ec2190a45e62a9fc922"}, 2529 | {file = "PyYAML-5.4.1-cp27-cp27m-win32.whl", hash = "sha256:129def1b7c1bf22faffd67b8f3724645203b79d8f4cc81f674654d9902cb4393"}, 2530 | {file = "PyYAML-5.4.1-cp27-cp27m-win_amd64.whl", hash = "sha256:4465124ef1b18d9ace298060f4eccc64b0850899ac4ac53294547536533800c8"}, 2531 | {file = "PyYAML-5.4.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:bb4191dfc9306777bc594117aee052446b3fa88737cd13b7188d0e7aa8162185"}, 2532 | {file = "PyYAML-5.4.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:6c78645d400265a062508ae399b60b8c167bf003db364ecb26dcab2bda048253"}, 2533 | {file = "PyYAML-5.4.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:4e0583d24c881e14342eaf4ec5fbc97f934b999a6828693a99157fde912540cc"}, 2534 | {file = "PyYAML-5.4.1-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:72a01f726a9c7851ca9bfad6fd09ca4e090a023c00945ea05ba1638c09dc3347"}, 2535 | {file = "PyYAML-5.4.1-cp36-cp36m-manylinux2014_s390x.whl", hash = "sha256:895f61ef02e8fed38159bb70f7e100e00f471eae2bc838cd0f4ebb21e28f8541"}, 2536 | {file = "PyYAML-5.4.1-cp36-cp36m-win32.whl", hash = "sha256:3bd0e463264cf257d1ffd2e40223b197271046d09dadf73a0fe82b9c1fc385a5"}, 2537 | {file = "PyYAML-5.4.1-cp36-cp36m-win_amd64.whl", hash = "sha256:e4fac90784481d221a8e4b1162afa7c47ed953be40d31ab4629ae917510051df"}, 2538 | {file = "PyYAML-5.4.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:5accb17103e43963b80e6f837831f38d314a0495500067cb25afab2e8d7a4018"}, 2539 | {file = "PyYAML-5.4.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:e1d4970ea66be07ae37a3c2e48b5ec63f7ba6804bdddfdbd3cfd954d25a82e63"}, 2540 | {file = "PyYAML-5.4.1-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:cb333c16912324fd5f769fff6bc5de372e9e7a202247b48870bc251ed40239aa"}, 2541 | {file = "PyYAML-5.4.1-cp37-cp37m-manylinux2014_s390x.whl", hash = "sha256:fe69978f3f768926cfa37b867e3843918e012cf83f680806599ddce33c2c68b0"}, 2542 | {file = "PyYAML-5.4.1-cp37-cp37m-win32.whl", hash = "sha256:dd5de0646207f053eb0d6c74ae45ba98c3395a571a2891858e87df7c9b9bd51b"}, 2543 | {file = "PyYAML-5.4.1-cp37-cp37m-win_amd64.whl", hash = "sha256:08682f6b72c722394747bddaf0aa62277e02557c0fd1c42cb853016a38f8dedf"}, 2544 | {file = "PyYAML-5.4.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d2d9808ea7b4af864f35ea216be506ecec180628aced0704e34aca0b040ffe46"}, 2545 | {file = "PyYAML-5.4.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:8c1be557ee92a20f184922c7b6424e8ab6691788e6d86137c5d93c1a6ec1b8fb"}, 2546 | {file = "PyYAML-5.4.1-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:fd7f6999a8070df521b6384004ef42833b9bd62cfee11a09bda1079b4b704247"}, 2547 | {file = "PyYAML-5.4.1-cp38-cp38-manylinux2014_s390x.whl", hash = "sha256:bfb51918d4ff3d77c1c856a9699f8492c612cde32fd3bcd344af9be34999bfdc"}, 2548 | {file = "PyYAML-5.4.1-cp38-cp38-win32.whl", hash = "sha256:fa5ae20527d8e831e8230cbffd9f8fe952815b2b7dae6ffec25318803a7528fc"}, 2549 | {file = "PyYAML-5.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:0f5f5786c0e09baddcd8b4b45f20a7b5d61a7e7e99846e3c799b05c7c53fa696"}, 2550 | {file = "PyYAML-5.4.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:294db365efa064d00b8d1ef65d8ea2c3426ac366c0c4368d930bf1c5fb497f77"}, 2551 | {file = "PyYAML-5.4.1-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:74c1485f7707cf707a7aef42ef6322b8f97921bd89be2ab6317fd782c2d53183"}, 2552 | {file = "PyYAML-5.4.1-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:d483ad4e639292c90170eb6f7783ad19490e7a8defb3e46f97dfe4bacae89122"}, 2553 | {file = "PyYAML-5.4.1-cp39-cp39-manylinux2014_s390x.whl", hash = "sha256:fdc842473cd33f45ff6bce46aea678a54e3d21f1b61a7750ce3c498eedfe25d6"}, 2554 | {file = "PyYAML-5.4.1-cp39-cp39-win32.whl", hash = "sha256:49d4cdd9065b9b6e206d0595fee27a96b5dd22618e7520c33204a4a3239d5b10"}, 2555 | {file = "PyYAML-5.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:c20cfa2d49991c8b4147af39859b167664f2ad4561704ee74c1de03318e898db"}, 2556 | {file = "PyYAML-5.4.1.tar.gz", hash = "sha256:607774cbba28732bfa802b54baa7484215f530991055bb562efbed5b2f20a45e"}, 2557 | ] 2558 | pyzmq = [] 2559 | qtconsole = [] 2560 | qtpy = [] 2561 | requests = [] 2562 | retry = [ 2563 | {file = "retry-0.9.2-py2.py3-none-any.whl", hash = "sha256:ccddf89761fa2c726ab29391837d4327f819ea14d244c232a1d24c67a2f98606"}, 2564 | {file = "retry-0.9.2.tar.gz", hash = "sha256:f8bfa8b99b69c4506d6f5bd3b0aabf77f98cdb17f3c9fc3f5ca820033336fba4"}, 2565 | ] 2566 | rfc3339-validator = [ 2567 | {file = "rfc3339_validator-0.1.4-py2.py3-none-any.whl", hash = "sha256:24f6ec1eda14ef823da9e36ec7113124b39c04d50a4d3d3a3c2859577e7791fa"}, 2568 | {file = "rfc3339_validator-0.1.4.tar.gz", hash = "sha256:138a2abdf93304ad60530167e51d2dfb9549521a836871b88d7f4695d0022f6b"}, 2569 | ] 2570 | rfc3986-validator = [] 2571 | "ruamel.yaml" = [] 2572 | "ruamel.yaml.clib" = [] 2573 | s3transfer = [] 2574 | scipy = [] 2575 | send2trash = [ 2576 | {file = "Send2Trash-1.8.0-py3-none-any.whl", hash = "sha256:f20eaadfdb517eaca5ce077640cb261c7d2698385a6a0f072a4a5447fd49fa08"}, 2577 | {file = "Send2Trash-1.8.0.tar.gz", hash = "sha256:d2c24762fd3759860a0aff155e45871447ea58d2be6bdd39b5c8f966a0c99c2d"}, 2578 | ] 2579 | six = [ 2580 | {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, 2581 | {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, 2582 | ] 2583 | sniffio = [] 2584 | soupsieve = [] 2585 | sqlalchemy = [] 2586 | stack-data = [] 2587 | ta = [] 2588 | termcolor = [] 2589 | terminado = [] 2590 | thrift = [] 2591 | tinycss2 = [] 2592 | tomli = [ 2593 | {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, 2594 | {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, 2595 | ] 2596 | tomlkit = [] 2597 | toolz = [] 2598 | tornado = [] 2599 | tqdm = [] 2600 | traitlets = [] 2601 | twofish = [] 2602 | typing-extensions = [] 2603 | tzdata = [] 2604 | tzlocal = [] 2605 | uri-template = [] 2606 | urllib3 = [] 2607 | wcwidth = [] 2608 | webcolors = [] 2609 | webencodings = [ 2610 | {file = "webencodings-0.5.1-py2.py3-none-any.whl", hash = "sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78"}, 2611 | {file = "webencodings-0.5.1.tar.gz", hash = "sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923"}, 2612 | ] 2613 | websocket-client = [] 2614 | widgetsnbextension = [] 2615 | wrapt = [] 2616 | zipp = [] 2617 | --------------------------------------------------------------------------------