diff --git a/awswrangler/__init__.py b/awswrangler/__init__.py index c3d5afe1f..17ca698d8 100644 --- a/awswrangler/__init__.py +++ b/awswrangler/__init__.py @@ -18,6 +18,7 @@ exceptions, lakeformation, mysql, + neptune, opensearch, postgresql, quicksight, @@ -47,6 +48,7 @@ "redshift", "lakeformation", "mysql", + "neptune", "postgresql", "secretsmanager", "sqlserver", diff --git a/awswrangler/neptune/__init__.py b/awswrangler/neptune/__init__.py new file mode 100644 index 000000000..4253b20c5 --- /dev/null +++ b/awswrangler/neptune/__init__.py @@ -0,0 +1,22 @@ +"""Utilities Module for Amazon Neptune.""" +from awswrangler.neptune.gremlin_parser import GremlinParser +from awswrangler.neptune.neptune import ( + connect, + execute_gremlin, + execute_opencypher, + execute_sparql, + flatten_nested_df, + to_property_graph, + to_rdf_graph, +) + +__all__ = [ + "execute_gremlin", + "execute_opencypher", + "execute_sparql", + "to_property_graph", + "to_rdf_graph", + "connect", + "GremlinParser", + "flatten_nested_df", +] diff --git a/awswrangler/neptune/_utils.py b/awswrangler/neptune/_utils.py new file mode 100644 index 000000000..ef3f6eb5d --- /dev/null +++ b/awswrangler/neptune/_utils.py @@ -0,0 +1,118 @@ +"""Amazon Neptune Utils Module (PRIVATE).""" + +import logging +from enum import Enum +from typing import Any + +import pandas as pd +from gremlin_python.process.graph_traversal import GraphTraversalSource, __ +from gremlin_python.process.translator import Translator +from gremlin_python.process.traversal import Cardinality, T +from gremlin_python.structure.graph import Graph + +from awswrangler import exceptions +from awswrangler.neptune.client import NeptuneClient + +_logger: logging.Logger = logging.getLogger(__name__) + + +class WriteDFType(Enum): + """Dataframe type enum.""" + + VERTEX = 1 + EDGE = 2 + UPDATE = 3 + + +def write_gremlin_df(client: NeptuneClient, df: pd.DataFrame, mode: WriteDFType, batch_size: int) -> bool: + """Write the provided dataframe using Gremlin. + + Parameters + ---------- + client : NeptuneClient + The Neptune client to write the dataframe + df : pd.DataFrame + The dataframe to write + mode : WriteDFType + The type of dataframe to write + batch_size : int + The size of the batch to write + + Returns + ------- + bool + True if the write operation succeeded + """ + g = Graph().traversal() + # Loop through items in the DF + for (index, row) in df.iterrows(): + # build up a query + if mode == WriteDFType.EDGE: + g = _build_gremlin_edges(g, row.to_dict()) + elif mode == WriteDFType.VERTEX: + g = _build_gremlin_vertices(g, row.to_dict()) + else: + g = _build_gremlin_update(g, row.to_dict()) + # run the query + if index > 0 and index % batch_size == 0: + res = _run_gremlin_insert(client, g) + if res: + g = Graph().traversal() + else: + _logger.debug(res) + raise exceptions.QueryFailed( + """Failed to insert part or all of the data in the DataFrame, please check the log output.""" + ) + + return _run_gremlin_insert(client, g) + + +def _run_gremlin_insert(client: NeptuneClient, g: GraphTraversalSource) -> bool: + translator = Translator("g") + s = translator.translate(g.bytecode) + s = s.replace("Cardinality.", "") # hack to fix parser error for set cardinality + _logger.debug(s) + res = client.write_gremlin(s) + return res + + +def _build_gremlin_update(g: GraphTraversalSource, row: Any) -> GraphTraversalSource: + g = g.V(str(row["~id"])) + g = _build_gremlin_properties(g, row) + + return g + + +def _build_gremlin_vertices(g: GraphTraversalSource, row: Any) -> GraphTraversalSource: + g = g.V(str(row["~id"])).fold().coalesce(__.unfold(), __.addV(row["~label"]).property(T.id, str(row["~id"]))) + g = _build_gremlin_properties(g, row) + + return g + + +def _build_gremlin_edges(g: GraphTraversalSource, row: pd.Series) -> GraphTraversalSource: + g = ( + g.V(str(row["~from"])) + .fold() + .coalesce(__.unfold(), _build_gremlin_vertices(__, {"~id": row["~from"], "~label": "Vertex"})) + .addE(row["~label"]) + .to( + __.V(str(row["~to"])) + .fold() + .coalesce(__.unfold(), _build_gremlin_vertices(__, {"~id": row["~to"], "~label": "Vertex"})) + ) + ) + g = _build_gremlin_properties(g, row) + + return g + + +def _build_gremlin_properties(g: GraphTraversalSource, row: Any) -> GraphTraversalSource: + for (column, value) in row.items(): + if column not in ["~id", "~label", "~to", "~from"]: + if isinstance(value, list) and len(value) > 0: + for item in value: + g = g.property(Cardinality.set_, column, item) + elif not pd.isna(value) and not pd.isnull(value): + g = g.property(column, value) + return g diff --git a/awswrangler/neptune/client.py b/awswrangler/neptune/client.py new file mode 100644 index 000000000..f77029109 --- /dev/null +++ b/awswrangler/neptune/client.py @@ -0,0 +1,275 @@ +"""Amazon NeptuneClient Module.""" + +import logging +from typing import Any, Dict, List, Optional + +import boto3 +import requests +from botocore.auth import SigV4Auth +from botocore.awsrequest import AWSRequest +from gremlin_python.driver import client +from SPARQLWrapper import SPARQLWrapper + +from awswrangler import exceptions +from awswrangler.neptune.gremlin_parser import GremlinParser + +_logger: logging.Logger = logging.getLogger(__name__) + +DEFAULT_PORT = 8182 +NEPTUNE_SERVICE_NAME = "neptune-db" +HTTP_PROTOCOL = "https" +WS_PROTOCOL = "wss" + + +class NeptuneClient: + """Class representing a Neptune cluster connection.""" + + def __init__( + self, + host: str, + port: int = DEFAULT_PORT, + iam_enabled: bool = False, + boto3_session: Optional[boto3.Session] = None, + region: Optional[str] = None, + ): + self.host = host + self.port = port + self.iam_enabled = iam_enabled + self.boto3_session = self.__ensure_session(session=boto3_session) + if region is None: + self.region = self.__get_region_from_session() + else: + self.region = region + self._http_session = requests.Session() + self.gremlin_connection = None + + def __del__(self) -> None: + """Close the Gremlin connection.""" + if isinstance(self.gremlin_connection, client.Client): + self.gremlin_connection.close() + + def __get_region_from_session(self) -> str: + """Extract region from session.""" + region: Optional[str] = self.boto3_session.region_name + if region is not None: + return region + raise exceptions.InvalidArgument("There is no region_name defined on boto3, please configure it.") + + @staticmethod + def __ensure_session(session: boto3.Session = None) -> boto3.Session: + """Ensure that a valid boto3.Session will be returned.""" + if session is not None: + return session + if boto3.DEFAULT_SESSION: + return boto3.DEFAULT_SESSION + + return boto3.Session() + + def _prepare_request( + self, + method: str, + url: str, + *, + data: Any = None, + params: Any = None, + headers: Any = None, + service: str = NEPTUNE_SERVICE_NAME, + ) -> requests.PreparedRequest: + request = requests.Request(method=method, url=url, data=data, params=params, headers=headers) + if self.boto3_session is not None: + aws_request = self._get_aws_request( + method=method, url=url, data=data, params=params, headers=headers, service=service + ) + request.headers = dict(aws_request.headers) + + return request.prepare() + + def _get_aws_request( + self, + method: str, + url: str, + *, + data: Any = None, + params: Any = None, + headers: Any = None, + service: str = NEPTUNE_SERVICE_NAME, + ) -> AWSRequest: + req = AWSRequest(method=method, url=url, data=data, params=params, headers=headers) + if self.iam_enabled: + credentials = self.boto3_session.get_credentials() + try: + frozen_creds = credentials.get_frozen_credentials() + except AttributeError: + _logger.warning("Could not find valid IAM credentials in any the following locations:\n") + _logger.warning( + "env, assume-role, assume-role-with-web-identity, sso, shared-credential-file, custom-process, " + "config-file, ec2-credentials-file, boto-config, container-role, iam-role\n" + ) + _logger.warning( + "Go to https://boto3.amazonaws.com/v1/documentation/api/latest/guide/credentials.html for more " + "details on configuring your IAM credentials." + ) + return req + SigV4Auth(frozen_creds, service, self.region).add_auth(req) + prepared_iam_req = req.prepare() + return prepared_iam_req + return req + + def read_opencypher(self, query: str, headers: Any = None) -> Any: + """Execute the provided openCypher query. + + Parameters + ---------- + query : str + The query to execute + headers : Any, optional + Any additional headers that should be associated with the query. Defaults to None. + + Returns + ------- + Any + The result of the query. + """ + if headers is None: + headers = {} + + if "content-type" not in headers: + headers["content-type"] = "application/x-www-form-urlencoded" + + url = f"{HTTP_PROTOCOL}://{self.host}:{self.port}/openCypher" + data = {"query": query} + + req = self._prepare_request("POST", url, data=data, headers=headers) + res = self._http_session.send(req) + _logger.debug(res) + if res.ok: + return res.json()["results"] + raise exceptions.QueryFailed(f"Status Code: {res.status_code} Reason: {res.reason} Message: {res.text}") + + def read_gremlin(self, query: str, headers: Any = None) -> List[Dict[str, Any]]: + """Execute the provided Gremlin traversal and returns the results. + + Parameters + ---------- + query : str + The Gremlin query + + Returns + ------- + Dict[str, Any] + Dictionary with the results + """ + return self._execute_gremlin(query, headers) + + def write_gremlin(self, query: str) -> bool: + """Execute a Gremlin write query. + + Parameters + ---------- + query (str): The query to execute + + Returns + ------- + bool + The success of the Gremlin write query + """ + res = self._execute_gremlin(query) + _logger.debug(res) + return True + + def _execute_gremlin(self, query: str, headers: Any = None) -> List[Dict[str, Any]]: + try: + c = self._get_gremlin_connection(headers) + result = c.submit(query) + future_results = result.all() + results = future_results.result() + return GremlinParser.gremlin_results_to_dict(results) + except Exception as e: + if isinstance(self.gremlin_connection, client.Client): + self.gremlin_connection.close() + self.gremlin_connection = None + _logger.error(e) + raise exceptions.QueryFailed(e) + + def _get_gremlin_connection(self, headers: Any = None) -> client.Client: + if self.gremlin_connection is None: + uri = f"{HTTP_PROTOCOL}://{self.host}:{self.port}/gremlin" + request = self._prepare_request("GET", uri, headers=headers) + ws_url = f"{WS_PROTOCOL}://{self.host}:{self.port}/gremlin" + self.gremlin_connection = client.Client( + ws_url, "g", headers=dict(request.headers), call_from_event_loop=True + ) + return self.gremlin_connection + + def read_sparql(self, query: str, headers: Any = None) -> Any: + """Execute the given query and returns the results. + + Parameters + ---------- + query : str + The SPARQL query to execute + headers : Any, optional + Any additional headers to include with the request. Defaults to None. + + Returns + ------- + Any + [description] + """ + res = self._execute_sparql(query, headers) + _logger.debug(res) + return res + + def write_sparql(self, query: str, headers: Any = None) -> bool: + """Execute the specified SPARQL write statements. + + Parameters + ---------- + query : str + The SPARQL query to execute + headers : Any, optional + Any additional headers to include with the request. Defaults to None. + + Returns + ------- + bool + The success of the query + """ + self._execute_sparql(query, headers) + return True + + def _execute_sparql(self, query: str, headers: Any) -> Any: + if headers is None: + headers = {} + + s = SPARQLWrapper("") + s.setQuery(query) + query_type = s.queryType.upper() + if query_type in ["SELECT", "CONSTRUCT", "ASK", "DESCRIBE"]: + data = {"query": query} + else: + data = {"update": query} + + if "content-type" not in headers: + headers["content-type"] = "application/x-www-form-urlencoded" + + uri = f"{HTTP_PROTOCOL}://{self.host}:{self.port}/sparql" + req = self._prepare_request("POST", uri, data=data, headers=headers) + res = self._http_session.send(req) + _logger.debug(res) + if res.ok: + return res.json() + raise exceptions.QueryFailed(f"Status Code: {res.status_code} Reason: {res.reason} Message: {res.text}") + + def status(self) -> Any: + """Return the status of the Neptune cluster. + + Returns + ------- + str + The result of the call to the status API for the Neptune cluster + """ + url = f"{HTTP_PROTOCOL}://{self.host}:{self.port}/status" + req = self._prepare_request("GET", url, data="") + res = self._http_session.send(req) + return res.json() diff --git a/awswrangler/neptune/gremlin_parser.py b/awswrangler/neptune/gremlin_parser.py new file mode 100644 index 000000000..6d095e725 --- /dev/null +++ b/awswrangler/neptune/gremlin_parser.py @@ -0,0 +1,73 @@ +"""Amazon Neptune GremlinParser Module (PRIVATE).""" +from typing import Any, Dict, List + +from gremlin_python.structure.graph import Edge, Path, Property, Vertex, VertexProperty + + +class GremlinParser: + """Class representing a parser for returning Gremlin results as a dictionary.""" + + @staticmethod + def gremlin_results_to_dict(result: Any) -> List[Dict[str, Any]]: + """Take a Gremlin ResultSet and return a dictionary. + + Parameters + ---------- + result : Any + The Gremlin resultset to convert + + Returns + ------- + List[Dict[str, Any]] + A list of dictionary results + """ + res = [] + + # For lists or paths unwind them + if isinstance(result, (list, Path)): + for x in result: + res.append(GremlinParser._parse_dict(x)) + + # For dictionaries just add them + elif isinstance(result, dict): + res.append(result) + + # For everything else parse them + else: + res.append(GremlinParser._parse_dict(result)) + return res + + @staticmethod + def _parse_dict(data: Any) -> Any: + d: Dict[str, Any] = {} + + # If this is a list or Path then unwind it + if isinstance(data, (list, Path)): + res = [] + for x in data: + res.append(GremlinParser._parse_dict(x)) + return res + + # If this is an element then make it a dictionary + if isinstance(data, (Vertex, Edge, VertexProperty, Property)): + data = data.__dict__ + + # If this is a scalar then create a Map with it + elif not hasattr(data, "__len__") or isinstance(data, str): + data = {0: data} + + for (k, v) in data.items(): + # If the key is a Vertex or an Edge do special processing + if isinstance(k, (Vertex, Edge)): + k = k.id + + # If the value is a list do special processing to make it a scalar if the list is of length 1 + if isinstance(v, list) and len(v) == 1: + d[k] = v[0] + else: + d[k] = v + + # If the value is a Vertex or Edge do special processing + if isinstance(data, (Vertex, Edge, VertexProperty, Property)): + d[k] = d[k].__dict__ + return d diff --git a/awswrangler/neptune/neptune.py b/awswrangler/neptune/neptune.py new file mode 100644 index 000000000..5f8865e44 --- /dev/null +++ b/awswrangler/neptune/neptune.py @@ -0,0 +1,414 @@ +"""Amazon Neptune Module.""" + +import logging +import re +from typing import Any + +import pandas as pd +from gremlin_python.process.graph_traversal import GraphTraversalSource, __ +from gremlin_python.process.translator import Translator +from gremlin_python.process.traversal import Cardinality, T +from gremlin_python.structure.graph import Graph + +from awswrangler import exceptions +from awswrangler.neptune.client import NeptuneClient + +_logger: logging.Logger = logging.getLogger(__name__) + + +def execute_gremlin(client: NeptuneClient, query: str) -> pd.DataFrame: + """Return results of a Gremlin traversal as pandas dataframe. + + Parameters + ---------- + client : neptune.Client + instance of the neptune client to use + traversal : str + The gremlin traversal to execute + + Returns + ------- + Union[pandas.DataFrame, Iterator[pandas.DataFrame]] + Results as Pandas DataFrame + + Examples + -------- + Run a Gremlin Query + + >>> import awswrangler as wr + >>> client = wr.neptune.connect(neptune_endpoint, neptune_port, iam_enabled=False) + >>> df = wr.neptune.execute_gremlin(client, "g.V().limit(1)") + """ + results = client.read_gremlin(query) + df = pd.DataFrame.from_records(results) + return df + + +def execute_opencypher(client: NeptuneClient, query: str) -> pd.DataFrame: + """Return results of a openCypher traversal as pandas dataframe. + + Parameters + ---------- + client : NeptuneClient + instance of the neptune client to use + query : str + The openCypher query to execute + + Returns + ------- + Union[pandas.DataFrame, Iterator[pandas.DataFrame]] + Results as Pandas DataFrame + + Examples + -------- + Run an openCypher query + + >>> import awswrangler as wr + >>> client = wr.neptune.connect(neptune_endpoint, neptune_port, iam_enabled=False) + >>> resp = wr.neptune.execute_opencypher(client, "MATCH (n) RETURN n LIMIT 1") + """ + resp = client.read_opencypher(query) + df = pd.DataFrame.from_dict(resp) + return df + + +def execute_sparql(client: NeptuneClient, query: str) -> pd.DataFrame: + """Return results of a SPARQL query as pandas dataframe. + + Parameters + ---------- + client : NeptuneClient + instance of the neptune client to use + query : str + The SPARQL traversal to execute + + Returns + ------- + Union[pandas.DataFrame, Iterator[pandas.DataFrame]] + Results as Pandas DataFrame + + Examples + -------- + Run a SPARQL query + + >>> import awswrangler as wr + >>> client = wr.neptune.connect(neptune_endpoint, neptune_port, iam_enabled=False) + >>> df = wr.neptune.execute_sparql(client, "PREFIX foaf: + SELECT ?name + WHERE { + ?person foaf:name ?name . + """ + data = client.read_sparql(query) + df = None + if "results" in data and "bindings" in data["results"]: + df = pd.DataFrame(data["results"]["bindings"]) + df.applymap(lambda x: x["value"]) + else: + df = pd.DataFrame(data) + + return df + + +def to_property_graph( + client: NeptuneClient, df: pd.DataFrame, batch_size: int = 50, use_header_cardinality: bool = True +) -> bool: + """Write records stored in a DataFrame into Amazon Neptune. + + If writing to a property graph then DataFrames for vertices and edges must be written separately. + DataFrames for vertices must have a ~label column with the label and a ~id column for the vertex id. + If the ~id column does not exist, the specified id does not exists, or is empty then a new vertex will be added. + If no ~label column exists an exception will be thrown. + DataFrames for edges must have a ~id, ~label, ~to, and ~from column. If the ~id column does not exist + the specified id does not exists, or is empty then a new edge will be added. If no ~label, ~to, or ~from column + exists an exception will be thrown. + + If you would like to save data using `single` cardinality then you can postfix (single) to the column header and + set use_header_cardinality=True (default). e.g. A column named `name(single)` will save the `name` property + as single + cardinality. You can disable this by setting by setting `use_header_cardinality=False`. + + Parameters + ---------- + client : NeptuneClient + instance of the neptune client to use + df : pandas.DataFrame + Pandas DataFrame https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.html + batch_size: The number of rows to save at a time. Default 50 + use_header_cardinality: If True, then the header cardinality will be used to save the data. Default True + + Returns + ------- + bool + True if records were written + + Examples + -------- + Writing to Amazon Neptune + + >>> import awswrangler as wr + >>> client = wr.neptune.connect(neptune_endpoint, neptune_port, iam_enabled=False) + >>> wr.neptune.gremlin.to_property_graph( + ... df=df + ... ) + """ + # check if ~id and ~label column exist and if not throw error + g = Graph().traversal() + is_edge_df = False + is_update_df = True + if "~id" in df.columns: + if "~label" in df.columns: + is_update_df = False + if "~to" in df.columns and "~from" in df.columns: + is_edge_df = True + else: + raise exceptions.InvalidArgumentValue( + "Dataframe must contain at least a ~id and a ~label column to be saved to Amazon Neptune" + ) + + # Loop through items in the DF + for (index, row) in df.iterrows(): + # build up a query + if is_update_df: + g = _build_gremlin_update(g, row, use_header_cardinality) + elif is_edge_df: + g = _build_gremlin_insert_edges(g, row.to_dict(), use_header_cardinality) + else: + g = _build_gremlin_insert_vertices(g, row.to_dict(), use_header_cardinality) + # run the query + if index > 0 and index % batch_size == 0: + res = _run_gremlin_insert(client, g) + if res: + g = Graph().traversal() + + return _run_gremlin_insert(client, g) + + +def to_rdf_graph( + client: NeptuneClient, + df: pd.DataFrame, + batch_size: int = 50, + subject_column: str = "s", + predicate_column: str = "p", + object_column: str = "o", + graph_column: str = "g", +) -> bool: + """Write records stored in a DataFrame into Amazon Neptune. + + The DataFrame must consist of triples with column names for the subject, predicate, and object specified. + If you want to add data into a named graph then you will also need the graph column. + + Parameters + ---------- + client (NeptuneClient) : + instance of the neptune client to use + df (pandas.DataFrame) : + Pandas DataFrame https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.html + subject_column (str, optional) : + The column name in the dataframe for the subject. Defaults to 's' + predicate_column (str, optional) : + The column name in the dataframe for the predicate. Defaults to 'p' + object_column (str, optional) : + The column name in the dataframe for the object. Defaults to 'o' + graph_column (str, optional) : + The column name in the dataframe for the graph if sending across quads. Defaults to 'g' + + Returns + ------- + bool + True if records were written + + Examples + -------- + Writing to Amazon Neptune + + >>> import awswrangler as wr + >>> client = wr.neptune.connect(neptune_endpoint, neptune_port, iam_enabled=False) + >>> wr.neptune.gremlin.to_rdf_graph( + ... df=df + ... ) + """ + is_quads = False + if pd.Series([subject_column, object_column, predicate_column]).isin(df.columns).all(): + if graph_column in df.columns: + is_quads = True + else: + raise exceptions.InvalidArgumentValue( + """Dataframe must contain at least the subject, predicate, and object columns defined or the defaults + (s, p, o) to be saved to Amazon Neptune""" + ) + + query = "" + # Loop through items in the DF + for (index, row) in df.iterrows(): + # build up a query + if is_quads: + insert = f"""INSERT DATA {{ GRAPH <{row[graph_column]}> {{<{row[subject_column]}> + <{str(row[predicate_column])}> <{row[object_column]}> . }} }}; """ + query = query + insert + else: + insert = f"""INSERT DATA {{ <{row[subject_column]}> <{str(row[predicate_column])}> + <{row[object_column]}> . }}; """ + query = query + insert + # run the query + if index > 0 and index % batch_size == 0: + res = client.write_sparql(query) + if res: + query = "" + return client.write_sparql(query) + + +def connect(host: str, port: int, iam_enabled: bool = False, **kwargs: Any) -> NeptuneClient: + """Create a connection to a Neptune cluster. + + Parameters + ---------- + host : str + The host endpoint to connect to + port : int + The port endpoint to connect to + iam_enabled : bool, optional + True if IAM is enabled on the cluster. Defaults to False. + + Returns + ------- + NeptuneClient + [description] + """ + return NeptuneClient(host, port, iam_enabled, **kwargs) + + +def _get_column_name(column: str) -> str: + if "(single)" in column.lower(): + return re.compile(r"\(single\)", re.IGNORECASE).sub("", column) + return column + + +def _set_properties(g: GraphTraversalSource, use_header_cardinality: bool, row: Any) -> GraphTraversalSource: + for (column, value) in row.items(): + if column not in ["~id", "~label", "~to", "~from"]: + # If the column header is specifying the cardinality then use it + if use_header_cardinality: + if column.lower().find("(single)") > 0: + g = g.property(Cardinality.single, _get_column_name(column), value) + else: + g = _expand_properties(g, _get_column_name(column), value) + else: + # If not using header cardinality then use the default of set + g = _expand_properties(g, column, value) + return g + + +def _expand_properties(g: GraphTraversalSource, column: str, value: Any) -> GraphTraversalSource: + # If this is a list then expand it out into multiple property calls + if isinstance(value, list) and len(value) > 0: + for item in value: + g = g.property(Cardinality.set_, column, item) + else: + g = g.property(Cardinality.set_, column, value) + return g + + +def _build_gremlin_update(g: GraphTraversalSource, row: Any, use_header_cardinality: bool) -> GraphTraversalSource: + g = g.V(str(row["~id"])) + g = _set_properties(g, use_header_cardinality, row) + return g + + +def _build_gremlin_insert_vertices( + g: GraphTraversalSource, row: Any, use_header_cardinality: bool = False +) -> GraphTraversalSource: + g = g.V(str(row["~id"])).fold().coalesce(__.unfold(), __.addV(row["~label"]).property(T.id, str(row["~id"]))) + g = _set_properties(g, use_header_cardinality, row) + return g + + +def _build_gremlin_insert_edges( + g: GraphTraversalSource, row: pd.Series, use_header_cardinality: bool +) -> GraphTraversalSource: + g = ( + g.V(str(row["~from"])) + .fold() + .coalesce(__.unfold(), _build_gremlin_insert_vertices(__, {"~id": row["~from"], "~label": "Vertex"})) + .addE(row["~label"]) + .property(T.id, str(row["~id"])) + .to( + __.V(str(row["~to"])) + .fold() + .coalesce(__.unfold(), _build_gremlin_insert_vertices(__, {"~id": row["~to"], "~label": "Vertex"})) + ) + ) + g = _set_properties(g, use_header_cardinality, row) + + return g + + +def _run_gremlin_insert(client: NeptuneClient, g: GraphTraversalSource) -> bool: + translator = Translator("g") + s = translator.translate(g.bytecode) + s = s.replace("Cardinality.", "") # hack to fix parser error for set cardinality + _logger.debug(s) + res = client.write_gremlin(s) + return res + + +def flatten_nested_df( + df: pd.DataFrame, include_prefix: bool = True, seperator: str = "_", recursive: bool = True +) -> pd.DataFrame: + """Flatten the lists and dictionaries of the input data frame. + + Parameters + ---------- + df : pd.DataFrame + The input data frame + include_prefix : bool, optional + If True, then it will prefix the new column name with the original column name. + Defaults to True. + seperator : str, optional + The seperator to use between field names when a dictionary is exploded. + Defaults to "_". + recursive : bool, optional + If True, then this will recurse the fields in the data frame. Defaults to True. + + Returns + ------- + pd.DataFrame: The flattened data frame + """ + if seperator is None: + seperator = "_" + df = df.reset_index() + + # search for list and map + s = (df.applymap(type) == list).all() + list_columns = s[s].index.tolist() + + s = (df.applymap(type) == dict).all() + dict_columns = s[s].index.tolist() + + if len(list_columns) > 0 or len(dict_columns) > 0: + new_columns = [] + + for col in dict_columns: + # expand dictionaries horizontally + expanded = None + if include_prefix: + expanded = pd.json_normalize(df[col], sep=seperator).add_prefix(f"{col}{seperator}") + else: + expanded = pd.json_normalize(df[col], sep=seperator).add_prefix(f"{seperator}") + expanded.index = df.index + df = pd.concat([df, expanded], axis=1).drop(columns=[col]) + new_columns.extend(expanded.columns) + + for col in list_columns: + df = df.drop(columns=[col]).join(df[col].explode().to_frame()) + new_columns.append(col) + + # check if there are still dict o list fields to flatten + s = (df[new_columns].applymap(type) == list).all() + list_columns = s[s].index.tolist() + + s = (df[new_columns].applymap(type) == dict).all() + dict_columns = s[s].index.tolist() + if recursive and (len(list_columns) > 0 or len(dict_columns) > 0): + df = flatten_nested_df(df, include_prefix=include_prefix, seperator=seperator, recursive=recursive) + + return df diff --git a/docs/source/api.rst b/docs/source/api.rst index 0caecc332..8222aa20e 100644 --- a/docs/source/api.rst +++ b/docs/source/api.rst @@ -12,6 +12,7 @@ API Reference * `Data API Redshift`_ * `Data API RDS`_ * `OpenSearch`_ +* `Amazon Neptune`_ * `DynamoDB`_ * `Amazon Timestream`_ * `Amazon EMR`_ @@ -240,6 +241,22 @@ OpenSearch search search_by_sql +Amazon Neptune +-------------- + +.. currentmodule:: awswrangler.neptune + +.. autosummary:: + :toctree: stubs + + connect + execute_gremlin + execute_opencypher + execute_sparql + flatten_nested_df + to_property_graph + to_rdf_graph + DynamoDB -------- diff --git a/poetry.lock b/poetry.lock index 4cedd3f2f..7c8007ac5 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,3 +1,45 @@ +[[package]] +name = "aenum" +version = "2.2.6" +description = "Advanced Enumerations (compatible with Python's stdlib Enum), NamedTuples, and NamedConstants" +category = "main" +optional = false +python-versions = "*" + +[[package]] +name = "aiohttp" +version = "3.8.1" +description = "Async http client/server framework (asyncio)" +category = "main" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +aiosignal = ">=1.1.2" +async-timeout = ">=4.0.0a3,<5.0" +asynctest = {version = "0.13.0", markers = "python_version < \"3.8\""} +attrs = ">=17.3.0" +charset-normalizer = ">=2.0,<3.0" +frozenlist = ">=1.1.1" +idna-ssl = {version = ">=1.0", markers = "python_version < \"3.7\""} +multidict = ">=4.5,<7.0" +typing-extensions = {version = ">=3.7.4", markers = "python_version < \"3.8\""} +yarl = ">=1.0,<2.0" + +[package.extras] +speedups = ["aiodns", "brotli", "cchardet"] + +[[package]] +name = "aiosignal" +version = "1.2.0" +description = "aiosignal: a list of registered asynchronous callbacks" +category = "main" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +frozenlist = ">=1.1.0" + [[package]] name = "alabaster" version = "0.7.12" @@ -69,7 +111,7 @@ tests = ["pytest"] [[package]] name = "asn1crypto" -version = "1.4.0" +version = "1.5.1" description = "Fast ASN.1 parser and serializer with definitions for private keys, public keys, certificates, CRL, OCSP, CMS, PKCS#3, PKCS#7, PKCS#8, PKCS#12, PKCS#5, X.509 and TSP" category = "main" optional = false @@ -97,6 +139,25 @@ category = "dev" optional = false python-versions = ">=3.5" +[[package]] +name = "async-timeout" +version = "4.0.2" +description = "Timeout context manager for asyncio programs" +category = "main" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +typing-extensions = {version = ">=3.6.5", markers = "python_version < \"3.8\""} + +[[package]] +name = "asynctest" +version = "0.13.0" +description = "Enhance the standard unittest package with features for testing asyncio libraries" +category = "main" +optional = false +python-versions = ">=3.5" + [[package]] name = "atomicwrites" version = "1.4.0" @@ -109,7 +170,7 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" name = "attrs" version = "21.4.0" description = "Classes Without Boilerplate" -category = "dev" +category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" @@ -138,6 +199,14 @@ category = "dev" optional = false python-versions = "*" +[[package]] +name = "backoff" +version = "1.11.1" +description = "Function decoration for backoff and retry" +category = "main" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" + [[package]] name = "beautifulsoup4" version = "4.10.0" @@ -192,15 +261,15 @@ webencodings = "*" [[package]] name = "boto3" -version = "1.20.54" +version = "1.21.22" description = "The AWS SDK for Python" category = "main" optional = false python-versions = ">= 3.6" [package.dependencies] -botocore = ">=1.23.54,<1.24.0" -jmespath = ">=0.7.1,<1.0.0" +botocore = ">=1.24.22,<1.25.0" +jmespath = ">=0.7.1,<2.0.0" s3transfer = ">=0.5.0,<0.6.0" [package.extras] @@ -208,19 +277,19 @@ crt = ["botocore[crt] (>=1.21.0,<2.0a0)"] [[package]] name = "botocore" -version = "1.23.54" +version = "1.24.22" description = "Low-level, data-driven core of boto 3." category = "main" optional = false python-versions = ">= 3.6" [package.dependencies] -jmespath = ">=0.7.1,<1.0.0" +jmespath = ">=0.7.1,<2.0.0" python-dateutil = ">=2.1,<3.0.0" urllib3 = ">=1.25.4,<1.27" [package.extras] -crt = ["awscrt (==0.12.5)"] +crt = ["awscrt (==0.13.5)"] [[package]] name = "bump2version" @@ -262,7 +331,7 @@ unicode_backport = ["unicodedata2"] [[package]] name = "click" -version = "8.0.3" +version = "8.0.4" description = "Composable command line interface toolkit" category = "dev" optional = false @@ -307,7 +376,7 @@ toml = ["tomli"] [[package]] name = "cryptography" -version = "36.0.1" +version = "36.0.2" description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." category = "dev" optional = false @@ -431,6 +500,14 @@ mccabe = ">=0.6.0,<0.7.0" pycodestyle = ">=2.8.0,<2.9.0" pyflakes = ">=2.4.0,<2.5.0" +[[package]] +name = "frozenlist" +version = "1.2.0" +description = "A list-like structure which implements collections.abc.MutableSequence" +category = "main" +optional = false +python-versions = ">=3.6" + [[package]] name = "fsspec" version = "2022.1.0" @@ -461,6 +538,21 @@ sftp = ["paramiko"] smb = ["smbprotocol"] ssh = ["paramiko"] +[[package]] +name = "gremlinpython" +version = "3.5.2" +description = "Gremlin-Python for Apache TinkerPop" +category = "main" +optional = false +python-versions = "*" + +[package.dependencies] +aenum = ">=1.4.5,<3.0.0" +aiohttp = ">=3.8.0,<=3.8.1" +isodate = ">=0.6.0,<1.0.0" +nest-asyncio = "*" +six = ">=1.10.0,<2.0.0" + [[package]] name = "idna" version = "3.3" @@ -469,6 +561,17 @@ category = "main" optional = false python-versions = ">=3.5" +[[package]] +name = "idna-ssl" +version = "1.1.0" +description = "Patch ssl.match_hostname for Unicode(idna) domains support" +category = "main" +optional = false +python-versions = "*" + +[package.dependencies] +idna = ">=2.0" + [[package]] name = "imagesize" version = "1.3.0" @@ -588,6 +691,17 @@ category = "dev" optional = false python-versions = "*" +[[package]] +name = "isodate" +version = "0.6.1" +description = "An ISO 8601 date/time/duration parser and formatter" +category = "main" +optional = false +python-versions = "*" + +[package.dependencies] +six = "*" + [[package]] name = "isort" version = "5.10.1" @@ -703,7 +817,7 @@ test = ["codecov", "coverage", "ipykernel", "ipython", "mock", "mypy", "pre-comm [[package]] name = "jupyter-core" -version = "4.9.1" +version = "4.9.2" description = "Jupyter core package. A base package on which Jupyter projects rely." category = "dev" optional = false @@ -805,7 +919,7 @@ python-versions = ">=3.6" [[package]] name = "lxml" -version = "4.7.1" +version = "4.8.0" description = "Powerful and Pythonic XML processing library combining libxml2/libxslt with the ElementTree API." category = "main" optional = false @@ -843,11 +957,11 @@ python-versions = "*" [[package]] name = "moto" -version = "3.0.3" +version = "3.1.1" description = "A library that allows your python tests to easily mock out the boto library" category = "dev" optional = false -python-versions = "*" +python-versions = ">=3.6" [package.dependencies] boto3 = ">=1.9.201" @@ -865,7 +979,7 @@ xmltodict = "*" [package.extras] all = ["PyYAML (>=5.1)", "python-jose[cryptography] (>=3.1.0,<4.0.0)", "ecdsa (!=0.15)", "docker (>=2.5.1)", "graphql-core", "jsondiff (>=1.1.2)", "aws-xray-sdk (>=0.93,!=0.96)", "idna (>=2.5,<4)", "cfn-lint (>=0.4.0)", "sshpubkeys (>=3.1.0)", "setuptools"] -apigateway = ["python-jose[cryptography] (>=3.1.0,<4.0.0)", "ecdsa (!=0.15)"] +apigateway = ["PyYAML (>=5.1)", "python-jose[cryptography] (>=3.1.0,<4.0.0)", "ecdsa (!=0.15)"] apigatewayv2 = ["PyYAML (>=5.1)"] appsync = ["graphql-core"] awslambda = ["docker (>=2.5.1)"] @@ -873,6 +987,7 @@ batch = ["docker (>=2.5.1)"] cloudformation = ["docker (>=2.5.1)", "PyYAML (>=5.1)", "cfn-lint (>=0.4.0)"] cognitoidp = ["python-jose[cryptography] (>=3.1.0,<4.0.0)", "ecdsa (!=0.15)"] ds = ["sshpubkeys (>=3.1.0)"] +dynamodb = ["docker (>=2.5.1)"] dynamodb2 = ["docker (>=2.5.1)"] dynamodbstreams = ["docker (>=2.5.1)"] ec2 = ["sshpubkeys (>=3.1.0)"] @@ -884,6 +999,14 @@ server = ["PyYAML (>=5.1)", "python-jose[cryptography] (>=3.1.0,<4.0.0)", "ecdsa ssm = ["PyYAML (>=5.1)", "dataclasses"] xray = ["aws-xray-sdk (>=0.93,!=0.96)", "setuptools"] +[[package]] +name = "multidict" +version = "5.2.0" +description = "multidict implementation" +category = "main" +optional = false +python-versions = ">=3.6" + [[package]] name = "mypy" version = "0.910" @@ -1025,13 +1148,13 @@ sphinx = ">=1.8" name = "nest-asyncio" version = "1.5.4" description = "Patch asyncio to allow nested event loops" -category = "dev" +category = "main" optional = false python-versions = ">=3.5" [[package]] name = "notebook" -version = "6.4.8" +version = "6.4.10" description = "A web-based notebook environment for interactive computing" category = "dev" optional = false @@ -1044,7 +1167,7 @@ ipython-genutils = "*" jinja2 = "*" jupyter-client = ">=5.3.4" jupyter-core = ">=4.6.1" -nbconvert = "*" +nbconvert = ">=5" nbformat = "*" nest-asyncio = ">=1.5" prometheus-client = "*" @@ -1599,7 +1722,7 @@ python-versions = "*" [[package]] name = "pywinpty" -version = "2.0.2" +version = "2.0.3" description = "Pseudo terminal support for Windows from Python." category = "dev" optional = false @@ -1617,9 +1740,28 @@ python-versions = ">=3.6" cffi = {version = "*", markers = "implementation_name == \"pypy\""} py = {version = "*", markers = "implementation_name == \"pypy\""} +[[package]] +name = "rdflib" +version = "5.0.0" +description = "RDFLib is a Python library for working with RDF, a simple yet powerful language for representing information." +category = "main" +optional = false +python-versions = "*" + +[package.dependencies] +isodate = "*" +pyparsing = "*" +six = "*" + +[package.extras] +docs = ["sphinx (<3)", "sphinxcontrib-apidoc"] +html = ["html5lib"] +sparql = ["requests"] +tests = ["html5lib", "networkx", "nose", "doctest-ignore-unicode"] + [[package]] name = "redshift-connector" -version = "2.0.904" +version = "2.0.905" description = "Redshift interface library" category = "main" optional = false @@ -1686,7 +1828,7 @@ tests = ["coverage (>=3.7.1,<6.0.0)", "pytest-cov", "pytest-localserver", "flake [[package]] name = "restructuredtext-lint" -version = "1.3.2" +version = "1.4.0" description = "reStructuredText linter" category = "dev" optional = false @@ -1709,7 +1851,7 @@ fsspec = ">=0.6.0" [[package]] name = "s3transfer" -version = "0.5.1" +version = "0.5.2" description = "An Amazon S3 Transfer Manager" category = "main" optional = false @@ -1780,6 +1922,20 @@ category = "main" optional = false python-versions = ">=3.6" +[[package]] +name = "sparqlwrapper" +version = "1.8.5" +description = "SPARQL Endpoint interface to Python" +category = "main" +optional = false +python-versions = "*" + +[package.dependencies] +rdflib = ">=4.0" + +[package.extras] +keepalive = ["keepalive (>=0.5)"] + [[package]] name = "sphinx" version = "4.3.2" @@ -1920,14 +2076,14 @@ test = ["pytest"] [[package]] name = "testpath" -version = "0.5.0" +version = "0.6.0" description = "Test utilities for code working with files and commands" category = "dev" optional = false python-versions = ">= 3.5" [package.extras] -test = ["pytest", "pathlib2"] +test = ["pytest"] [[package]] name = "toml" @@ -2004,26 +2160,26 @@ python-versions = "*" name = "typing-extensions" version = "4.1.1" description = "Backported and Experimental Type Hints for Python 3.6+" -category = "dev" +category = "main" optional = false python-versions = ">=3.6" [[package]] name = "urllib3" -version = "1.26.8" +version = "1.26.9" description = "HTTP library with thread-safe connection pooling, file post, and more." category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4" [package.extras] -brotli = ["brotlipy (>=0.6.0)"] +brotli = ["brotlicffi (>=0.8.0)", "brotli (>=1.0.9)", "brotlipy (>=0.6.0)"] secure = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "certifi", "ipaddress"] socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] [[package]] name = "virtualenv" -version = "20.13.1" +version = "20.13.4" description = "Virtual Python Environment builder" category = "dev" optional = false @@ -2059,7 +2215,7 @@ python-versions = "*" [[package]] name = "websocket-client" -version = "1.2.3" +version = "1.3.1" description = "WebSocket client for Python with low level API options" category = "dev" optional = false @@ -2121,6 +2277,19 @@ category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +[[package]] +name = "yarl" +version = "1.7.2" +description = "Yet another URL library" +category = "main" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +idna = ">=2.0" +multidict = ">=4.0" +typing-extensions = {version = ">=3.7.4", markers = "python_version < \"3.8\""} + [[package]] name = "zipp" version = "3.6.0" @@ -2139,9 +2308,92 @@ sqlserver = ["pyodbc"] [metadata] lock-version = "1.1" python-versions = ">=3.6.2, <3.11" -content-hash = "de3d0a6b2863272884719e0bba489b7e0df29c6621176faab55f6b729043f1da" +content-hash = "80f13438c6033d51c3020003cf52d6df176ec57c5bad69110945a01ec57f2785" [metadata.files] +aenum = [ + {file = "aenum-2.2.6-py2-none-any.whl", hash = "sha256:aaebe735508d9cbc72cd6adfb59660a5e676dfbeb6fb24fb090041e7ddb8d3b3"}, + {file = "aenum-2.2.6-py3-none-any.whl", hash = "sha256:f9d20f7302ce3dc3639b3f75c3b3e146f3b22409a6b4513c1f0bd6dbdfcbd8c1"}, + {file = "aenum-2.2.6.tar.gz", hash = "sha256:260225470b49429f5893a195a8b99c73a8d182be42bf90c37c93e7b20e44eaae"}, +] +aiohttp = [ + {file = "aiohttp-3.8.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:1ed0b6477896559f17b9eaeb6d38e07f7f9ffe40b9f0f9627ae8b9926ae260a8"}, + {file = "aiohttp-3.8.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:7dadf3c307b31e0e61689cbf9e06be7a867c563d5a63ce9dca578f956609abf8"}, + {file = "aiohttp-3.8.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a79004bb58748f31ae1cbe9fa891054baaa46fb106c2dc7af9f8e3304dc30316"}, + {file = "aiohttp-3.8.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:12de6add4038df8f72fac606dff775791a60f113a725c960f2bab01d8b8e6b15"}, + {file = "aiohttp-3.8.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6f0d5f33feb5f69ddd57a4a4bd3d56c719a141080b445cbf18f238973c5c9923"}, + {file = "aiohttp-3.8.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:eaba923151d9deea315be1f3e2b31cc39a6d1d2f682f942905951f4e40200922"}, + {file = "aiohttp-3.8.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:099ebd2c37ac74cce10a3527d2b49af80243e2a4fa39e7bce41617fbc35fa3c1"}, + {file = "aiohttp-3.8.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:2e5d962cf7e1d426aa0e528a7e198658cdc8aa4fe87f781d039ad75dcd52c516"}, + {file = "aiohttp-3.8.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:fa0ffcace9b3aa34d205d8130f7873fcfefcb6a4dd3dd705b0dab69af6712642"}, + {file = "aiohttp-3.8.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:61bfc23df345d8c9716d03717c2ed5e27374e0fe6f659ea64edcd27b4b044cf7"}, + {file = "aiohttp-3.8.1-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:31560d268ff62143e92423ef183680b9829b1b482c011713ae941997921eebc8"}, + {file = "aiohttp-3.8.1-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:01d7bdb774a9acc838e6b8f1d114f45303841b89b95984cbb7d80ea41172a9e3"}, + {file = "aiohttp-3.8.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:97ef77eb6b044134c0b3a96e16abcb05ecce892965a2124c566af0fd60f717e2"}, + {file = "aiohttp-3.8.1-cp310-cp310-win32.whl", hash = "sha256:c2aef4703f1f2ddc6df17519885dbfa3514929149d3ff900b73f45998f2532fa"}, + {file = "aiohttp-3.8.1-cp310-cp310-win_amd64.whl", hash = "sha256:713ac174a629d39b7c6a3aa757b337599798da4c1157114a314e4e391cd28e32"}, + {file = "aiohttp-3.8.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:473d93d4450880fe278696549f2e7aed8cd23708c3c1997981464475f32137db"}, + {file = "aiohttp-3.8.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:99b5eeae8e019e7aad8af8bb314fb908dd2e028b3cdaad87ec05095394cce632"}, + {file = "aiohttp-3.8.1-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3af642b43ce56c24d063325dd2cf20ee012d2b9ba4c3c008755a301aaea720ad"}, + {file = "aiohttp-3.8.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c3630c3ef435c0a7c549ba170a0633a56e92629aeed0e707fec832dee313fb7a"}, + {file = "aiohttp-3.8.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:4a4a4e30bf1edcad13fb0804300557aedd07a92cabc74382fdd0ba6ca2661091"}, + {file = "aiohttp-3.8.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:6f8b01295e26c68b3a1b90efb7a89029110d3a4139270b24fda961893216c440"}, + {file = "aiohttp-3.8.1-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:a25fa703a527158aaf10dafd956f7d42ac6d30ec80e9a70846253dd13e2f067b"}, + {file = "aiohttp-3.8.1-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:5bfde62d1d2641a1f5173b8c8c2d96ceb4854f54a44c23102e2ccc7e02f003ec"}, + {file = "aiohttp-3.8.1-cp36-cp36m-musllinux_1_1_ppc64le.whl", hash = "sha256:51467000f3647d519272392f484126aa716f747859794ac9924a7aafa86cd411"}, + {file = "aiohttp-3.8.1-cp36-cp36m-musllinux_1_1_s390x.whl", hash = "sha256:03a6d5349c9ee8f79ab3ff3694d6ce1cfc3ced1c9d36200cb8f08ba06bd3b782"}, + {file = "aiohttp-3.8.1-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:102e487eeb82afac440581e5d7f8f44560b36cf0bdd11abc51a46c1cd88914d4"}, + {file = "aiohttp-3.8.1-cp36-cp36m-win32.whl", hash = "sha256:4aed991a28ea3ce320dc8ce655875e1e00a11bdd29fe9444dd4f88c30d558602"}, + {file = "aiohttp-3.8.1-cp36-cp36m-win_amd64.whl", hash = "sha256:b0e20cddbd676ab8a64c774fefa0ad787cc506afd844de95da56060348021e96"}, + {file = "aiohttp-3.8.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:37951ad2f4a6df6506750a23f7cbabad24c73c65f23f72e95897bb2cecbae676"}, + {file = "aiohttp-3.8.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5c23b1ad869653bc818e972b7a3a79852d0e494e9ab7e1a701a3decc49c20d51"}, + {file = "aiohttp-3.8.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:15b09b06dae900777833fe7fc4b4aa426556ce95847a3e8d7548e2d19e34edb8"}, + {file = "aiohttp-3.8.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:477c3ea0ba410b2b56b7efb072c36fa91b1e6fc331761798fa3f28bb224830dd"}, + {file = "aiohttp-3.8.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:2f2f69dca064926e79997f45b2f34e202b320fd3782f17a91941f7eb85502ee2"}, + {file = "aiohttp-3.8.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:ef9612483cb35171d51d9173647eed5d0069eaa2ee812793a75373447d487aa4"}, + {file = "aiohttp-3.8.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:6d69f36d445c45cda7b3b26afef2fc34ef5ac0cdc75584a87ef307ee3c8c6d00"}, + {file = "aiohttp-3.8.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:55c3d1072704d27401c92339144d199d9de7b52627f724a949fc7d5fc56d8b93"}, + {file = "aiohttp-3.8.1-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:b9d00268fcb9f66fbcc7cd9fe423741d90c75ee029a1d15c09b22d23253c0a44"}, + {file = "aiohttp-3.8.1-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:07b05cd3305e8a73112103c834e91cd27ce5b4bd07850c4b4dbd1877d3f45be7"}, + {file = "aiohttp-3.8.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:c34dc4958b232ef6188c4318cb7b2c2d80521c9a56c52449f8f93ab7bc2a8a1c"}, + {file = "aiohttp-3.8.1-cp37-cp37m-win32.whl", hash = "sha256:d2f9b69293c33aaa53d923032fe227feac867f81682f002ce33ffae978f0a9a9"}, + {file = "aiohttp-3.8.1-cp37-cp37m-win_amd64.whl", hash = "sha256:6ae828d3a003f03ae31915c31fa684b9890ea44c9c989056fea96e3d12a9fa17"}, + {file = "aiohttp-3.8.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:0c7ebbbde809ff4e970824b2b6cb7e4222be6b95a296e46c03cf050878fc1785"}, + {file = "aiohttp-3.8.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8b7ef7cbd4fec9a1e811a5de813311ed4f7ac7d93e0fda233c9b3e1428f7dd7b"}, + {file = "aiohttp-3.8.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:c3d6a4d0619e09dcd61021debf7059955c2004fa29f48788a3dfaf9c9901a7cd"}, + {file = "aiohttp-3.8.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:718626a174e7e467f0558954f94af117b7d4695d48eb980146016afa4b580b2e"}, + {file = "aiohttp-3.8.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:589c72667a5febd36f1315aa6e5f56dd4aa4862df295cb51c769d16142ddd7cd"}, + {file = "aiohttp-3.8.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2ed076098b171573161eb146afcb9129b5ff63308960aeca4b676d9d3c35e700"}, + {file = "aiohttp-3.8.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:086f92daf51a032d062ec5f58af5ca6a44d082c35299c96376a41cbb33034675"}, + {file = "aiohttp-3.8.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:11691cf4dc5b94236ccc609b70fec991234e7ef8d4c02dd0c9668d1e486f5abf"}, + {file = "aiohttp-3.8.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:31d1e1c0dbf19ebccbfd62eff461518dcb1e307b195e93bba60c965a4dcf1ba0"}, + {file = "aiohttp-3.8.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:11a67c0d562e07067c4e86bffc1553f2cf5b664d6111c894671b2b8712f3aba5"}, + {file = "aiohttp-3.8.1-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:bb01ba6b0d3f6c68b89fce7305080145d4877ad3acaed424bae4d4ee75faa950"}, + {file = "aiohttp-3.8.1-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:44db35a9e15d6fe5c40d74952e803b1d96e964f683b5a78c3cc64eb177878155"}, + {file = "aiohttp-3.8.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:844a9b460871ee0a0b0b68a64890dae9c415e513db0f4a7e3cab41a0f2fedf33"}, + {file = "aiohttp-3.8.1-cp38-cp38-win32.whl", hash = "sha256:7d08744e9bae2ca9c382581f7dce1273fe3c9bae94ff572c3626e8da5b193c6a"}, + {file = "aiohttp-3.8.1-cp38-cp38-win_amd64.whl", hash = "sha256:04d48b8ce6ab3cf2097b1855e1505181bdd05586ca275f2505514a6e274e8e75"}, + {file = "aiohttp-3.8.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:f5315a2eb0239185af1bddb1abf472d877fede3cc8d143c6cddad37678293237"}, + {file = "aiohttp-3.8.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a996d01ca39b8dfe77440f3cd600825d05841088fd6bc0144cc6c2ec14cc5f74"}, + {file = "aiohttp-3.8.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:13487abd2f761d4be7c8ff9080de2671e53fff69711d46de703c310c4c9317ca"}, + {file = "aiohttp-3.8.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ea302f34477fda3f85560a06d9ebdc7fa41e82420e892fc50b577e35fc6a50b2"}, + {file = "aiohttp-3.8.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a2f635ce61a89c5732537a7896b6319a8fcfa23ba09bec36e1b1ac0ab31270d2"}, + {file = "aiohttp-3.8.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e999f2d0e12eea01caeecb17b653f3713d758f6dcc770417cf29ef08d3931421"}, + {file = "aiohttp-3.8.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:0770e2806a30e744b4e21c9d73b7bee18a1cfa3c47991ee2e5a65b887c49d5cf"}, + {file = "aiohttp-3.8.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:d15367ce87c8e9e09b0f989bfd72dc641bcd04ba091c68cd305312d00962addd"}, + {file = "aiohttp-3.8.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:6c7cefb4b0640703eb1069835c02486669312bf2f12b48a748e0a7756d0de33d"}, + {file = "aiohttp-3.8.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:71927042ed6365a09a98a6377501af5c9f0a4d38083652bcd2281a06a5976724"}, + {file = "aiohttp-3.8.1-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:28d490af82bc6b7ce53ff31337a18a10498303fe66f701ab65ef27e143c3b0ef"}, + {file = "aiohttp-3.8.1-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:b6613280ccedf24354406caf785db748bebbddcf31408b20c0b48cb86af76866"}, + {file = "aiohttp-3.8.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:81e3d8c34c623ca4e36c46524a3530e99c0bc95ed068fd6e9b55cb721d408fb2"}, + {file = "aiohttp-3.8.1-cp39-cp39-win32.whl", hash = "sha256:7187a76598bdb895af0adbd2fb7474d7f6025d170bc0a1130242da817ce9e7d1"}, + {file = "aiohttp-3.8.1-cp39-cp39-win_amd64.whl", hash = "sha256:1c182cb873bc91b411e184dab7a2b664d4fea2743df0e4d57402f7f3fa644bac"}, + {file = "aiohttp-3.8.1.tar.gz", hash = "sha256:fc5471e1a54de15ef71c1bc6ebe80d4dc681ea600e68bfd1cbce40427f0b7578"}, +] +aiosignal = [ + {file = "aiosignal-1.2.0-py3-none-any.whl", hash = "sha256:26e62109036cd181df6e6ad646f91f0dcfd05fe16d0cb924138ff2ab75d64e3a"}, + {file = "aiosignal-1.2.0.tar.gz", hash = "sha256:78ed67db6c7b7ced4f98e495e572106d5c432a93e1ddd1bf475e1dc05f5b7df2"}, +] alabaster = [ {file = "alabaster-0.7.12-py2.py3-none-any.whl", hash = "sha256:446438bdcca0e05bd45ea2de1668c1d9b032e1a9154c2c259092d77031ddd359"}, {file = "alabaster-0.7.12.tar.gz", hash = "sha256:a661d72d58e6ea8a57f7a86e37d86716863ee5e92788398526d58b26a4e4dc02"}, @@ -2182,8 +2434,8 @@ argon2-cffi-bindings = [ {file = "argon2_cffi_bindings-21.2.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:5e00316dabdaea0b2dd82d141cc66889ced0cdcbfa599e8b471cf22c620c329a"}, ] asn1crypto = [ - {file = "asn1crypto-1.4.0-py2.py3-none-any.whl", hash = "sha256:4bcdf33c861c7d40bdcd74d8e4dd7661aac320fcdf40b9a3f95b4ee12fde2fa8"}, - {file = "asn1crypto-1.4.0.tar.gz", hash = "sha256:f4f6e119474e58e04a2b1af817eb585b4fd72bdd89b998624712b5c99be7641c"}, + {file = "asn1crypto-1.5.1-py2.py3-none-any.whl", hash = "sha256:db4e40728b728508912cbb3d44f19ce188f218e9eba635821bb4b68564f8fd67"}, + {file = "asn1crypto-1.5.1.tar.gz", hash = "sha256:13ae38502be632115abf8a24cbe5f4da52e3b5231990aff31123c805306ccb9c"}, ] astroid = [ {file = "astroid-2.9.3-py3-none-any.whl", hash = "sha256:506daabe5edffb7e696ad82483ad0228245a9742ed7d2d8c9cdb31537decf9f6"}, @@ -2193,6 +2445,14 @@ async-generator = [ {file = "async_generator-1.10-py3-none-any.whl", hash = "sha256:01c7bf666359b4967d2cda0000cc2e4af16a0ae098cbffcb8472fb9e8ad6585b"}, {file = "async_generator-1.10.tar.gz", hash = "sha256:6ebb3d106c12920aaae42ccb6f787ef5eefdcdd166ea3d628fa8476abe712144"}, ] +async-timeout = [ + {file = "async-timeout-4.0.2.tar.gz", hash = "sha256:2163e1640ddb52b7a8c80d0a67a08587e5d245cc9c553a74a847056bc2976b15"}, + {file = "async_timeout-4.0.2-py3-none-any.whl", hash = "sha256:8ca1e4fcf50d07413d66d1a5e416e42cfdf5851c981d679a09851a6853383b3c"}, +] +asynctest = [ + {file = "asynctest-0.13.0-py3-none-any.whl", hash = "sha256:5da6118a7e6d6b54d83a8f7197769d046922a44d2a99c21382f0a6e4fadae676"}, + {file = "asynctest-0.13.0.tar.gz", hash = "sha256:c27862842d15d83e6a34eb0b2866c323880eb3a75e4485b079ea11748fd77fac"}, +] atomicwrites = [ {file = "atomicwrites-1.4.0-py2.py3-none-any.whl", hash = "sha256:6d1784dea7c0c8d4a5172b6c620f40b6e4cbfdf96d783691f2e1302a7b88e197"}, {file = "atomicwrites-1.4.0.tar.gz", hash = "sha256:ae70396ad1a434f9c7046fd2dd196fc04b12f9e91ffb859164193be8b6168a7a"}, @@ -2209,6 +2469,10 @@ backcall = [ {file = "backcall-0.2.0-py2.py3-none-any.whl", hash = "sha256:fbbce6a29f263178a1f7915c1940bde0ec2b2a967566fe1c65c1dfb7422bd255"}, {file = "backcall-0.2.0.tar.gz", hash = "sha256:5cbdbf27be5e7cfadb448baf0aa95508f91f2bbc6c6437cd9cd06e2a4c215e1e"}, ] +backoff = [ + {file = "backoff-1.11.1-py2.py3-none-any.whl", hash = "sha256:61928f8fa48d52e4faa81875eecf308eccfb1016b018bb6bd21e05b5d90a96c5"}, + {file = "backoff-1.11.1.tar.gz", hash = "sha256:ccb962a2378418c667b3c979b504fdeb7d9e0d29c0579e3b13b86467177728cb"}, +] beautifulsoup4 = [ {file = "beautifulsoup4-4.10.0-py3-none-any.whl", hash = "sha256:9a315ce70049920ea4572a4055bc4bd700c940521d36fc858205ad4fcde149bf"}, {file = "beautifulsoup4-4.10.0.tar.gz", hash = "sha256:c23ad23c521d818955a4151a67d81580319d4bf548d3d49f4223ae041ff98891"}, @@ -2243,12 +2507,12 @@ bleach = [ {file = "bleach-4.1.0.tar.gz", hash = "sha256:0900d8b37eba61a802ee40ac0061f8c2b5dee29c1927dd1d233e075ebf5a71da"}, ] boto3 = [ - {file = "boto3-1.20.54-py3-none-any.whl", hash = "sha256:1a272a1dd36414b1626a47bb580425203be0b5a34caa117f38a5e18adf21f918"}, - {file = "boto3-1.20.54.tar.gz", hash = "sha256:8129ad42cc0120d1c63daa18512d6f0b1439e385b2b6e0fe987f116bdf795546"}, + {file = "boto3-1.21.22-py3-none-any.whl", hash = "sha256:a56e34d8dc3390006a6d7ae5373f357917932045e874c82de2736f3b42c02b10"}, + {file = "boto3-1.21.22.tar.gz", hash = "sha256:334f14ffbd89ddd15090e90b32e4fcea73d83b60b19ca2737a9264fd44096f35"}, ] botocore = [ - {file = "botocore-1.23.54-py3-none-any.whl", hash = "sha256:06ae8076c4dcf3d72bec4d37e5f2dce4a92a18a8cdaa3bfaa6e3b7b5e30a8d7e"}, - {file = "botocore-1.23.54.tar.gz", hash = "sha256:4bb9ba16cccee5f5a2602049bc3e2db6865346b2550667f3013bdf33b0a01ceb"}, + {file = "botocore-1.24.22-py3-none-any.whl", hash = "sha256:e812604653c635c78431b3dd168d3fc04e8c3514839226814c999336d5e59ea0"}, + {file = "botocore-1.24.22.tar.gz", hash = "sha256:92ba8afeda48f5d2467811d87df401d703a25191f82882994d8d09a7d8b5b965"}, ] bump2version = [ {file = "bump2version-1.0.1-py2.py3-none-any.whl", hash = "sha256:37f927ea17cde7ae2d7baf832f8e80ce3777624554a653006c9144f8017fe410"}, @@ -2315,8 +2579,8 @@ charset-normalizer = [ {file = "charset_normalizer-2.0.12-py3-none-any.whl", hash = "sha256:6881edbebdb17b39b4eaaa821b438bf6eddffb4468cf344f09f89def34a8b1df"}, ] click = [ - {file = "click-8.0.3-py3-none-any.whl", hash = "sha256:353f466495adaeb40b6b5f592f9f91cb22372351c84caeb068132442a4518ef3"}, - {file = "click-8.0.3.tar.gz", hash = "sha256:410e932b050f5eed773c4cda94de75971c89cdb3155a72a0831139a79e5ecb5b"}, + {file = "click-8.0.4-py3-none-any.whl", hash = "sha256:6a7a62563bbfabfda3a38f3023a1db4a35978c0abd76f6c9605ecd6554d6d9b1"}, + {file = "click-8.0.4.tar.gz", hash = "sha256:8458d7b1287c5fb128c90e23381cf99dcde74beaf6c7ff6384ce84d6fe090adb"}, ] colorama = [ {file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"}, @@ -2375,26 +2639,26 @@ coverage = [ {file = "coverage-6.2.tar.gz", hash = "sha256:e2cad8093172b7d1595b4ad66f24270808658e11acf43a8f95b41276162eb5b8"}, ] cryptography = [ - {file = "cryptography-36.0.1-cp36-abi3-macosx_10_10_universal2.whl", hash = "sha256:73bc2d3f2444bcfeac67dd130ff2ea598ea5f20b40e36d19821b4df8c9c5037b"}, - {file = "cryptography-36.0.1-cp36-abi3-macosx_10_10_x86_64.whl", hash = "sha256:2d87cdcb378d3cfed944dac30596da1968f88fb96d7fc34fdae30a99054b2e31"}, - {file = "cryptography-36.0.1-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:74d6c7e80609c0f4c2434b97b80c7f8fdfaa072ca4baab7e239a15d6d70ed73a"}, - {file = "cryptography-36.0.1-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:6c0c021f35b421ebf5976abf2daacc47e235f8b6082d3396a2fe3ccd537ab173"}, - {file = "cryptography-36.0.1-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5d59a9d55027a8b88fd9fd2826c4392bd487d74bf628bb9d39beecc62a644c12"}, - {file = "cryptography-36.0.1-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0a817b961b46894c5ca8a66b599c745b9a3d9f822725221f0e0fe49dc043a3a3"}, - {file = "cryptography-36.0.1-cp36-abi3-manylinux_2_24_x86_64.whl", hash = "sha256:94ae132f0e40fe48f310bba63f477f14a43116f05ddb69d6fa31e93f05848ae2"}, - {file = "cryptography-36.0.1-cp36-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:7be0eec337359c155df191d6ae00a5e8bbb63933883f4f5dffc439dac5348c3f"}, - {file = "cryptography-36.0.1-cp36-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:e0344c14c9cb89e76eb6a060e67980c9e35b3f36691e15e1b7a9e58a0a6c6dc3"}, - {file = "cryptography-36.0.1-cp36-abi3-win32.whl", hash = "sha256:4caa4b893d8fad33cf1964d3e51842cd78ba87401ab1d2e44556826df849a8ca"}, - {file = "cryptography-36.0.1-cp36-abi3-win_amd64.whl", hash = "sha256:391432971a66cfaf94b21c24ab465a4cc3e8bf4a939c1ca5c3e3a6e0abebdbcf"}, - {file = "cryptography-36.0.1-pp37-pypy37_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:bb5829d027ff82aa872d76158919045a7c1e91fbf241aec32cb07956e9ebd3c9"}, - {file = "cryptography-36.0.1-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ebc15b1c22e55c4d5566e3ca4db8689470a0ca2babef8e3a9ee057a8b82ce4b1"}, - {file = "cryptography-36.0.1-pp37-pypy37_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:596f3cd67e1b950bc372c33f1a28a0692080625592ea6392987dba7f09f17a94"}, - {file = "cryptography-36.0.1-pp38-pypy38_pp73-macosx_10_10_x86_64.whl", hash = "sha256:30ee1eb3ebe1644d1c3f183d115a8c04e4e603ed6ce8e394ed39eea4a98469ac"}, - {file = "cryptography-36.0.1-pp38-pypy38_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:ec63da4e7e4a5f924b90af42eddf20b698a70e58d86a72d943857c4c6045b3ee"}, - {file = "cryptography-36.0.1-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ca238ceb7ba0bdf6ce88c1b74a87bffcee5afbfa1e41e173b1ceb095b39add46"}, - {file = "cryptography-36.0.1-pp38-pypy38_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:ca28641954f767f9822c24e927ad894d45d5a1e501767599647259cbf030b903"}, - {file = "cryptography-36.0.1-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:39bdf8e70eee6b1c7b289ec6e5d84d49a6bfa11f8b8646b5b3dfe41219153316"}, - {file = "cryptography-36.0.1.tar.gz", hash = "sha256:53e5c1dc3d7a953de055d77bef2ff607ceef7a2aac0353b5d630ab67f7423638"}, + {file = "cryptography-36.0.2-cp36-abi3-macosx_10_10_universal2.whl", hash = "sha256:4e2dddd38a5ba733be6a025a1475a9f45e4e41139d1321f412c6b360b19070b6"}, + {file = "cryptography-36.0.2-cp36-abi3-macosx_10_10_x86_64.whl", hash = "sha256:4881d09298cd0b669bb15b9cfe6166f16fc1277b4ed0d04a22f3d6430cb30f1d"}, + {file = "cryptography-36.0.2-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:ea634401ca02367c1567f012317502ef3437522e2fc44a3ea1844de028fa4b84"}, + {file = "cryptography-36.0.2-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:7be666cc4599b415f320839e36367b273db8501127b38316f3b9f22f17a0b815"}, + {file = "cryptography-36.0.2-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8241cac0aae90b82d6b5c443b853723bcc66963970c67e56e71a2609dc4b5eaf"}, + {file = "cryptography-36.0.2-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7b2d54e787a884ffc6e187262823b6feb06c338084bbe80d45166a1cb1c6c5bf"}, + {file = "cryptography-36.0.2-cp36-abi3-manylinux_2_24_x86_64.whl", hash = "sha256:c2c5250ff0d36fd58550252f54915776940e4e866f38f3a7866d92b32a654b86"}, + {file = "cryptography-36.0.2-cp36-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:ec6597aa85ce03f3e507566b8bcdf9da2227ec86c4266bd5e6ab4d9e0cc8dab2"}, + {file = "cryptography-36.0.2-cp36-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:ca9f686517ec2c4a4ce930207f75c00bf03d94e5063cbc00a1dc42531511b7eb"}, + {file = "cryptography-36.0.2-cp36-abi3-win32.whl", hash = "sha256:f64b232348ee82f13aac22856515ce0195837f6968aeaa94a3d0353ea2ec06a6"}, + {file = "cryptography-36.0.2-cp36-abi3-win_amd64.whl", hash = "sha256:53e0285b49fd0ab6e604f4c5d9c5ddd98de77018542e88366923f152dbeb3c29"}, + {file = "cryptography-36.0.2-pp37-pypy37_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:32db5cc49c73f39aac27574522cecd0a4bb7384e71198bc65a0d23f901e89bb7"}, + {file = "cryptography-36.0.2-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b3d199647468d410994dbeb8cec5816fb74feb9368aedf300af709ef507e3e"}, + {file = "cryptography-36.0.2-pp37-pypy37_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:da73d095f8590ad437cd5e9faf6628a218aa7c387e1fdf67b888b47ba56a17f0"}, + {file = "cryptography-36.0.2-pp38-pypy38_pp73-macosx_10_10_x86_64.whl", hash = "sha256:0a3bf09bb0b7a2c93ce7b98cb107e9170a90c51a0162a20af1c61c765b90e60b"}, + {file = "cryptography-36.0.2-pp38-pypy38_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:8897b7b7ec077c819187a123174b645eb680c13df68354ed99f9b40a50898f77"}, + {file = "cryptography-36.0.2-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:82740818f2f240a5da8dfb8943b360e4f24022b093207160c77cadade47d7c85"}, + {file = "cryptography-36.0.2-pp38-pypy38_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:1f64a62b3b75e4005df19d3b5235abd43fa6358d5516cfc43d87aeba8d08dd51"}, + {file = "cryptography-36.0.2-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:e167b6b710c7f7bc54e67ef593f8731e1f45aa35f8a8a7b72d6e42ec76afd4b3"}, + {file = "cryptography-36.0.2.tar.gz", hash = "sha256:70f8f4f7bb2ac9f340655cbac89d68c527af5bb4387522a8413e841e3e6628c9"}, ] dataclasses = [ {file = "dataclasses-0.8-py3-none-any.whl", hash = "sha256:0201d89fa866f68c8ebd9d08ee6ff50c0b255f8ec63a71c16fda7af82bb887bf"}, @@ -2440,14 +2704,95 @@ flake8 = [ {file = "flake8-4.0.1-py2.py3-none-any.whl", hash = "sha256:479b1304f72536a55948cb40a32dce8bb0ffe3501e26eaf292c7e60eb5e0428d"}, {file = "flake8-4.0.1.tar.gz", hash = "sha256:806e034dda44114815e23c16ef92f95c91e4c71100ff52813adf7132a6ad870d"}, ] +frozenlist = [ + {file = "frozenlist-1.2.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:977a1438d0e0d96573fd679d291a1542097ea9f4918a8b6494b06610dfeefbf9"}, + {file = "frozenlist-1.2.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a8d86547a5e98d9edd47c432f7a14b0c5592624b496ae9880fb6332f34af1edc"}, + {file = "frozenlist-1.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:181754275d5d32487431a0a29add4f897968b7157204bc1eaaf0a0ce80c5ba7d"}, + {file = "frozenlist-1.2.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5df31bb2b974f379d230a25943d9bf0d3bc666b4b0807394b131a28fca2b0e5f"}, + {file = "frozenlist-1.2.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4766632cd8a68e4f10f156a12c9acd7b1609941525569dd3636d859d79279ed3"}, + {file = "frozenlist-1.2.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:16eef427c51cb1203a7c0ab59d1b8abccaba9a4f58c4bfca6ed278fc896dc193"}, + {file = "frozenlist-1.2.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:01d79515ed5aa3d699b05f6bdcf1fe9087d61d6b53882aa599a10853f0479c6c"}, + {file = "frozenlist-1.2.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:28e164722ea0df0cf6d48c4d5bdf3d19e87aaa6dfb39b0ba91153f224b912020"}, + {file = "frozenlist-1.2.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:e63ad0beef6ece06475d29f47d1f2f29727805376e09850ebf64f90777962792"}, + {file = "frozenlist-1.2.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:41de4db9b9501679cf7cddc16d07ac0f10ef7eb58c525a1c8cbff43022bddca4"}, + {file = "frozenlist-1.2.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:c6a9d84ee6427b65a81fc24e6ef589cb794009f5ca4150151251c062773e7ed2"}, + {file = "frozenlist-1.2.0-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:f5f3b2942c3b8b9bfe76b408bbaba3d3bb305ee3693e8b1d631fe0a0d4f93673"}, + {file = "frozenlist-1.2.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c98d3c04701773ad60d9545cd96df94d955329efc7743fdb96422c4b669c633b"}, + {file = "frozenlist-1.2.0-cp310-cp310-win32.whl", hash = "sha256:72cfbeab7a920ea9e74b19aa0afe3b4ad9c89471e3badc985d08756efa9b813b"}, + {file = "frozenlist-1.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:11ff401951b5ac8c0701a804f503d72c048173208490c54ebb8d7bb7c07a6d00"}, + {file = "frozenlist-1.2.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:b46f997d5ed6d222a863b02cdc9c299101ee27974d9bbb2fd1b3c8441311c408"}, + {file = "frozenlist-1.2.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:351686ca020d1bcd238596b1fa5c8efcbc21bffda9d0efe237aaa60348421e2a"}, + {file = "frozenlist-1.2.0-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bfbaa08cf1452acad9cb1c1d7b89394a41e712f88df522cea1a0f296b57782a0"}, + {file = "frozenlist-1.2.0-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b2ae2f5e9fa10805fb1c9adbfefaaecedd9e31849434be462c3960a0139ed729"}, + {file = "frozenlist-1.2.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:6790b8d96bbb74b7a6f4594b6f131bd23056c25f2aa5d816bd177d95245a30e3"}, + {file = "frozenlist-1.2.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:41f62468af1bd4e4b42b5508a3fe8cc46a693f0cdd0ca2f443f51f207893d837"}, + {file = "frozenlist-1.2.0-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:ec6cf345771cdb00791d271af9a0a6fbfc2b6dd44cb753f1eeaa256e21622adb"}, + {file = "frozenlist-1.2.0-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:14a5cef795ae3e28fb504b73e797c1800e9249f950e1c964bb6bdc8d77871161"}, + {file = "frozenlist-1.2.0-cp36-cp36m-musllinux_1_1_ppc64le.whl", hash = "sha256:8b54cdd2fda15467b9b0bfa78cee2ddf6dbb4585ef23a16e14926f4b076dfae4"}, + {file = "frozenlist-1.2.0-cp36-cp36m-musllinux_1_1_s390x.whl", hash = "sha256:f025f1d6825725b09c0038775acab9ae94264453a696cc797ce20c0769a7b367"}, + {file = "frozenlist-1.2.0-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:84e97f59211b5b9083a2e7a45abf91cfb441369e8bb6d1f5287382c1c526def3"}, + {file = "frozenlist-1.2.0-cp36-cp36m-win32.whl", hash = "sha256:c5328ed53fdb0a73c8a50105306a3bc013e5ca36cca714ec4f7bd31d38d8a97f"}, + {file = "frozenlist-1.2.0-cp36-cp36m-win_amd64.whl", hash = "sha256:9ade70aea559ca98f4b1b1e5650c45678052e76a8ab2f76d90f2ac64180215a2"}, + {file = "frozenlist-1.2.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:a0d3ffa8772464441b52489b985d46001e2853a3b082c655ec5fad9fb6a3d618"}, + {file = "frozenlist-1.2.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3457f8cf86deb6ce1ba67e120f1b0128fcba1332a180722756597253c465fc1d"}, + {file = "frozenlist-1.2.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5a72eecf37eface331636951249d878750db84034927c997d47f7f78a573b72b"}, + {file = "frozenlist-1.2.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:acc4614e8d1feb9f46dd829a8e771b8f5c4b1051365d02efb27a3229048ade8a"}, + {file = "frozenlist-1.2.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:87521e32e18a2223311afc2492ef2d99946337da0779ddcda77b82ee7319df59"}, + {file = "frozenlist-1.2.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:8b4c7665a17c3a5430edb663e4ad4e1ad457614d1b2f2b7f87052e2ef4fa45ca"}, + {file = "frozenlist-1.2.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:ed58803563a8c87cf4c0771366cf0ad1aa265b6b0ae54cbbb53013480c7ad74d"}, + {file = "frozenlist-1.2.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:aa44c4740b4e23fcfa259e9dd52315d2b1770064cde9507457e4c4a65a04c397"}, + {file = "frozenlist-1.2.0-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:2de5b931701257d50771a032bba4e448ff958076380b049fd36ed8738fdb375b"}, + {file = "frozenlist-1.2.0-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:6e105013fa84623c057a4381dc8ea0361f4d682c11f3816cc80f49a1f3bc17c6"}, + {file = "frozenlist-1.2.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:705c184b77565955a99dc360f359e8249580c6b7eaa4dc0227caa861ef46b27a"}, + {file = "frozenlist-1.2.0-cp37-cp37m-win32.whl", hash = "sha256:a37594ad6356e50073fe4f60aa4187b97d15329f2138124d252a5a19c8553ea4"}, + {file = "frozenlist-1.2.0-cp37-cp37m-win_amd64.whl", hash = "sha256:25b358aaa7dba5891b05968dd539f5856d69f522b6de0bf34e61f133e077c1a4"}, + {file = "frozenlist-1.2.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:af2a51c8a381d76eabb76f228f565ed4c3701441ecec101dd18be70ebd483cfd"}, + {file = "frozenlist-1.2.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:82d22f6e6f2916e837c91c860140ef9947e31194c82aaeda843d6551cec92f19"}, + {file = "frozenlist-1.2.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:1cfe6fef507f8bac40f009c85c7eddfed88c1c0d38c75e72fe10476cef94e10f"}, + {file = "frozenlist-1.2.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:26f602e380a5132880fa245c92030abb0fc6ff34e0c5500600366cedc6adb06a"}, + {file = "frozenlist-1.2.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4ad065b2ebd09f32511ff2be35c5dfafee6192978b5a1e9d279a5c6e121e3b03"}, + {file = "frozenlist-1.2.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bc93f5f62df3bdc1f677066327fc81f92b83644852a31c6aa9b32c2dde86ea7d"}, + {file = "frozenlist-1.2.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:89fdfc84c6bf0bff2ff3170bb34ecba8a6911b260d318d377171429c4be18c73"}, + {file = "frozenlist-1.2.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:47b2848e464883d0bbdcd9493c67443e5e695a84694efff0476f9059b4cb6257"}, + {file = "frozenlist-1.2.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:4f52d0732e56906f8ddea4bd856192984650282424049c956857fed43697ea43"}, + {file = "frozenlist-1.2.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:16ef7dd5b7d17495404a2e7a49bac1bc13d6d20c16d11f4133c757dd94c4144c"}, + {file = "frozenlist-1.2.0-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:1cf63243bc5f5c19762943b0aa9e0d3fb3723d0c514d820a18a9b9a5ef864315"}, + {file = "frozenlist-1.2.0-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:54a1e09ab7a69f843cd28fefd2bcaf23edb9e3a8d7680032c8968b8ac934587d"}, + {file = "frozenlist-1.2.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:954b154a4533ef28bd3e83ffdf4eadf39deeda9e38fb8feaf066d6069885e034"}, + {file = "frozenlist-1.2.0-cp38-cp38-win32.whl", hash = "sha256:cb3957c39668d10e2b486acc85f94153520a23263b6401e8f59422ef65b9520d"}, + {file = "frozenlist-1.2.0-cp38-cp38-win_amd64.whl", hash = "sha256:0a7c7cce70e41bc13d7d50f0e5dd175f14a4f1837a8549b0936ed0cbe6170bf9"}, + {file = "frozenlist-1.2.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:4c457220468d734e3077580a3642b7f682f5fd9507f17ddf1029452450912cdc"}, + {file = "frozenlist-1.2.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:e74f8b4d8677ebb4015ac01fcaf05f34e8a1f22775db1f304f497f2f88fdc697"}, + {file = "frozenlist-1.2.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:fbd4844ff111449f3bbe20ba24fbb906b5b1c2384d0f3287c9f7da2354ce6d23"}, + {file = "frozenlist-1.2.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f0081a623c886197ff8de9e635528fd7e6a387dccef432149e25c13946cb0cd0"}, + {file = "frozenlist-1.2.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9b6e21e5770df2dea06cb7b6323fbc008b13c4a4e3b52cb54685276479ee7676"}, + {file = "frozenlist-1.2.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:406aeb340613b4b559db78d86864485f68919b7141dec82aba24d1477fd2976f"}, + {file = "frozenlist-1.2.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:878ebe074839d649a1cdb03a61077d05760624f36d196884a5cafb12290e187b"}, + {file = "frozenlist-1.2.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:1fef737fd1388f9b93bba8808c5f63058113c10f4e3c0763ced68431773f72f9"}, + {file = "frozenlist-1.2.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:4a495c3d513573b0b3f935bfa887a85d9ae09f0627cf47cad17d0cc9b9ba5c38"}, + {file = "frozenlist-1.2.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:e7d0dd3e727c70c2680f5f09a0775525229809f1a35d8552b92ff10b2b14f2c2"}, + {file = "frozenlist-1.2.0-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:66a518731a21a55b7d3e087b430f1956a36793acc15912e2878431c7aec54210"}, + {file = "frozenlist-1.2.0-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:94728f97ddf603d23c8c3dd5cae2644fa12d33116e69f49b1644a71bb77b89ae"}, + {file = "frozenlist-1.2.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:c1e8e9033d34c2c9e186e58279879d78c94dd365068a3607af33f2bc99357a53"}, + {file = "frozenlist-1.2.0-cp39-cp39-win32.whl", hash = "sha256:83334e84a290a158c0c4cc4d22e8c7cfe0bba5b76d37f1c2509dabd22acafe15"}, + {file = "frozenlist-1.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:735f386ec522e384f511614c01d2ef9cf799f051353876b4c6fb93ef67a6d1ee"}, + {file = "frozenlist-1.2.0.tar.gz", hash = "sha256:68201be60ac56aff972dc18085800b6ee07973c49103a8aba669dee3d71079de"}, +] fsspec = [ {file = "fsspec-2022.1.0-py3-none-any.whl", hash = "sha256:256e2be44e62430c9ca8dac2e480384b00a3c52aef4e2b0b7204163fdc861d37"}, {file = "fsspec-2022.1.0.tar.gz", hash = "sha256:0bdd519bbf4d8c9a1d893a50b5ebacc89acd0e1fe0045d2f7b0e0c1af5990edc"}, ] +gremlinpython = [ + {file = "gremlinpython-3.5.2-py2.py3-none-any.whl", hash = "sha256:333c8d2d67d1c5350a7ade2efd8d2acdb81968c01c09fdea80269292deadb582"}, + {file = "gremlinpython-3.5.2.tar.gz", hash = "sha256:2ebaa1f360ba62c48705b056ba3d4e92e448287431f42a92eef4b2217ae51c5b"}, +] idna = [ {file = "idna-3.3-py3-none-any.whl", hash = "sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff"}, {file = "idna-3.3.tar.gz", hash = "sha256:9d643ff0a55b762d5cdb124b8eaa99c66322e2157b69160bc32796e824360e6d"}, ] +idna-ssl = [ + {file = "idna-ssl-1.1.0.tar.gz", hash = "sha256:a933e3bb13da54383f9e8f35dc4f9cb9eb9b3b78c6b36f311254d6d0d92c6c7c"}, +] imagesize = [ {file = "imagesize-1.3.0-py2.py3-none-any.whl", hash = "sha256:1db2f82529e53c3e929e8926a1fa9235aa82d0bd0c580359c67ec31b2fddaa8c"}, {file = "imagesize-1.3.0.tar.gz", hash = "sha256:cd1750d452385ca327479d45b64d9c7729ecf0b3969a58148298c77092261f9d"}, @@ -2505,6 +2850,10 @@ ipython-genutils = [ {file = "ipython_genutils-0.2.0-py2.py3-none-any.whl", hash = "sha256:72dd37233799e619666c9f639a9da83c34013a73e8bbc79a7a6348d93c61fab8"}, {file = "ipython_genutils-0.2.0.tar.gz", hash = "sha256:eb2e116e75ecef9d4d228fdc66af54269afa26ab4463042e33785b887c628ba8"}, ] +isodate = [ + {file = "isodate-0.6.1-py2.py3-none-any.whl", hash = "sha256:0751eece944162659049d35f4f549ed815792b38793f07cf73381c1c87cbed96"}, + {file = "isodate-0.6.1.tar.gz", hash = "sha256:48c5881de7e8b0a0d648cb024c8062dc84e7b840ed81e864c7614fd3c127bde9"}, +] isort = [ {file = "isort-5.10.1-py3-none-any.whl", hash = "sha256:6f62d78e2f89b4500b080fe3a81690850cd254227f27f75c3a0c491a1f351ba7"}, {file = "isort-5.10.1.tar.gz", hash = "sha256:e8443a5e7a020e9d7f97f1d7d9cd17c88bcb3bc7e218bf9cf5095fe550be2951"}, @@ -2539,8 +2888,8 @@ jupyter-client = [ {file = "jupyter_client-7.1.2.tar.gz", hash = "sha256:4ea61033726c8e579edb55626d8ee2e6bf0a83158ddf3751b8dd46b2c5cd1e96"}, ] jupyter-core = [ - {file = "jupyter_core-4.9.1-py3-none-any.whl", hash = "sha256:1c091f3bbefd6f2a8782f2c1db662ca8478ac240e962ae2c66f0b87c818154ea"}, - {file = "jupyter_core-4.9.1.tar.gz", hash = "sha256:dce8a7499da5a53ae3afd5a9f4b02e5df1d57250cf48f3ad79da23b4778cd6fa"}, + {file = "jupyter_core-4.9.2-py3-none-any.whl", hash = "sha256:f875e4d27e202590311d468fa55f90c575f201490bd0c18acabe4e318db4a46d"}, + {file = "jupyter_core-4.9.2.tar.gz", hash = "sha256:d69baeb9ffb128b8cd2657fcf2703f89c769d1673c851812119e3a2a0e93ad9a"}, ] jupyter-server = [ {file = "jupyter_server-1.13.1-py3-none-any.whl", hash = "sha256:abfe55b6cd7bac0d7d7b8042765b7e451f11b5f2276a2ad708745cd8904d4e5b"}, @@ -2598,66 +2947,67 @@ lazy-object-proxy = [ {file = "lazy_object_proxy-1.7.1-pp37.pp38-none-any.whl", hash = "sha256:d66906d5785da8e0be7360912e99c9188b70f52c422f9fc18223347235691a84"}, ] lxml = [ - {file = "lxml-4.7.1-cp27-cp27m-macosx_10_14_x86_64.whl", hash = "sha256:d546431636edb1d6a608b348dd58cc9841b81f4116745857b6cb9f8dadb2725f"}, - {file = "lxml-4.7.1-cp27-cp27m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6308062534323f0d3edb4e702a0e26a76ca9e0e23ff99be5d82750772df32a9e"}, - {file = "lxml-4.7.1-cp27-cp27m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:f76dbe44e31abf516114f6347a46fa4e7c2e8bceaa4b6f7ee3a0a03c8eba3c17"}, - {file = "lxml-4.7.1-cp27-cp27m-win32.whl", hash = "sha256:d5618d49de6ba63fe4510bdada62d06a8acfca0b4b5c904956c777d28382b419"}, - {file = "lxml-4.7.1-cp27-cp27m-win_amd64.whl", hash = "sha256:9393a05b126a7e187f3e38758255e0edf948a65b22c377414002d488221fdaa2"}, - {file = "lxml-4.7.1-cp27-cp27mu-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:50d3dba341f1e583265c1a808e897b4159208d814ab07530202b6036a4d86da5"}, - {file = "lxml-4.7.1-cp27-cp27mu-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:44f552e0da3c8ee3c28e2eb82b0b784200631687fc6a71277ea8ab0828780e7d"}, - {file = "lxml-4.7.1-cp310-cp310-macosx_10_14_x86_64.whl", hash = "sha256:e662c6266e3a275bdcb6bb049edc7cd77d0b0f7e119a53101d367c841afc66dc"}, - {file = "lxml-4.7.1-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:4c093c571bc3da9ebcd484e001ba18b8452903cd428c0bc926d9b0141bcb710e"}, - {file = "lxml-4.7.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:3e26ad9bc48d610bf6cc76c506b9e5ad9360ed7a945d9be3b5b2c8535a0145e3"}, - {file = "lxml-4.7.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:a5f623aeaa24f71fce3177d7fee875371345eb9102b355b882243e33e04b7175"}, - {file = "lxml-4.7.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:7b5e2acefd33c259c4a2e157119c4373c8773cf6793e225006a1649672ab47a6"}, - {file = "lxml-4.7.1-cp310-cp310-win32.whl", hash = "sha256:67fa5f028e8a01e1d7944a9fb616d1d0510d5d38b0c41708310bd1bc45ae89f6"}, - {file = "lxml-4.7.1-cp310-cp310-win_amd64.whl", hash = "sha256:b1d381f58fcc3e63fcc0ea4f0a38335163883267f77e4c6e22d7a30877218a0e"}, - {file = "lxml-4.7.1-cp35-cp35m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:38d9759733aa04fb1697d717bfabbedb21398046bd07734be7cccc3d19ea8675"}, - {file = "lxml-4.7.1-cp35-cp35m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:dfd0d464f3d86a1460683cd742306d1138b4e99b79094f4e07e1ca85ee267fe7"}, - {file = "lxml-4.7.1-cp35-cp35m-win32.whl", hash = "sha256:534e946bce61fd162af02bad7bfd2daec1521b71d27238869c23a672146c34a5"}, - {file = "lxml-4.7.1-cp35-cp35m-win_amd64.whl", hash = "sha256:6ec829058785d028f467be70cd195cd0aaf1a763e4d09822584ede8c9eaa4b03"}, - {file = "lxml-4.7.1-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:ade74f5e3a0fd17df5782896ddca7ddb998845a5f7cd4b0be771e1ffc3b9aa5b"}, - {file = "lxml-4.7.1-cp36-cp36m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:41358bfd24425c1673f184d7c26c6ae91943fe51dfecc3603b5e08187b4bcc55"}, - {file = "lxml-4.7.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:6e56521538f19c4a6690f439fefed551f0b296bd785adc67c1777c348beb943d"}, - {file = "lxml-4.7.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5b0f782f0e03555c55e37d93d7a57454efe7495dab33ba0ccd2dbe25fc50f05d"}, - {file = "lxml-4.7.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:490712b91c65988012e866c411a40cc65b595929ececf75eeb4c79fcc3bc80a6"}, - {file = "lxml-4.7.1-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:34c22eb8c819d59cec4444d9eebe2e38b95d3dcdafe08965853f8799fd71161d"}, - {file = "lxml-4.7.1-cp36-cp36m-win32.whl", hash = "sha256:2a906c3890da6a63224d551c2967413b8790a6357a80bf6b257c9a7978c2c42d"}, - {file = "lxml-4.7.1-cp36-cp36m-win_amd64.whl", hash = "sha256:36b16fecb10246e599f178dd74f313cbdc9f41c56e77d52100d1361eed24f51a"}, - {file = "lxml-4.7.1-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:a5edc58d631170de90e50adc2cc0248083541affef82f8cd93bea458e4d96db8"}, - {file = "lxml-4.7.1-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:87c1b0496e8c87ec9db5383e30042357b4839b46c2d556abd49ec770ce2ad868"}, - {file = "lxml-4.7.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:0a5f0e4747f31cff87d1eb32a6000bde1e603107f632ef4666be0dc065889c7a"}, - {file = "lxml-4.7.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:bf6005708fc2e2c89a083f258b97709559a95f9a7a03e59f805dd23c93bc3986"}, - {file = "lxml-4.7.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:fc15874816b9320581133ddc2096b644582ab870cf6a6ed63684433e7af4b0d3"}, - {file = "lxml-4.7.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:0b5e96e25e70917b28a5391c2ed3ffc6156513d3db0e1476c5253fcd50f7a944"}, - {file = "lxml-4.7.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:ec9027d0beb785a35aa9951d14e06d48cfbf876d8ff67519403a2522b181943b"}, - {file = "lxml-4.7.1-cp37-cp37m-win32.whl", hash = "sha256:9fbc0dee7ff5f15c4428775e6fa3ed20003140560ffa22b88326669d53b3c0f4"}, - {file = "lxml-4.7.1-cp37-cp37m-win_amd64.whl", hash = "sha256:1104a8d47967a414a436007c52f533e933e5d52574cab407b1e49a4e9b5ddbd1"}, - {file = "lxml-4.7.1-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:fc9fb11b65e7bc49f7f75aaba1b700f7181d95d4e151cf2f24d51bfd14410b77"}, - {file = "lxml-4.7.1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:317bd63870b4d875af3c1be1b19202de34c32623609ec803b81c99193a788c1e"}, - {file = "lxml-4.7.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:610807cea990fd545b1559466971649e69302c8a9472cefe1d6d48a1dee97440"}, - {file = "lxml-4.7.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:09b738360af8cb2da275998a8bf79517a71225b0de41ab47339c2beebfff025f"}, - {file = "lxml-4.7.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6a2ab9d089324d77bb81745b01f4aeffe4094306d939e92ba5e71e9a6b99b71e"}, - {file = "lxml-4.7.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:eed394099a7792834f0cb4a8f615319152b9d801444c1c9e1b1a2c36d2239f9e"}, - {file = "lxml-4.7.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:735e3b4ce9c0616e85f302f109bdc6e425ba1670a73f962c9f6b98a6d51b77c9"}, - {file = "lxml-4.7.1-cp38-cp38-win32.whl", hash = "sha256:772057fba283c095db8c8ecde4634717a35c47061d24f889468dc67190327bcd"}, - {file = "lxml-4.7.1-cp38-cp38-win_amd64.whl", hash = "sha256:13dbb5c7e8f3b6a2cf6e10b0948cacb2f4c9eb05029fe31c60592d08ac63180d"}, - {file = "lxml-4.7.1-cp39-cp39-macosx_10_14_x86_64.whl", hash = "sha256:718d7208b9c2d86aaf0294d9381a6acb0158b5ff0f3515902751404e318e02c9"}, - {file = "lxml-4.7.1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:5bee1b0cbfdb87686a7fb0e46f1d8bd34d52d6932c0723a86de1cc532b1aa489"}, - {file = "lxml-4.7.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:e410cf3a2272d0a85526d700782a2fa92c1e304fdcc519ba74ac80b8297adf36"}, - {file = "lxml-4.7.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:585ea241ee4961dc18a95e2f5581dbc26285fcf330e007459688096f76be8c42"}, - {file = "lxml-4.7.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a555e06566c6dc167fbcd0ad507ff05fd9328502aefc963cb0a0547cfe7f00db"}, - {file = "lxml-4.7.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:adaab25be351fff0d8a691c4f09153647804d09a87a4e4ea2c3f9fe9e8651851"}, - {file = "lxml-4.7.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:82d16a64236970cb93c8d63ad18c5b9f138a704331e4b916b2737ddfad14e0c4"}, - {file = "lxml-4.7.1-cp39-cp39-win32.whl", hash = "sha256:59e7da839a1238807226f7143c68a479dee09244d1b3cf8c134f2fce777d12d0"}, - {file = "lxml-4.7.1-cp39-cp39-win_amd64.whl", hash = "sha256:a1bbc4efa99ed1310b5009ce7f3a1784698082ed2c1ef3895332f5df9b3b92c2"}, - {file = "lxml-4.7.1-pp37-pypy37_pp73-macosx_10_14_x86_64.whl", hash = "sha256:0607ff0988ad7e173e5ddf7bf55ee65534bd18a5461183c33e8e41a59e89edf4"}, - {file = "lxml-4.7.1-pp37-pypy37_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:6c198bfc169419c09b85ab10cb0f572744e686f40d1e7f4ed09061284fc1303f"}, - {file = "lxml-4.7.1-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:a58d78653ae422df6837dd4ca0036610b8cb4962b5cfdbd337b7b24de9e5f98a"}, - {file = "lxml-4.7.1-pp38-pypy38_pp73-macosx_10_14_x86_64.whl", hash = "sha256:e18281a7d80d76b66a9f9e68a98cf7e1d153182772400d9a9ce855264d7d0ce7"}, - {file = "lxml-4.7.1-pp38-pypy38_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:8e54945dd2eeb50925500957c7c579df3cd07c29db7810b83cf30495d79af267"}, - {file = "lxml-4.7.1-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:447d5009d6b5447b2f237395d0018901dcc673f7d9f82ba26c1b9f9c3b444b60"}, - {file = "lxml-4.7.1.tar.gz", hash = "sha256:a1613838aa6b89af4ba10a0f3a972836128801ed008078f8c1244e65958f1b24"}, + {file = "lxml-4.8.0-cp27-cp27m-macosx_10_14_x86_64.whl", hash = "sha256:e1ab2fac607842ac36864e358c42feb0960ae62c34aa4caaf12ada0a1fb5d99b"}, + {file = "lxml-4.8.0-cp27-cp27m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:28d1af847786f68bec57961f31221125c29d6f52d9187c01cd34dc14e2b29430"}, + {file = "lxml-4.8.0-cp27-cp27m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:b92d40121dcbd74831b690a75533da703750f7041b4bf951befc657c37e5695a"}, + {file = "lxml-4.8.0-cp27-cp27m-win32.whl", hash = "sha256:e01f9531ba5420838c801c21c1b0f45dbc9607cb22ea2cf132844453bec863a5"}, + {file = "lxml-4.8.0-cp27-cp27m-win_amd64.whl", hash = "sha256:6259b511b0f2527e6d55ad87acc1c07b3cbffc3d5e050d7e7bcfa151b8202df9"}, + {file = "lxml-4.8.0-cp27-cp27mu-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1010042bfcac2b2dc6098260a2ed022968dbdfaf285fc65a3acf8e4eb1ffd1bc"}, + {file = "lxml-4.8.0-cp27-cp27mu-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:fa56bb08b3dd8eac3a8c5b7d075c94e74f755fd9d8a04543ae8d37b1612dd170"}, + {file = "lxml-4.8.0-cp310-cp310-macosx_10_15_x86_64.whl", hash = "sha256:31ba2cbc64516dcdd6c24418daa7abff989ddf3ba6d3ea6f6ce6f2ed6e754ec9"}, + {file = "lxml-4.8.0-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:31499847fc5f73ee17dbe1b8e24c6dafc4e8d5b48803d17d22988976b0171f03"}, + {file = "lxml-4.8.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:5f7d7d9afc7b293147e2d506a4596641d60181a35279ef3aa5778d0d9d9123fe"}, + {file = "lxml-4.8.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:a3c5f1a719aa11866ffc530d54ad965063a8cbbecae6515acbd5f0fae8f48eaa"}, + {file = "lxml-4.8.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:6268e27873a3d191849204d00d03f65c0e343b3bcb518a6eaae05677c95621d1"}, + {file = "lxml-4.8.0-cp310-cp310-win32.whl", hash = "sha256:330bff92c26d4aee79c5bc4d9967858bdbe73fdbdbacb5daf623a03a914fe05b"}, + {file = "lxml-4.8.0-cp310-cp310-win_amd64.whl", hash = "sha256:b2582b238e1658c4061ebe1b4df53c435190d22457642377fd0cb30685cdfb76"}, + {file = "lxml-4.8.0-cp35-cp35m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a2bfc7e2a0601b475477c954bf167dee6d0f55cb167e3f3e7cefad906e7759f6"}, + {file = "lxml-4.8.0-cp35-cp35m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:a1547ff4b8a833511eeaceacbcd17b043214fcdb385148f9c1bc5556ca9623e2"}, + {file = "lxml-4.8.0-cp35-cp35m-win32.whl", hash = "sha256:a9f1c3489736ff8e1c7652e9dc39f80cff820f23624f23d9eab6e122ac99b150"}, + {file = "lxml-4.8.0-cp35-cp35m-win_amd64.whl", hash = "sha256:530f278849031b0eb12f46cca0e5db01cfe5177ab13bd6878c6e739319bae654"}, + {file = "lxml-4.8.0-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:078306d19a33920004addeb5f4630781aaeabb6a8d01398045fcde085091a169"}, + {file = "lxml-4.8.0-cp36-cp36m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:86545e351e879d0b72b620db6a3b96346921fa87b3d366d6c074e5a9a0b8dadb"}, + {file = "lxml-4.8.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:24f5c5ae618395ed871b3d8ebfcbb36e3f1091fd847bf54c4de623f9107942f3"}, + {file = "lxml-4.8.0-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:bbab6faf6568484707acc052f4dfc3802bdb0cafe079383fbaa23f1cdae9ecd4"}, + {file = "lxml-4.8.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:7993232bd4044392c47779a3c7e8889fea6883be46281d45a81451acfd704d7e"}, + {file = "lxml-4.8.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:6d6483b1229470e1d8835e52e0ff3c6973b9b97b24cd1c116dca90b57a2cc613"}, + {file = "lxml-4.8.0-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:ad4332a532e2d5acb231a2e5d33f943750091ee435daffca3fec0a53224e7e33"}, + {file = "lxml-4.8.0-cp36-cp36m-win32.whl", hash = "sha256:db3535733f59e5605a88a706824dfcb9bd06725e709ecb017e165fc1d6e7d429"}, + {file = "lxml-4.8.0-cp36-cp36m-win_amd64.whl", hash = "sha256:5f148b0c6133fb928503cfcdfdba395010f997aa44bcf6474fcdd0c5398d9b63"}, + {file = "lxml-4.8.0-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:8a31f24e2a0b6317f33aafbb2f0895c0bce772980ae60c2c640d82caac49628a"}, + {file = "lxml-4.8.0-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:719544565c2937c21a6f76d520e6e52b726d132815adb3447ccffbe9f44203c4"}, + {file = "lxml-4.8.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:c0b88ed1ae66777a798dc54f627e32d3b81c8009967c63993c450ee4cbcbec15"}, + {file = "lxml-4.8.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:fa9b7c450be85bfc6cd39f6df8c5b8cbd76b5d6fc1f69efec80203f9894b885f"}, + {file = "lxml-4.8.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e9f84ed9f4d50b74fbc77298ee5c870f67cb7e91dcdc1a6915cb1ff6a317476c"}, + {file = "lxml-4.8.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:1d650812b52d98679ed6c6b3b55cbb8fe5a5460a0aef29aeb08dc0b44577df85"}, + {file = "lxml-4.8.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:80bbaddf2baab7e6de4bc47405e34948e694a9efe0861c61cdc23aa774fcb141"}, + {file = "lxml-4.8.0-cp37-cp37m-win32.whl", hash = "sha256:6f7b82934c08e28a2d537d870293236b1000d94d0b4583825ab9649aef7ddf63"}, + {file = "lxml-4.8.0-cp37-cp37m-win_amd64.whl", hash = "sha256:e1fd7d2fe11f1cb63d3336d147c852f6d07de0d0020d704c6031b46a30b02ca8"}, + {file = "lxml-4.8.0-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:5045ee1ccd45a89c4daec1160217d363fcd23811e26734688007c26f28c9e9e7"}, + {file = "lxml-4.8.0-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:0c1978ff1fd81ed9dcbba4f91cf09faf1f8082c9d72eb122e92294716c605428"}, + {file = "lxml-4.8.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:52cbf2ff155b19dc4d4100f7442f6a697938bf4493f8d3b0c51d45568d5666b5"}, + {file = "lxml-4.8.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:ce13d6291a5f47c1c8dbd375baa78551053bc6b5e5c0e9bb8e39c0a8359fd52f"}, + {file = "lxml-4.8.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e11527dc23d5ef44d76fef11213215c34f36af1608074561fcc561d983aeb870"}, + {file = "lxml-4.8.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:60d2f60bd5a2a979df28ab309352cdcf8181bda0cca4529769a945f09aba06f9"}, + {file = "lxml-4.8.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:62f93eac69ec0f4be98d1b96f4d6b964855b8255c345c17ff12c20b93f247b68"}, + {file = "lxml-4.8.0-cp38-cp38-win32.whl", hash = "sha256:20b8a746a026017acf07da39fdb10aa80ad9877046c9182442bf80c84a1c4696"}, + {file = "lxml-4.8.0-cp38-cp38-win_amd64.whl", hash = "sha256:891dc8f522d7059ff0024cd3ae79fd224752676447f9c678f2a5c14b84d9a939"}, + {file = "lxml-4.8.0-cp39-cp39-macosx_10_15_x86_64.whl", hash = "sha256:b6fc2e2fb6f532cf48b5fed57567ef286addcef38c28874458a41b7837a57807"}, + {file = "lxml-4.8.0-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:74eb65ec61e3c7c019d7169387d1b6ffcfea1b9ec5894d116a9a903636e4a0b1"}, + {file = "lxml-4.8.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:627e79894770783c129cc5e89b947e52aa26e8e0557c7e205368a809da4b7939"}, + {file = "lxml-4.8.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:545bd39c9481f2e3f2727c78c169425efbfb3fbba6e7db4f46a80ebb249819ca"}, + {file = "lxml-4.8.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5a58d0b12f5053e270510bf12f753a76aaf3d74c453c00942ed7d2c804ca845c"}, + {file = "lxml-4.8.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:ec4b4e75fc68da9dc0ed73dcdb431c25c57775383fec325d23a770a64e7ebc87"}, + {file = "lxml-4.8.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5804e04feb4e61babf3911c2a974a5b86f66ee227cc5006230b00ac6d285b3a9"}, + {file = "lxml-4.8.0-cp39-cp39-win32.whl", hash = "sha256:aa0cf4922da7a3c905d000b35065df6184c0dc1d866dd3b86fd961905bbad2ea"}, + {file = "lxml-4.8.0-cp39-cp39-win_amd64.whl", hash = "sha256:dd10383f1d6b7edf247d0960a3db274c07e96cf3a3fc7c41c8448f93eac3fb1c"}, + {file = "lxml-4.8.0-pp37-pypy37_pp73-macosx_10_14_x86_64.whl", hash = "sha256:2403a6d6fb61c285969b71f4a3527873fe93fd0abe0832d858a17fe68c8fa507"}, + {file = "lxml-4.8.0-pp37-pypy37_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:986b7a96228c9b4942ec420eff37556c5777bfba6758edcb95421e4a614b57f9"}, + {file = "lxml-4.8.0-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:6fe4ef4402df0250b75ba876c3795510d782def5c1e63890bde02d622570d39e"}, + {file = "lxml-4.8.0-pp38-pypy38_pp73-macosx_10_14_x86_64.whl", hash = "sha256:f10ce66fcdeb3543df51d423ede7e238be98412232fca5daec3e54bcd16b8da0"}, + {file = "lxml-4.8.0-pp38-pypy38_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:730766072fd5dcb219dd2b95c4c49752a54f00157f322bc6d71f7d2a31fecd79"}, + {file = "lxml-4.8.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:8b99ec73073b37f9ebe8caf399001848fced9c08064effdbfc4da2b5a8d07b93"}, + {file = "lxml-4.8.0.tar.gz", hash = "sha256:f63f62fc60e6228a4ca9abae28228f35e1bd3ce675013d1dfb828688d50c6e23"}, ] markupsafe = [ {file = "MarkupSafe-2.0.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d8446c54dc28c01e5a2dbac5a25f071f6653e6e40f3a8818e8b45d790fe6ef53"}, @@ -2739,8 +3089,82 @@ mistune = [ {file = "mistune-0.8.4.tar.gz", hash = "sha256:59a3429db53c50b5c6bcc8a07f8848cb00d7dc8bdb431a4ab41920d201d4756e"}, ] moto = [ - {file = "moto-3.0.3-py2.py3-none-any.whl", hash = "sha256:445a574395b8a43a249ae0f932bf10c5cc677054198bfa1ff92e6fbd60e72c38"}, - {file = "moto-3.0.3.tar.gz", hash = "sha256:fa3fbdc22c55d7e70b407e2f2639c48ac82b074f472b167609405c0c1e3a2ccb"}, + {file = "moto-3.1.1-py2.py3-none-any.whl", hash = "sha256:462495563847134ea8ef4135a229731a598a8e7b6b10a74f8d745815aa20a25b"}, + {file = "moto-3.1.1.tar.gz", hash = "sha256:9b5446b3d1f7505d32616209ae09f02123ebc583387f7c182f11e4175754034f"}, +] +multidict = [ + {file = "multidict-5.2.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:3822c5894c72e3b35aae9909bef66ec83e44522faf767c0ad39e0e2de11d3b55"}, + {file = "multidict-5.2.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:28e6d883acd8674887d7edc896b91751dc2d8e87fbdca8359591a13872799e4e"}, + {file = "multidict-5.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:b61f85101ef08cbbc37846ac0e43f027f7844f3fade9b7f6dd087178caedeee7"}, + {file = "multidict-5.2.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d9b668c065968c5979fe6b6fa6760bb6ab9aeb94b75b73c0a9c1acf6393ac3bf"}, + {file = "multidict-5.2.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:517d75522b7b18a3385726b54a081afd425d4f41144a5399e5abd97ccafdf36b"}, + {file = "multidict-5.2.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1b4ac3ba7a97b35a5ccf34f41b5a8642a01d1e55454b699e5e8e7a99b5a3acf5"}, + {file = "multidict-5.2.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:df23c83398715b26ab09574217ca21e14694917a0c857e356fd39e1c64f8283f"}, + {file = "multidict-5.2.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:e58a9b5cc96e014ddf93c2227cbdeca94b56a7eb77300205d6e4001805391747"}, + {file = "multidict-5.2.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:f76440e480c3b2ca7f843ff8a48dc82446b86ed4930552d736c0bac507498a52"}, + {file = "multidict-5.2.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:cfde464ca4af42a629648c0b0d79b8f295cf5b695412451716531d6916461628"}, + {file = "multidict-5.2.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:0fed465af2e0eb6357ba95795d003ac0bdb546305cc2366b1fc8f0ad67cc3fda"}, + {file = "multidict-5.2.0-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:b70913cbf2e14275013be98a06ef4b412329fe7b4f83d64eb70dce8269ed1e1a"}, + {file = "multidict-5.2.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a5635bcf1b75f0f6ef3c8a1ad07b500104a971e38d3683167b9454cb6465ac86"}, + {file = "multidict-5.2.0-cp310-cp310-win32.whl", hash = "sha256:77f0fb7200cc7dedda7a60912f2059086e29ff67cefbc58d2506638c1a9132d7"}, + {file = "multidict-5.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:9416cf11bcd73c861267e88aea71e9fcc35302b3943e45e1dbb4317f91a4b34f"}, + {file = "multidict-5.2.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:fd77c8f3cba815aa69cb97ee2b2ef385c7c12ada9c734b0f3b32e26bb88bbf1d"}, + {file = "multidict-5.2.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:98ec9aea6223adf46999f22e2c0ab6cf33f5914be604a404f658386a8f1fba37"}, + {file = "multidict-5.2.0-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e5283c0a00f48e8cafcecadebfa0ed1dac8b39e295c7248c44c665c16dc1138b"}, + {file = "multidict-5.2.0-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5f79c19c6420962eb17c7e48878a03053b7ccd7b69f389d5831c0a4a7f1ac0a1"}, + {file = "multidict-5.2.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:e4a67f1080123de76e4e97a18d10350df6a7182e243312426d508712e99988d4"}, + {file = "multidict-5.2.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:94b117e27efd8e08b4046c57461d5a114d26b40824995a2eb58372b94f9fca02"}, + {file = "multidict-5.2.0-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:2e77282fd1d677c313ffcaddfec236bf23f273c4fba7cdf198108f5940ae10f5"}, + {file = "multidict-5.2.0-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:116347c63ba049c1ea56e157fa8aa6edaf5e92925c9b64f3da7769bdfa012858"}, + {file = "multidict-5.2.0-cp36-cp36m-musllinux_1_1_ppc64le.whl", hash = "sha256:dc3a866cf6c13d59a01878cd806f219340f3e82eed514485e094321f24900677"}, + {file = "multidict-5.2.0-cp36-cp36m-musllinux_1_1_s390x.whl", hash = "sha256:ac42181292099d91217a82e3fa3ce0e0ddf3a74fd891b7c2b347a7f5aa0edded"}, + {file = "multidict-5.2.0-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:f0bb0973f42ffcb5e3537548e0767079420aefd94ba990b61cf7bb8d47f4916d"}, + {file = "multidict-5.2.0-cp36-cp36m-win32.whl", hash = "sha256:ea21d4d5104b4f840b91d9dc8cbc832aba9612121eaba503e54eaab1ad140eb9"}, + {file = "multidict-5.2.0-cp36-cp36m-win_amd64.whl", hash = "sha256:e6453f3cbeb78440747096f239d282cc57a2997a16b5197c9bc839099e1633d0"}, + {file = "multidict-5.2.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:d3def943bfd5f1c47d51fd324df1e806d8da1f8e105cc7f1c76a1daf0f7e17b0"}, + {file = "multidict-5.2.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:35591729668a303a02b06e8dba0eb8140c4a1bfd4c4b3209a436a02a5ac1de11"}, + {file = "multidict-5.2.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ce8cacda0b679ebc25624d5de66c705bc53dcc7c6f02a7fb0f3ca5e227d80422"}, + {file = "multidict-5.2.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:baf1856fab8212bf35230c019cde7c641887e3fc08cadd39d32a421a30151ea3"}, + {file = "multidict-5.2.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:a43616aec0f0d53c411582c451f5d3e1123a68cc7b3475d6f7d97a626f8ff90d"}, + {file = "multidict-5.2.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:25cbd39a9029b409167aa0a20d8a17f502d43f2efebfe9e3ac019fe6796c59ac"}, + {file = "multidict-5.2.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:0a2cbcfbea6dc776782a444db819c8b78afe4db597211298dd8b2222f73e9cd0"}, + {file = "multidict-5.2.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:3d2d7d1fff8e09d99354c04c3fd5b560fb04639fd45926b34e27cfdec678a704"}, + {file = "multidict-5.2.0-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:a37e9a68349f6abe24130846e2f1d2e38f7ddab30b81b754e5a1fde32f782b23"}, + {file = "multidict-5.2.0-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:637c1896497ff19e1ee27c1c2c2ddaa9f2d134bbb5e0c52254361ea20486418d"}, + {file = "multidict-5.2.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:9815765f9dcda04921ba467957be543423e5ec6a1136135d84f2ae092c50d87b"}, + {file = "multidict-5.2.0-cp37-cp37m-win32.whl", hash = "sha256:8b911d74acdc1fe2941e59b4f1a278a330e9c34c6c8ca1ee21264c51ec9b67ef"}, + {file = "multidict-5.2.0-cp37-cp37m-win_amd64.whl", hash = "sha256:380b868f55f63d048a25931a1632818f90e4be71d2081c2338fcf656d299949a"}, + {file = "multidict-5.2.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:e7d81ce5744757d2f05fc41896e3b2ae0458464b14b5a2c1e87a6a9d69aefaa8"}, + {file = "multidict-5.2.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2d1d55cdf706ddc62822d394d1df53573d32a7a07d4f099470d3cb9323b721b6"}, + {file = "multidict-5.2.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:a4771d0d0ac9d9fe9e24e33bed482a13dfc1256d008d101485fe460359476065"}, + {file = "multidict-5.2.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da7d57ea65744d249427793c042094c4016789eb2562576fb831870f9c878d9e"}, + {file = "multidict-5.2.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cdd68778f96216596218b4e8882944d24a634d984ee1a5a049b300377878fa7c"}, + {file = "multidict-5.2.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ecc99bce8ee42dcad15848c7885197d26841cb24fa2ee6e89d23b8993c871c64"}, + {file = "multidict-5.2.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:067150fad08e6f2dd91a650c7a49ba65085303fcc3decbd64a57dc13a2733031"}, + {file = "multidict-5.2.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:78c106b2b506b4d895ddc801ff509f941119394b89c9115580014127414e6c2d"}, + {file = "multidict-5.2.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:e6c4fa1ec16e01e292315ba76eb1d012c025b99d22896bd14a66628b245e3e01"}, + {file = "multidict-5.2.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:b227345e4186809d31f22087d0265655114af7cda442ecaf72246275865bebe4"}, + {file = "multidict-5.2.0-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:06560fbdcf22c9387100979e65b26fba0816c162b888cb65b845d3def7a54c9b"}, + {file = "multidict-5.2.0-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:7878b61c867fb2df7a95e44b316f88d5a3742390c99dfba6c557a21b30180cac"}, + {file = "multidict-5.2.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:246145bff76cc4b19310f0ad28bd0769b940c2a49fc601b86bfd150cbd72bb22"}, + {file = "multidict-5.2.0-cp38-cp38-win32.whl", hash = "sha256:c30ac9f562106cd9e8071c23949a067b10211917fdcb75b4718cf5775356a940"}, + {file = "multidict-5.2.0-cp38-cp38-win_amd64.whl", hash = "sha256:f19001e790013ed580abfde2a4465388950728861b52f0da73e8e8a9418533c0"}, + {file = "multidict-5.2.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c1ff762e2ee126e6f1258650ac641e2b8e1f3d927a925aafcfde943b77a36d24"}, + {file = "multidict-5.2.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:bd6c9c50bf2ad3f0448edaa1a3b55b2e6866ef8feca5d8dbec10ec7c94371d21"}, + {file = "multidict-5.2.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:fc66d4016f6e50ed36fb39cd287a3878ffcebfa90008535c62e0e90a7ab713ae"}, + {file = "multidict-5.2.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a9acb76d5f3dd9421874923da2ed1e76041cb51b9337fd7f507edde1d86535d6"}, + {file = "multidict-5.2.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dfc924a7e946dd3c6360e50e8f750d51e3ef5395c95dc054bc9eab0f70df4f9c"}, + {file = "multidict-5.2.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:32fdba7333eb2351fee2596b756d730d62b5827d5e1ab2f84e6cbb287cc67fe0"}, + {file = "multidict-5.2.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:b9aad49466b8d828b96b9e3630006234879c8d3e2b0a9d99219b3121bc5cdb17"}, + {file = "multidict-5.2.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:93de39267c4c676c9ebb2057e98a8138bade0d806aad4d864322eee0803140a0"}, + {file = "multidict-5.2.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:f9bef5cff994ca3026fcc90680e326d1a19df9841c5e3d224076407cc21471a1"}, + {file = "multidict-5.2.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:5f841c4f14331fd1e36cbf3336ed7be2cb2a8f110ce40ea253e5573387db7621"}, + {file = "multidict-5.2.0-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:38ba256ee9b310da6a1a0f013ef4e422fca30a685bcbec86a969bd520504e341"}, + {file = "multidict-5.2.0-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:3bc3b1621b979621cee9f7b09f024ec76ec03cc365e638126a056317470bde1b"}, + {file = "multidict-5.2.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:6ee908c070020d682e9b42c8f621e8bb10c767d04416e2ebe44e37d0f44d9ad5"}, + {file = "multidict-5.2.0-cp39-cp39-win32.whl", hash = "sha256:1c7976cd1c157fa7ba5456ae5d31ccdf1479680dc9b8d8aa28afabc370df42b8"}, + {file = "multidict-5.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:c9631c642e08b9fff1c6255487e62971d8b8e821808ddd013d8ac058087591ac"}, + {file = "multidict-5.2.0.tar.gz", hash = "sha256:0dd1c93edb444b33ba2274b66f63def8a327d607c6c790772f448a53b6ea59ce"}, ] mypy = [ {file = "mypy-0.910-cp35-cp35m-macosx_10_9_x86_64.whl", hash = "sha256:a155d80ea6cee511a3694b108c4494a39f42de11ee4e61e72bc424c490e46457"}, @@ -2800,8 +3224,8 @@ nest-asyncio = [ {file = "nest_asyncio-1.5.4.tar.gz", hash = "sha256:f969f6013a16fadb4adcf09d11a68a4f617c6049d7af7ac2c676110169a63abd"}, ] notebook = [ - {file = "notebook-6.4.8-py3-none-any.whl", hash = "sha256:3e702fcc54b8ae597533c3864793b7a1e971dec9e112f67235828d8a798fd654"}, - {file = "notebook-6.4.8.tar.gz", hash = "sha256:1e985c9dc6f678bdfffb9dc657306b5469bfa62d73e03f74e8defbf76d284312"}, + {file = "notebook-6.4.10-py3-none-any.whl", hash = "sha256:49cead814bff0945fcb2ee07579259418672ac175d3dc3d8102a4b0a656ed4df"}, + {file = "notebook-6.4.10.tar.gz", hash = "sha256:2408a76bc6289283a8eecfca67e298ec83c67db51a4c2e1b713dd180bb39e90e"}, ] numpy = [ {file = "numpy-1.18.5-cp35-cp35m-macosx_10_9_intel.whl", hash = "sha256:e91d31b34fc7c2c8f756b4e902f901f856ae53a93399368d9a0dc7be17ed2ca0"}, @@ -3190,11 +3614,11 @@ pywin32 = [ {file = "pywin32-303-cp39-cp39-win_amd64.whl", hash = "sha256:79cbb862c11b9af19bcb682891c1b91942ec2ff7de8151e2aea2e175899cda34"}, ] pywinpty = [ - {file = "pywinpty-2.0.2-cp310-none-win_amd64.whl", hash = "sha256:4b421379b407bf2f52a64a4c58f61deffe623b5add02d871acb290b771bb6227"}, - {file = "pywinpty-2.0.2-cp37-none-win_amd64.whl", hash = "sha256:238b75fc456a6bc558761a89c9e6b3c8f2f54d79db03ae28997a68313c24b2ca"}, - {file = "pywinpty-2.0.2-cp38-none-win_amd64.whl", hash = "sha256:344858a0b956fdc64a547d5e1980b0257b47f5433ed7cb89bf7b6268cb280c6c"}, - {file = "pywinpty-2.0.2-cp39-none-win_amd64.whl", hash = "sha256:a4a066eaf2e30944d3028d946883ceb7883a499b53c4b89ca2d54bd7a4210550"}, - {file = "pywinpty-2.0.2.tar.gz", hash = "sha256:20ec117183f79642eff555ce0dd1823f942618d65813fb6122d14b6e34b5d05a"}, + {file = "pywinpty-2.0.3-cp310-none-win_amd64.whl", hash = "sha256:7a330ef7a2ce284370b1a1fdd2a80c523585464fa5e5ab934c9f27220fa7feab"}, + {file = "pywinpty-2.0.3-cp37-none-win_amd64.whl", hash = "sha256:6455f1075f978942d318f95616661c605d5e0f991c5b176c0c852d237aafefc0"}, + {file = "pywinpty-2.0.3-cp38-none-win_amd64.whl", hash = "sha256:2e7a288a8121393c526d4e6ec7d65edef75d68c7787ab9560e438df867b75a5d"}, + {file = "pywinpty-2.0.3-cp39-none-win_amd64.whl", hash = "sha256:def51627e6aa659f33ea7a0ea4c6b68365c83af4aad7940600f844746817a0ed"}, + {file = "pywinpty-2.0.3.tar.gz", hash = "sha256:6b29a826e896105370c38d53904c3aaac6c36146a50448fc0ed5082cf9d092bc"}, ] pyzmq = [ {file = "pyzmq-22.3.0-cp310-cp310-macosx_10_15_universal2.whl", hash = "sha256:6b217b8f9dfb6628f74b94bdaf9f7408708cb02167d644edca33f38746ca12dd"}, @@ -3245,8 +3669,12 @@ pyzmq = [ {file = "pyzmq-22.3.0-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:d6157793719de168b199194f6b6173f0ccd3bf3499e6870fac17086072e39115"}, {file = "pyzmq-22.3.0.tar.gz", hash = "sha256:8eddc033e716f8c91c6a2112f0a8ebc5e00532b4a6ae1eb0ccc48e027f9c671c"}, ] +rdflib = [ + {file = "rdflib-5.0.0-py3-none-any.whl", hash = "sha256:88208ea971a87886d60ae2b1a4b2cdc263527af0454c422118d43fe64b357877"}, + {file = "rdflib-5.0.0.tar.gz", hash = "sha256:78149dd49d385efec3b3adfbd61c87afaf1281c30d3fcaf1b323b34f603fb155"}, +] redshift-connector = [ - {file = "redshift_connector-2.0.904-py3-none-any.whl", hash = "sha256:e8dec071e76bb98aa4f8eeae3ac34fc68618c47a735903093477f3946eb181e1"}, + {file = "redshift_connector-2.0.905-py3-none-any.whl", hash = "sha256:e97074c6a5fb87a3f9697462ebd97072d30bf0ab418dc48574c8ae29e4a7d060"}, ] requests = [ {file = "requests-2.27.1-py2.py3-none-any.whl", hash = "sha256:f22fa1e554c9ddfd16e6e41ac79759e17be9e492b3587efa038054674760e72d"}, @@ -3261,15 +3689,15 @@ responses = [ {file = "responses-0.17.0.tar.gz", hash = "sha256:ec675e080d06bf8d1fb5e5a68a1e5cd0df46b09c78230315f650af5e4036bec7"}, ] restructuredtext-lint = [ - {file = "restructuredtext_lint-1.3.2.tar.gz", hash = "sha256:d3b10a1fe2ecac537e51ae6d151b223b78de9fafdd50e5eb6b08c243df173c80"}, + {file = "restructuredtext_lint-1.4.0.tar.gz", hash = "sha256:1b235c0c922341ab6c530390892eb9e92f90b9b75046063e047cacfb0f050c45"}, ] s3fs = [ {file = "s3fs-0.4.2-py3-none-any.whl", hash = "sha256:91c1dfb45e5217bd441a7a560946fe865ced6225ff7eb0fb459fe6e601a95ed3"}, {file = "s3fs-0.4.2.tar.gz", hash = "sha256:2ca5de8dc18ad7ad350c0bd01aef0406aa5d0fff78a561f0f710f9d9858abdd0"}, ] s3transfer = [ - {file = "s3transfer-0.5.1-py3-none-any.whl", hash = "sha256:25c140f5c66aa79e1ac60be50dcd45ddc59e83895f062a3aab263b870102911f"}, - {file = "s3transfer-0.5.1.tar.gz", hash = "sha256:69d264d3e760e569b78aaa0f22c97e955891cd22e32b10c51f784eeda4d9d10a"}, + {file = "s3transfer-0.5.2-py3-none-any.whl", hash = "sha256:7a6f4c4d1fdb9a2b640244008e142cbc2cd3ae34b386584ef044dd0f27101971"}, + {file = "s3transfer-0.5.2.tar.gz", hash = "sha256:95c58c194ce657a5f4fb0b9e60a84968c808888aed628cd98ab8771fe1db98ed"}, ] scramp = [ {file = "scramp-1.4.1-py3-none-any.whl", hash = "sha256:93c9cc2ffe54a451e02981c07a5a23cbd830701102789939cfb4ff91efd6ca8c"}, @@ -3295,6 +3723,13 @@ soupsieve = [ {file = "soupsieve-2.3.1-py3-none-any.whl", hash = "sha256:1a3cca2617c6b38c0343ed661b1fa5de5637f257d4fe22bd9f1338010a1efefb"}, {file = "soupsieve-2.3.1.tar.gz", hash = "sha256:b8d49b1cd4f037c7082a9683dfa1801aa2597fb11c3a1155b7a5b94829b4f1f9"}, ] +sparqlwrapper = [ + {file = "SPARQLWrapper-1.8.5-py2-none-any.whl", hash = "sha256:357ee8a27bc910ea13d77836dbddd0b914991495b8cc1bf70676578155e962a8"}, + {file = "SPARQLWrapper-1.8.5-py2.7.egg", hash = "sha256:17ec44b08b8ae2888c801066249f74fe328eec25d90203ce7eadaf82e64484c7"}, + {file = "SPARQLWrapper-1.8.5-py3-none-any.whl", hash = "sha256:c7f9c9d8ebb13428771bc3b6dee54197422507dcc3dea34e30d5dcfc53478dec"}, + {file = "SPARQLWrapper-1.8.5-py3.4.egg", hash = "sha256:8cf6c21126ed76edc85c5c232fd6f77b9f61f8ad1db90a7147cdde2104aff145"}, + {file = "SPARQLWrapper-1.8.5.tar.gz", hash = "sha256:d6a66b5b8cda141660e07aeb00472db077a98d22cb588c973209c7336850fb3c"}, +] sphinx = [ {file = "Sphinx-4.3.2-py3-none-any.whl", hash = "sha256:6a11ea5dd0bdb197f9c2abc2e0ce73e01340464feaece525e64036546d24c851"}, {file = "Sphinx-4.3.2.tar.gz", hash = "sha256:0a8836751a68306b3fe97ecbe44db786f8479c3bf4b80e3a7f5c838657b4698c"}, @@ -3336,8 +3771,8 @@ terminado = [ {file = "terminado-0.13.0.tar.gz", hash = "sha256:713531ccb5db7d4f544651f14050da79809030f00d1afa21462088cf32fb143a"}, ] testpath = [ - {file = "testpath-0.5.0-py3-none-any.whl", hash = "sha256:8044f9a0bab6567fc644a3593164e872543bb44225b0e24846e2c89237937589"}, - {file = "testpath-0.5.0.tar.gz", hash = "sha256:1acf7a0bcd3004ae8357409fc33751e16d37ccc650921da1094a86581ad1e417"}, + {file = "testpath-0.6.0-py3-none-any.whl", hash = "sha256:8ada9f80a2ac6fb0391aa7cdb1a7d11cfa8429f693eda83f74dde570fe6fa639"}, + {file = "testpath-0.6.0.tar.gz", hash = "sha256:2f1b97e6442c02681ebe01bd84f531028a7caea1af3825000f52345c30285e0f"}, ] toml = [ {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"}, @@ -3435,12 +3870,12 @@ typing-extensions = [ {file = "typing_extensions-4.1.1.tar.gz", hash = "sha256:1a9462dcc3347a79b1f1c0271fbe79e844580bb598bafa1ed208b94da3cdcd42"}, ] urllib3 = [ - {file = "urllib3-1.26.8-py2.py3-none-any.whl", hash = "sha256:000ca7f471a233c2251c6c7023ee85305721bfdf18621ebff4fd17a8653427ed"}, - {file = "urllib3-1.26.8.tar.gz", hash = "sha256:0e7c33d9a63e7ddfcb86780aac87befc2fbddf46c58dbb487e0855f7ceec283c"}, + {file = "urllib3-1.26.9-py2.py3-none-any.whl", hash = "sha256:44ece4d53fb1706f667c9bd1c648f5469a2ec925fcf3a776667042d645472c14"}, + {file = "urllib3-1.26.9.tar.gz", hash = "sha256:aabaf16477806a5e1dd19aa41f8c2b7950dd3c746362d7e3223dbe6de6ac448e"}, ] virtualenv = [ - {file = "virtualenv-20.13.1-py2.py3-none-any.whl", hash = "sha256:45e1d053cad4cd453181ae877c4ffc053546ae99e7dd049b9ff1d9be7491abf7"}, - {file = "virtualenv-20.13.1.tar.gz", hash = "sha256:e0621bcbf4160e4e1030f05065c8834b4e93f4fcc223255db2a823440aca9c14"}, + {file = "virtualenv-20.13.4-py2.py3-none-any.whl", hash = "sha256:c3e01300fb8495bc00ed70741f5271fc95fed067eb7106297be73d30879af60c"}, + {file = "virtualenv-20.13.4.tar.gz", hash = "sha256:ce8901d3bbf3b90393498187f2d56797a8a452fb2d0d7efc6fd837554d6f679c"}, ] wcwidth = [ {file = "wcwidth-0.2.5-py2.py3-none-any.whl", hash = "sha256:beb4802a9cebb9144e99086eff703a642a13d6a0052920003a230f3294bbe784"}, @@ -3451,8 +3886,8 @@ webencodings = [ {file = "webencodings-0.5.1.tar.gz", hash = "sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923"}, ] websocket-client = [ - {file = "websocket-client-1.2.3.tar.gz", hash = "sha256:1315816c0acc508997eb3ae03b9d3ff619c9d12d544c9a9b553704b1cc4f6af5"}, - {file = "websocket_client-1.2.3-py3-none-any.whl", hash = "sha256:2eed4cc58e4d65613ed6114af2f380f7910ff416fc8c46947f6e76b6815f56c0"}, + {file = "websocket-client-1.3.1.tar.gz", hash = "sha256:6278a75065395418283f887de7c3beafb3aa68dada5cacbe4b214e8d26da499b"}, + {file = "websocket_client-1.3.1-py3-none-any.whl", hash = "sha256:074e2ed575e7c822fc0940d31c3ac9bb2b1142c303eafcf3e304e6ce035522e8"}, ] werkzeug = [ {file = "Werkzeug-2.0.3-py3-none-any.whl", hash = "sha256:1421ebfc7648a39a5c58c601b154165d05cf47a3cd0ccb70857cbdacf6c8f2b8"}, @@ -3523,6 +3958,80 @@ xmltodict = [ {file = "xmltodict-0.12.0-py2.py3-none-any.whl", hash = "sha256:8bbcb45cc982f48b2ca8fe7e7827c5d792f217ecf1792626f808bf41c3b86051"}, {file = "xmltodict-0.12.0.tar.gz", hash = "sha256:50d8c638ed7ecb88d90561beedbf720c9b4e851a9fa6c47ebd64e99d166d8a21"}, ] +yarl = [ + {file = "yarl-1.7.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:f2a8508f7350512434e41065684076f640ecce176d262a7d54f0da41d99c5a95"}, + {file = "yarl-1.7.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:da6df107b9ccfe52d3a48165e48d72db0eca3e3029b5b8cb4fe6ee3cb870ba8b"}, + {file = "yarl-1.7.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a1d0894f238763717bdcfea74558c94e3bc34aeacd3351d769460c1a586a8b05"}, + {file = "yarl-1.7.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dfe4b95b7e00c6635a72e2d00b478e8a28bfb122dc76349a06e20792eb53a523"}, + {file = "yarl-1.7.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c145ab54702334c42237a6c6c4cc08703b6aa9b94e2f227ceb3d477d20c36c63"}, + {file = "yarl-1.7.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1ca56f002eaf7998b5fcf73b2421790da9d2586331805f38acd9997743114e98"}, + {file = "yarl-1.7.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:1d3d5ad8ea96bd6d643d80c7b8d5977b4e2fb1bab6c9da7322616fd26203d125"}, + {file = "yarl-1.7.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:167ab7f64e409e9bdd99333fe8c67b5574a1f0495dcfd905bc7454e766729b9e"}, + {file = "yarl-1.7.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:95a1873b6c0dd1c437fb3bb4a4aaa699a48c218ac7ca1e74b0bee0ab16c7d60d"}, + {file = "yarl-1.7.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:6152224d0a1eb254f97df3997d79dadd8bb2c1a02ef283dbb34b97d4f8492d23"}, + {file = "yarl-1.7.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:5bb7d54b8f61ba6eee541fba4b83d22b8a046b4ef4d8eb7f15a7e35db2e1e245"}, + {file = "yarl-1.7.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:9c1f083e7e71b2dd01f7cd7434a5f88c15213194df38bc29b388ccdf1492b739"}, + {file = "yarl-1.7.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:f44477ae29025d8ea87ec308539f95963ffdc31a82f42ca9deecf2d505242e72"}, + {file = "yarl-1.7.2-cp310-cp310-win32.whl", hash = "sha256:cff3ba513db55cc6a35076f32c4cdc27032bd075c9faef31fec749e64b45d26c"}, + {file = "yarl-1.7.2-cp310-cp310-win_amd64.whl", hash = "sha256:c9c6d927e098c2d360695f2e9d38870b2e92e0919be07dbe339aefa32a090265"}, + {file = "yarl-1.7.2-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:9b4c77d92d56a4c5027572752aa35082e40c561eec776048330d2907aead891d"}, + {file = "yarl-1.7.2-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c01a89a44bb672c38f42b49cdb0ad667b116d731b3f4c896f72302ff77d71656"}, + {file = "yarl-1.7.2-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c19324a1c5399b602f3b6e7db9478e5b1adf5cf58901996fc973fe4fccd73eed"}, + {file = "yarl-1.7.2-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3abddf0b8e41445426d29f955b24aeecc83fa1072be1be4e0d194134a7d9baee"}, + {file = "yarl-1.7.2-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:6a1a9fe17621af43e9b9fcea8bd088ba682c8192d744b386ee3c47b56eaabb2c"}, + {file = "yarl-1.7.2-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:8b0915ee85150963a9504c10de4e4729ae700af11df0dc5550e6587ed7891e92"}, + {file = "yarl-1.7.2-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:29e0656d5497733dcddc21797da5a2ab990c0cb9719f1f969e58a4abac66234d"}, + {file = "yarl-1.7.2-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:bf19725fec28452474d9887a128e98dd67eee7b7d52e932e6949c532d820dc3b"}, + {file = "yarl-1.7.2-cp36-cp36m-musllinux_1_1_ppc64le.whl", hash = "sha256:d6f3d62e16c10e88d2168ba2d065aa374e3c538998ed04996cd373ff2036d64c"}, + {file = "yarl-1.7.2-cp36-cp36m-musllinux_1_1_s390x.whl", hash = "sha256:ac10bbac36cd89eac19f4e51c032ba6b412b3892b685076f4acd2de18ca990aa"}, + {file = "yarl-1.7.2-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:aa32aaa97d8b2ed4e54dc65d241a0da1c627454950f7d7b1f95b13985afd6c5d"}, + {file = "yarl-1.7.2-cp36-cp36m-win32.whl", hash = "sha256:87f6e082bce21464857ba58b569370e7b547d239ca22248be68ea5d6b51464a1"}, + {file = "yarl-1.7.2-cp36-cp36m-win_amd64.whl", hash = "sha256:ac35ccde589ab6a1870a484ed136d49a26bcd06b6a1c6397b1967ca13ceb3913"}, + {file = "yarl-1.7.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:a467a431a0817a292121c13cbe637348b546e6ef47ca14a790aa2fa8cc93df63"}, + {file = "yarl-1.7.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6ab0c3274d0a846840bf6c27d2c60ba771a12e4d7586bf550eefc2df0b56b3b4"}, + {file = "yarl-1.7.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d260d4dc495c05d6600264a197d9d6f7fc9347f21d2594926202fd08cf89a8ba"}, + {file = "yarl-1.7.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fc4dd8b01a8112809e6b636b00f487846956402834a7fd59d46d4f4267181c41"}, + {file = "yarl-1.7.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:c1164a2eac148d85bbdd23e07dfcc930f2e633220f3eb3c3e2a25f6148c2819e"}, + {file = "yarl-1.7.2-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:67e94028817defe5e705079b10a8438b8cb56e7115fa01640e9c0bb3edf67332"}, + {file = "yarl-1.7.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:89ccbf58e6a0ab89d487c92a490cb5660d06c3a47ca08872859672f9c511fc52"}, + {file = "yarl-1.7.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:8cce6f9fa3df25f55521fbb5c7e4a736683148bcc0c75b21863789e5185f9185"}, + {file = "yarl-1.7.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:211fcd65c58bf250fb994b53bc45a442ddc9f441f6fec53e65de8cba48ded986"}, + {file = "yarl-1.7.2-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:c10ea1e80a697cf7d80d1ed414b5cb8f1eec07d618f54637067ae3c0334133c4"}, + {file = "yarl-1.7.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:52690eb521d690ab041c3919666bea13ab9fbff80d615ec16fa81a297131276b"}, + {file = "yarl-1.7.2-cp37-cp37m-win32.whl", hash = "sha256:695ba021a9e04418507fa930d5f0704edbce47076bdcfeeaba1c83683e5649d1"}, + {file = "yarl-1.7.2-cp37-cp37m-win_amd64.whl", hash = "sha256:c17965ff3706beedafd458c452bf15bac693ecd146a60a06a214614dc097a271"}, + {file = "yarl-1.7.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:fce78593346c014d0d986b7ebc80d782b7f5e19843ca798ed62f8e3ba8728576"}, + {file = "yarl-1.7.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:c2a1ac41a6aa980db03d098a5531f13985edcb451bcd9d00670b03129922cd0d"}, + {file = "yarl-1.7.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:39d5493c5ecd75c8093fa7700a2fb5c94fe28c839c8e40144b7ab7ccba6938c8"}, + {file = "yarl-1.7.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1eb6480ef366d75b54c68164094a6a560c247370a68c02dddb11f20c4c6d3c9d"}, + {file = "yarl-1.7.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5ba63585a89c9885f18331a55d25fe81dc2d82b71311ff8bd378fc8004202ff6"}, + {file = "yarl-1.7.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e39378894ee6ae9f555ae2de332d513a5763276a9265f8e7cbaeb1b1ee74623a"}, + {file = "yarl-1.7.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:c0910c6b6c31359d2f6184828888c983d54d09d581a4a23547a35f1d0b9484b1"}, + {file = "yarl-1.7.2-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:6feca8b6bfb9eef6ee057628e71e1734caf520a907b6ec0d62839e8293e945c0"}, + {file = "yarl-1.7.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:8300401dc88cad23f5b4e4c1226f44a5aa696436a4026e456fe0e5d2f7f486e6"}, + {file = "yarl-1.7.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:788713c2896f426a4e166b11f4ec538b5736294ebf7d5f654ae445fd44270832"}, + {file = "yarl-1.7.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:fd547ec596d90c8676e369dd8a581a21227fe9b4ad37d0dc7feb4ccf544c2d59"}, + {file = "yarl-1.7.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:737e401cd0c493f7e3dd4db72aca11cfe069531c9761b8ea474926936b3c57c8"}, + {file = "yarl-1.7.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:baf81561f2972fb895e7844882898bda1eef4b07b5b385bcd308d2098f1a767b"}, + {file = "yarl-1.7.2-cp38-cp38-win32.whl", hash = "sha256:ede3b46cdb719c794427dcce9d8beb4abe8b9aa1e97526cc20de9bd6583ad1ef"}, + {file = "yarl-1.7.2-cp38-cp38-win_amd64.whl", hash = "sha256:cc8b7a7254c0fc3187d43d6cb54b5032d2365efd1df0cd1749c0c4df5f0ad45f"}, + {file = "yarl-1.7.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:580c1f15500e137a8c37053e4cbf6058944d4c114701fa59944607505c2fe3a0"}, + {file = "yarl-1.7.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3ec1d9a0d7780416e657f1e405ba35ec1ba453a4f1511eb8b9fbab81cb8b3ce1"}, + {file = "yarl-1.7.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3bf8cfe8856708ede6a73907bf0501f2dc4e104085e070a41f5d88e7faf237f3"}, + {file = "yarl-1.7.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1be4bbb3d27a4e9aa5f3df2ab61e3701ce8fcbd3e9846dbce7c033a7e8136746"}, + {file = "yarl-1.7.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:534b047277a9a19d858cde163aba93f3e1677d5acd92f7d10ace419d478540de"}, + {file = "yarl-1.7.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c6ddcd80d79c96eb19c354d9dca95291589c5954099836b7c8d29278a7ec0bda"}, + {file = "yarl-1.7.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:9bfcd43c65fbb339dc7086b5315750efa42a34eefad0256ba114cd8ad3896f4b"}, + {file = "yarl-1.7.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f64394bd7ceef1237cc604b5a89bf748c95982a84bcd3c4bbeb40f685c810794"}, + {file = "yarl-1.7.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:044daf3012e43d4b3538562da94a88fb12a6490652dbc29fb19adfa02cf72eac"}, + {file = "yarl-1.7.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:368bcf400247318382cc150aaa632582d0780b28ee6053cd80268c7e72796dec"}, + {file = "yarl-1.7.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:bab827163113177aee910adb1f48ff7af31ee0289f434f7e22d10baf624a6dfe"}, + {file = "yarl-1.7.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:0cba38120db72123db7c58322fa69e3c0efa933040ffb586c3a87c063ec7cae8"}, + {file = "yarl-1.7.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:59218fef177296451b23214c91ea3aba7858b4ae3306dde120224cfe0f7a6ee8"}, + {file = "yarl-1.7.2-cp39-cp39-win32.whl", hash = "sha256:1edc172dcca3f11b38a9d5c7505c83c1913c0addc99cd28e993efeaafdfaa18d"}, + {file = "yarl-1.7.2-cp39-cp39-win_amd64.whl", hash = "sha256:797c2c412b04403d2da075fb93c123df35239cd7b4cc4e0cd9e5839b73f52c58"}, + {file = "yarl-1.7.2.tar.gz", hash = "sha256:45399b46d60c253327a460e99856752009fcee5f5d3c80b2f7c0cae1c38d56dd"}, +] zipp = [ {file = "zipp-3.6.0-py3-none-any.whl", hash = "sha256:9fe5ea21568a0a70e50f273397638d39b03353731e6cbbb3fd8502a33fec40bc"}, {file = "zipp-3.6.0.tar.gz", hash = "sha256:71c644c5369f4a6e07636f0aa966270449561fcea2e3d6747b8d23efaa9d7832"}, diff --git a/pyproject.toml b/pyproject.toml index 2668fb9f2..2321c060b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -49,6 +49,9 @@ progressbar2 = "^3.53.3" opensearch-py = "^1.0.0" xlrd = { version = "^2.0.1", python = "~3.6" } xlwt = { version = "^1.3.0", python = "~3.6" } +gremlinpython = "^3.5.2" +backoff = "^1.11.1" +SPARQLWrapper = "^1.8.5" pyodbc = { version = "~4.0.32", optional = true } [tool.poetry.extras] diff --git a/test_infra/poetry.lock b/test_infra/poetry.lock index 164515b8b..b7d577cbf 100644 --- a/test_infra/poetry.lock +++ b/test_infra/poetry.lock @@ -1,652 +1,688 @@ [[package]] name = "attrs" -version = "21.2.0" +version = "21.4.0" description = "Classes Without Boilerplate" category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" [package.extras] -dev = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "zope.interface", "furo", "sphinx", "sphinx-notfound-page", "pre-commit"] +dev = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "zope.interface", "furo", "sphinx", "sphinx-notfound-page", "pre-commit", "cloudpickle"] docs = ["furo", "sphinx", "zope.interface", "sphinx-notfound-page"] -tests = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "zope.interface"] -tests_no_zope = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins"] +tests = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "zope.interface", "cloudpickle"] +tests_no_zope = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "cloudpickle"] [[package]] name = "aws-cdk.assets" -version = "1.130.0" +version = "1.148.0" description = "This module is deprecated. All types are now available under the core module" category = "main" optional = false python-versions = ">=3.6" [package.dependencies] -"aws-cdk.core" = "1.130.0" -"aws-cdk.cx-api" = "1.130.0" +"aws-cdk.core" = "1.148.0" +"aws-cdk.cx-api" = "1.148.0" constructs = ">=3.3.69,<4.0.0" -jsii = ">=1.41.0,<2.0.0" +jsii = ">=1.54.0,<2.0.0" +publication = ">=0.0.3" + +[[package]] +name = "aws-cdk.aws-acmpca" +version = "1.148.0" +description = "The CDK Construct Library for AWS::ACMPCA" +category = "main" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +"aws-cdk.core" = "1.148.0" +constructs = ">=3.3.69,<4.0.0" +jsii = ">=1.54.0,<2.0.0" publication = ">=0.0.3" [[package]] name = "aws-cdk.aws-applicationautoscaling" -version = "1.130.0" +version = "1.148.0" description = "The CDK Construct Library for AWS::ApplicationAutoScaling" category = "main" optional = false python-versions = ">=3.6" [package.dependencies] -"aws-cdk.aws-autoscaling-common" = "1.130.0" -"aws-cdk.aws-cloudwatch" = "1.130.0" -"aws-cdk.aws-iam" = "1.130.0" -"aws-cdk.core" = "1.130.0" +"aws-cdk.aws-autoscaling-common" = "1.148.0" +"aws-cdk.aws-cloudwatch" = "1.148.0" +"aws-cdk.aws-iam" = "1.148.0" +"aws-cdk.core" = "1.148.0" constructs = ">=3.3.69,<4.0.0" -jsii = ">=1.41.0,<2.0.0" +jsii = ">=1.54.0,<2.0.0" publication = ">=0.0.3" [[package]] name = "aws-cdk.aws-autoscaling-common" -version = "1.130.0" +version = "1.148.0" description = "Common implementation package for @aws-cdk/aws-autoscaling and @aws-cdk/aws-applicationautoscaling" category = "main" optional = false python-versions = ">=3.6" [package.dependencies] -"aws-cdk.aws-iam" = "1.130.0" -"aws-cdk.core" = "1.130.0" +"aws-cdk.aws-iam" = "1.148.0" +"aws-cdk.core" = "1.148.0" constructs = ">=3.3.69,<4.0.0" -jsii = ">=1.41.0,<2.0.0" +jsii = ">=1.54.0,<2.0.0" publication = ">=0.0.3" [[package]] name = "aws-cdk.aws-certificatemanager" -version = "1.130.0" +version = "1.148.0" description = "The CDK Construct Library for AWS::CertificateManager" category = "main" optional = false python-versions = ">=3.6" [package.dependencies] -"aws-cdk.aws-cloudwatch" = "1.130.0" -"aws-cdk.aws-iam" = "1.130.0" -"aws-cdk.aws-lambda" = "1.130.0" -"aws-cdk.aws-route53" = "1.130.0" -"aws-cdk.core" = "1.130.0" +"aws-cdk.aws-acmpca" = "1.148.0" +"aws-cdk.aws-cloudwatch" = "1.148.0" +"aws-cdk.aws-iam" = "1.148.0" +"aws-cdk.aws-lambda" = "1.148.0" +"aws-cdk.aws-route53" = "1.148.0" +"aws-cdk.core" = "1.148.0" constructs = ">=3.3.69,<4.0.0" -jsii = ">=1.41.0,<2.0.0" +jsii = ">=1.54.0,<2.0.0" publication = ">=0.0.3" [[package]] name = "aws-cdk.aws-cloudformation" -version = "1.130.0" +version = "1.148.0" description = "The CDK Construct Library for AWS::CloudFormation" category = "main" optional = false python-versions = ">=3.6" [package.dependencies] -"aws-cdk.aws-iam" = "1.130.0" -"aws-cdk.aws-lambda" = "1.130.0" -"aws-cdk.aws-s3" = "1.130.0" -"aws-cdk.aws-sns" = "1.130.0" -"aws-cdk.core" = "1.130.0" -"aws-cdk.cx-api" = "1.130.0" +"aws-cdk.aws-iam" = "1.148.0" +"aws-cdk.aws-lambda" = "1.148.0" +"aws-cdk.aws-s3" = "1.148.0" +"aws-cdk.aws-sns" = "1.148.0" +"aws-cdk.core" = "1.148.0" +"aws-cdk.cx-api" = "1.148.0" constructs = ">=3.3.69,<4.0.0" -jsii = ">=1.41.0,<2.0.0" +jsii = ">=1.54.0,<2.0.0" publication = ">=0.0.3" [[package]] name = "aws-cdk.aws-cloudwatch" -version = "1.130.0" +version = "1.148.0" description = "The CDK Construct Library for AWS::CloudWatch" category = "main" optional = false python-versions = ">=3.6" [package.dependencies] -"aws-cdk.aws-iam" = "1.130.0" -"aws-cdk.core" = "1.130.0" +"aws-cdk.aws-iam" = "1.148.0" +"aws-cdk.core" = "1.148.0" constructs = ">=3.3.69,<4.0.0" -jsii = ">=1.41.0,<2.0.0" +jsii = ">=1.54.0,<2.0.0" publication = ">=0.0.3" [[package]] name = "aws-cdk.aws-codeguruprofiler" -version = "1.130.0" +version = "1.148.0" description = "The CDK Construct Library for AWS::CodeGuruProfiler" category = "main" optional = false python-versions = ">=3.6" [package.dependencies] -"aws-cdk.aws-iam" = "1.130.0" -"aws-cdk.core" = "1.130.0" +"aws-cdk.aws-iam" = "1.148.0" +"aws-cdk.core" = "1.148.0" constructs = ">=3.3.69,<4.0.0" -jsii = ">=1.41.0,<2.0.0" +jsii = ">=1.54.0,<2.0.0" publication = ">=0.0.3" [[package]] name = "aws-cdk.aws-codestarnotifications" -version = "1.130.0" +version = "1.148.0" description = "The CDK Construct Library for AWS::CodeStarNotifications" category = "main" optional = false python-versions = ">=3.6" [package.dependencies] -"aws-cdk.core" = "1.130.0" +"aws-cdk.core" = "1.148.0" constructs = ">=3.3.69,<4.0.0" -jsii = ">=1.41.0,<2.0.0" +jsii = ">=1.54.0,<2.0.0" publication = ">=0.0.3" [[package]] name = "aws-cdk.aws-ec2" -version = "1.130.0" +version = "1.148.0" description = "The CDK Construct Library for AWS::EC2" category = "main" optional = false python-versions = ">=3.6" [package.dependencies] -"aws-cdk.aws-cloudwatch" = "1.130.0" -"aws-cdk.aws-iam" = "1.130.0" -"aws-cdk.aws-kms" = "1.130.0" -"aws-cdk.aws-logs" = "1.130.0" -"aws-cdk.aws-s3" = "1.130.0" -"aws-cdk.aws-s3-assets" = "1.130.0" -"aws-cdk.aws-ssm" = "1.130.0" -"aws-cdk.cloud-assembly-schema" = "1.130.0" -"aws-cdk.core" = "1.130.0" -"aws-cdk.cx-api" = "1.130.0" -"aws-cdk.region-info" = "1.130.0" +"aws-cdk.aws-cloudwatch" = "1.148.0" +"aws-cdk.aws-iam" = "1.148.0" +"aws-cdk.aws-kms" = "1.148.0" +"aws-cdk.aws-logs" = "1.148.0" +"aws-cdk.aws-s3" = "1.148.0" +"aws-cdk.aws-s3-assets" = "1.148.0" +"aws-cdk.aws-ssm" = "1.148.0" +"aws-cdk.cloud-assembly-schema" = "1.148.0" +"aws-cdk.core" = "1.148.0" +"aws-cdk.cx-api" = "1.148.0" +"aws-cdk.region-info" = "1.148.0" constructs = ">=3.3.69,<4.0.0" -jsii = ">=1.41.0,<2.0.0" +jsii = ">=1.54.0,<2.0.0" publication = ">=0.0.3" [[package]] name = "aws-cdk.aws-ecr" -version = "1.130.0" +version = "1.148.0" description = "The CDK Construct Library for AWS::ECR" category = "main" optional = false python-versions = ">=3.6" [package.dependencies] -"aws-cdk.aws-events" = "1.130.0" -"aws-cdk.aws-iam" = "1.130.0" -"aws-cdk.core" = "1.130.0" +"aws-cdk.aws-events" = "1.148.0" +"aws-cdk.aws-iam" = "1.148.0" +"aws-cdk.aws-kms" = "1.148.0" +"aws-cdk.core" = "1.148.0" constructs = ">=3.3.69,<4.0.0" -jsii = ">=1.41.0,<2.0.0" +jsii = ">=1.54.0,<2.0.0" publication = ">=0.0.3" [[package]] name = "aws-cdk.aws-ecr-assets" -version = "1.130.0" +version = "1.148.0" description = "Docker image assets deployed to ECR" category = "main" optional = false python-versions = ">=3.6" [package.dependencies] -"aws-cdk.assets" = "1.130.0" -"aws-cdk.aws-ecr" = "1.130.0" -"aws-cdk.aws-iam" = "1.130.0" -"aws-cdk.aws-s3" = "1.130.0" -"aws-cdk.core" = "1.130.0" -"aws-cdk.cx-api" = "1.130.0" +"aws-cdk.assets" = "1.148.0" +"aws-cdk.aws-ecr" = "1.148.0" +"aws-cdk.aws-iam" = "1.148.0" +"aws-cdk.aws-s3" = "1.148.0" +"aws-cdk.core" = "1.148.0" +"aws-cdk.cx-api" = "1.148.0" constructs = ">=3.3.69,<4.0.0" -jsii = ">=1.41.0,<2.0.0" +jsii = ">=1.54.0,<2.0.0" publication = ">=0.0.3" [[package]] name = "aws-cdk.aws-efs" -version = "1.130.0" +version = "1.148.0" description = "The CDK Construct Library for AWS::EFS" category = "main" optional = false python-versions = ">=3.6" [package.dependencies] -"aws-cdk.aws-ec2" = "1.130.0" -"aws-cdk.aws-iam" = "1.130.0" -"aws-cdk.aws-kms" = "1.130.0" -"aws-cdk.cloud-assembly-schema" = "1.130.0" -"aws-cdk.core" = "1.130.0" -"aws-cdk.cx-api" = "1.130.0" +"aws-cdk.aws-ec2" = "1.148.0" +"aws-cdk.aws-iam" = "1.148.0" +"aws-cdk.aws-kms" = "1.148.0" +"aws-cdk.cloud-assembly-schema" = "1.148.0" +"aws-cdk.core" = "1.148.0" +"aws-cdk.cx-api" = "1.148.0" constructs = ">=3.3.69,<4.0.0" -jsii = ">=1.41.0,<2.0.0" +jsii = ">=1.54.0,<2.0.0" publication = ">=0.0.3" [[package]] name = "aws-cdk.aws-events" -version = "1.130.0" +version = "1.148.0" description = "Amazon EventBridge Construct Library" category = "main" optional = false python-versions = ">=3.6" [package.dependencies] -"aws-cdk.aws-iam" = "1.130.0" -"aws-cdk.core" = "1.130.0" +"aws-cdk.aws-iam" = "1.148.0" +"aws-cdk.core" = "1.148.0" constructs = ">=3.3.69,<4.0.0" -jsii = ">=1.41.0,<2.0.0" +jsii = ">=1.54.0,<2.0.0" publication = ">=0.0.3" [[package]] name = "aws-cdk.aws-glue" -version = "1.130.0" +version = "1.148.0" description = "The CDK Construct Library for AWS::Glue" category = "main" optional = false python-versions = ">=3.6" [package.dependencies] -"aws-cdk.assets" = "1.130.0" -"aws-cdk.aws-cloudwatch" = "1.130.0" -"aws-cdk.aws-ec2" = "1.130.0" -"aws-cdk.aws-events" = "1.130.0" -"aws-cdk.aws-iam" = "1.130.0" -"aws-cdk.aws-kms" = "1.130.0" -"aws-cdk.aws-logs" = "1.130.0" -"aws-cdk.aws-s3" = "1.130.0" -"aws-cdk.aws-s3-assets" = "1.130.0" -"aws-cdk.core" = "1.130.0" +"aws-cdk.assets" = "1.148.0" +"aws-cdk.aws-cloudwatch" = "1.148.0" +"aws-cdk.aws-ec2" = "1.148.0" +"aws-cdk.aws-events" = "1.148.0" +"aws-cdk.aws-iam" = "1.148.0" +"aws-cdk.aws-kms" = "1.148.0" +"aws-cdk.aws-logs" = "1.148.0" +"aws-cdk.aws-s3" = "1.148.0" +"aws-cdk.aws-s3-assets" = "1.148.0" +"aws-cdk.core" = "1.148.0" +"aws-cdk.custom-resources" = "1.148.0" constructs = ">=3.3.69,<4.0.0" -jsii = ">=1.41.0,<2.0.0" +jsii = ">=1.54.0,<2.0.0" publication = ">=0.0.3" [[package]] name = "aws-cdk.aws-iam" -version = "1.130.0" +version = "1.148.0" description = "CDK routines for easily assigning correct and minimal IAM permissions" category = "main" optional = false python-versions = ">=3.6" [package.dependencies] -"aws-cdk.core" = "1.130.0" -"aws-cdk.region-info" = "1.130.0" +"aws-cdk.core" = "1.148.0" +"aws-cdk.region-info" = "1.148.0" constructs = ">=3.3.69,<4.0.0" -jsii = ">=1.41.0,<2.0.0" +jsii = ">=1.54.0,<2.0.0" publication = ">=0.0.3" [[package]] name = "aws-cdk.aws-kms" -version = "1.130.0" +version = "1.148.0" description = "The CDK Construct Library for AWS::KMS" category = "main" optional = false python-versions = ">=3.6" [package.dependencies] -"aws-cdk.aws-iam" = "1.130.0" -"aws-cdk.cloud-assembly-schema" = "1.130.0" -"aws-cdk.core" = "1.130.0" -"aws-cdk.cx-api" = "1.130.0" +"aws-cdk.aws-iam" = "1.148.0" +"aws-cdk.cloud-assembly-schema" = "1.148.0" +"aws-cdk.core" = "1.148.0" +"aws-cdk.cx-api" = "1.148.0" constructs = ">=3.3.69,<4.0.0" -jsii = ">=1.41.0,<2.0.0" +jsii = ">=1.54.0,<2.0.0" publication = ">=0.0.3" [[package]] name = "aws-cdk.aws-lakeformation" -version = "1.130.0" +version = "1.148.0" description = "The CDK Construct Library for AWS::LakeFormation" category = "main" optional = false python-versions = ">=3.6" [package.dependencies] -"aws-cdk.core" = "1.130.0" +"aws-cdk.core" = "1.148.0" constructs = ">=3.3.69,<4.0.0" -jsii = ">=1.41.0,<2.0.0" +jsii = ">=1.54.0,<2.0.0" publication = ">=0.0.3" [[package]] name = "aws-cdk.aws-lambda" -version = "1.130.0" +version = "1.148.0" description = "The CDK Construct Library for AWS::Lambda" category = "main" optional = false python-versions = ">=3.6" [package.dependencies] -"aws-cdk.aws-applicationautoscaling" = "1.130.0" -"aws-cdk.aws-cloudwatch" = "1.130.0" -"aws-cdk.aws-codeguruprofiler" = "1.130.0" -"aws-cdk.aws-ec2" = "1.130.0" -"aws-cdk.aws-ecr" = "1.130.0" -"aws-cdk.aws-ecr-assets" = "1.130.0" -"aws-cdk.aws-efs" = "1.130.0" -"aws-cdk.aws-events" = "1.130.0" -"aws-cdk.aws-iam" = "1.130.0" -"aws-cdk.aws-kms" = "1.130.0" -"aws-cdk.aws-logs" = "1.130.0" -"aws-cdk.aws-s3" = "1.130.0" -"aws-cdk.aws-s3-assets" = "1.130.0" -"aws-cdk.aws-signer" = "1.130.0" -"aws-cdk.aws-sqs" = "1.130.0" -"aws-cdk.core" = "1.130.0" -"aws-cdk.cx-api" = "1.130.0" -"aws-cdk.region-info" = "1.130.0" +"aws-cdk.aws-applicationautoscaling" = "1.148.0" +"aws-cdk.aws-cloudwatch" = "1.148.0" +"aws-cdk.aws-codeguruprofiler" = "1.148.0" +"aws-cdk.aws-ec2" = "1.148.0" +"aws-cdk.aws-ecr" = "1.148.0" +"aws-cdk.aws-ecr-assets" = "1.148.0" +"aws-cdk.aws-efs" = "1.148.0" +"aws-cdk.aws-events" = "1.148.0" +"aws-cdk.aws-iam" = "1.148.0" +"aws-cdk.aws-kms" = "1.148.0" +"aws-cdk.aws-logs" = "1.148.0" +"aws-cdk.aws-s3" = "1.148.0" +"aws-cdk.aws-s3-assets" = "1.148.0" +"aws-cdk.aws-signer" = "1.148.0" +"aws-cdk.aws-sns" = "1.148.0" +"aws-cdk.aws-sqs" = "1.148.0" +"aws-cdk.core" = "1.148.0" +"aws-cdk.cx-api" = "1.148.0" +"aws-cdk.region-info" = "1.148.0" constructs = ">=3.3.69,<4.0.0" -jsii = ">=1.41.0,<2.0.0" +jsii = ">=1.54.0,<2.0.0" publication = ">=0.0.3" [[package]] name = "aws-cdk.aws-logs" -version = "1.130.0" +version = "1.148.0" description = "The CDK Construct Library for AWS::Logs" category = "main" optional = false python-versions = ">=3.6" [package.dependencies] -"aws-cdk.aws-cloudwatch" = "1.130.0" -"aws-cdk.aws-iam" = "1.130.0" -"aws-cdk.aws-kms" = "1.130.0" -"aws-cdk.aws-s3-assets" = "1.130.0" -"aws-cdk.core" = "1.130.0" +"aws-cdk.aws-cloudwatch" = "1.148.0" +"aws-cdk.aws-iam" = "1.148.0" +"aws-cdk.aws-kms" = "1.148.0" +"aws-cdk.aws-s3-assets" = "1.148.0" +"aws-cdk.core" = "1.148.0" +"aws-cdk.cx-api" = "1.148.0" +constructs = ">=3.3.69,<4.0.0" +jsii = ">=1.54.0,<2.0.0" +publication = ">=0.0.3" + +[[package]] +name = "aws-cdk.aws-neptune" +version = "1.148.0" +description = "The CDK Construct Library for AWS::Neptune" +category = "main" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +"aws-cdk.aws-ec2" = "1.148.0" +"aws-cdk.aws-iam" = "1.148.0" +"aws-cdk.aws-kms" = "1.148.0" +"aws-cdk.core" = "1.148.0" constructs = ">=3.3.69,<4.0.0" -jsii = ">=1.41.0,<2.0.0" +jsii = ">=1.54.0,<2.0.0" publication = ">=0.0.3" [[package]] name = "aws-cdk.aws-opensearchservice" -version = "1.130.0" +version = "1.148.0" description = "The CDK Construct Library for AWS::OpenSearchService" category = "main" optional = false python-versions = ">=3.6" [package.dependencies] -"aws-cdk.aws-certificatemanager" = "1.130.0" -"aws-cdk.aws-cloudwatch" = "1.130.0" -"aws-cdk.aws-ec2" = "1.130.0" -"aws-cdk.aws-iam" = "1.130.0" -"aws-cdk.aws-kms" = "1.130.0" -"aws-cdk.aws-logs" = "1.130.0" -"aws-cdk.aws-route53" = "1.130.0" -"aws-cdk.aws-secretsmanager" = "1.130.0" -"aws-cdk.core" = "1.130.0" -"aws-cdk.custom-resources" = "1.130.0" +"aws-cdk.aws-certificatemanager" = "1.148.0" +"aws-cdk.aws-cloudwatch" = "1.148.0" +"aws-cdk.aws-ec2" = "1.148.0" +"aws-cdk.aws-iam" = "1.148.0" +"aws-cdk.aws-kms" = "1.148.0" +"aws-cdk.aws-logs" = "1.148.0" +"aws-cdk.aws-route53" = "1.148.0" +"aws-cdk.aws-secretsmanager" = "1.148.0" +"aws-cdk.core" = "1.148.0" +"aws-cdk.custom-resources" = "1.148.0" constructs = ">=3.3.69,<4.0.0" -jsii = ">=1.41.0,<2.0.0" +jsii = ">=1.54.0,<2.0.0" publication = ">=0.0.3" [[package]] name = "aws-cdk.aws-rds" -version = "1.130.0" +version = "1.148.0" description = "The CDK Construct Library for AWS::RDS" category = "main" optional = false python-versions = ">=3.6" [package.dependencies] -"aws-cdk.aws-cloudwatch" = "1.130.0" -"aws-cdk.aws-ec2" = "1.130.0" -"aws-cdk.aws-events" = "1.130.0" -"aws-cdk.aws-iam" = "1.130.0" -"aws-cdk.aws-kms" = "1.130.0" -"aws-cdk.aws-logs" = "1.130.0" -"aws-cdk.aws-s3" = "1.130.0" -"aws-cdk.aws-secretsmanager" = "1.130.0" -"aws-cdk.core" = "1.130.0" -"aws-cdk.cx-api" = "1.130.0" +"aws-cdk.aws-cloudwatch" = "1.148.0" +"aws-cdk.aws-ec2" = "1.148.0" +"aws-cdk.aws-events" = "1.148.0" +"aws-cdk.aws-iam" = "1.148.0" +"aws-cdk.aws-kms" = "1.148.0" +"aws-cdk.aws-logs" = "1.148.0" +"aws-cdk.aws-s3" = "1.148.0" +"aws-cdk.aws-secretsmanager" = "1.148.0" +"aws-cdk.core" = "1.148.0" +"aws-cdk.cx-api" = "1.148.0" constructs = ">=3.3.69,<4.0.0" -jsii = ">=1.41.0,<2.0.0" +jsii = ">=1.54.0,<2.0.0" publication = ">=0.0.3" [[package]] name = "aws-cdk.aws-redshift" -version = "1.130.0" +version = "1.148.0" description = "The CDK Construct Library for AWS::Redshift" category = "main" optional = false python-versions = ">=3.6" [package.dependencies] -"aws-cdk.aws-ec2" = "1.130.0" -"aws-cdk.aws-iam" = "1.130.0" -"aws-cdk.aws-kms" = "1.130.0" -"aws-cdk.aws-lambda" = "1.130.0" -"aws-cdk.aws-s3" = "1.130.0" -"aws-cdk.aws-secretsmanager" = "1.130.0" -"aws-cdk.core" = "1.130.0" -"aws-cdk.custom-resources" = "1.130.0" +"aws-cdk.aws-ec2" = "1.148.0" +"aws-cdk.aws-iam" = "1.148.0" +"aws-cdk.aws-kms" = "1.148.0" +"aws-cdk.aws-lambda" = "1.148.0" +"aws-cdk.aws-s3" = "1.148.0" +"aws-cdk.aws-secretsmanager" = "1.148.0" +"aws-cdk.core" = "1.148.0" +"aws-cdk.custom-resources" = "1.148.0" constructs = ">=3.3.69,<4.0.0" -jsii = ">=1.41.0,<2.0.0" +jsii = ">=1.54.0,<2.0.0" publication = ">=0.0.3" [[package]] name = "aws-cdk.aws-route53" -version = "1.130.0" +version = "1.148.0" description = "The CDK Construct Library for AWS::Route53" category = "main" optional = false python-versions = ">=3.6" [package.dependencies] -"aws-cdk.aws-ec2" = "1.130.0" -"aws-cdk.aws-iam" = "1.130.0" -"aws-cdk.aws-logs" = "1.130.0" -"aws-cdk.cloud-assembly-schema" = "1.130.0" -"aws-cdk.core" = "1.130.0" -"aws-cdk.custom-resources" = "1.130.0" +"aws-cdk.aws-ec2" = "1.148.0" +"aws-cdk.aws-iam" = "1.148.0" +"aws-cdk.aws-logs" = "1.148.0" +"aws-cdk.cloud-assembly-schema" = "1.148.0" +"aws-cdk.core" = "1.148.0" +"aws-cdk.custom-resources" = "1.148.0" constructs = ">=3.3.69,<4.0.0" -jsii = ">=1.41.0,<2.0.0" +jsii = ">=1.54.0,<2.0.0" publication = ">=0.0.3" [[package]] name = "aws-cdk.aws-s3" -version = "1.130.0" +version = "1.148.0" description = "The CDK Construct Library for AWS::S3" category = "main" optional = false python-versions = ">=3.6" [package.dependencies] -"aws-cdk.aws-events" = "1.130.0" -"aws-cdk.aws-iam" = "1.130.0" -"aws-cdk.aws-kms" = "1.130.0" -"aws-cdk.core" = "1.130.0" -"aws-cdk.cx-api" = "1.130.0" +"aws-cdk.aws-events" = "1.148.0" +"aws-cdk.aws-iam" = "1.148.0" +"aws-cdk.aws-kms" = "1.148.0" +"aws-cdk.core" = "1.148.0" +"aws-cdk.cx-api" = "1.148.0" constructs = ">=3.3.69,<4.0.0" -jsii = ">=1.41.0,<2.0.0" +jsii = ">=1.54.0,<2.0.0" publication = ">=0.0.3" [[package]] name = "aws-cdk.aws-s3-assets" -version = "1.130.0" +version = "1.148.0" description = "Deploy local files and directories to S3" category = "main" optional = false python-versions = ">=3.6" [package.dependencies] -"aws-cdk.assets" = "1.130.0" -"aws-cdk.aws-iam" = "1.130.0" -"aws-cdk.aws-kms" = "1.130.0" -"aws-cdk.aws-s3" = "1.130.0" -"aws-cdk.core" = "1.130.0" -"aws-cdk.cx-api" = "1.130.0" +"aws-cdk.assets" = "1.148.0" +"aws-cdk.aws-iam" = "1.148.0" +"aws-cdk.aws-kms" = "1.148.0" +"aws-cdk.aws-s3" = "1.148.0" +"aws-cdk.core" = "1.148.0" +"aws-cdk.cx-api" = "1.148.0" constructs = ">=3.3.69,<4.0.0" -jsii = ">=1.41.0,<2.0.0" +jsii = ">=1.54.0,<2.0.0" publication = ">=0.0.3" [[package]] name = "aws-cdk.aws-sam" -version = "1.130.0" +version = "1.148.0" description = "The CDK Construct Library for the AWS Serverless Application Model (SAM) resources" category = "main" optional = false python-versions = ">=3.6" [package.dependencies] -"aws-cdk.core" = "1.130.0" +"aws-cdk.core" = "1.148.0" constructs = ">=3.3.69,<4.0.0" -jsii = ">=1.41.0,<2.0.0" +jsii = ">=1.54.0,<2.0.0" publication = ">=0.0.3" [[package]] name = "aws-cdk.aws-secretsmanager" -version = "1.130.0" +version = "1.148.0" description = "The CDK Construct Library for AWS::SecretsManager" category = "main" optional = false python-versions = ">=3.6" [package.dependencies] -"aws-cdk.aws-ec2" = "1.130.0" -"aws-cdk.aws-iam" = "1.130.0" -"aws-cdk.aws-kms" = "1.130.0" -"aws-cdk.aws-lambda" = "1.130.0" -"aws-cdk.aws-sam" = "1.130.0" -"aws-cdk.core" = "1.130.0" -"aws-cdk.cx-api" = "1.130.0" +"aws-cdk.aws-ec2" = "1.148.0" +"aws-cdk.aws-iam" = "1.148.0" +"aws-cdk.aws-kms" = "1.148.0" +"aws-cdk.aws-lambda" = "1.148.0" +"aws-cdk.aws-sam" = "1.148.0" +"aws-cdk.core" = "1.148.0" +"aws-cdk.cx-api" = "1.148.0" constructs = ">=3.3.69,<4.0.0" -jsii = ">=1.41.0,<2.0.0" +jsii = ">=1.54.0,<2.0.0" publication = ">=0.0.3" [[package]] name = "aws-cdk.aws-signer" -version = "1.130.0" +version = "1.148.0" description = "The CDK Construct Library for AWS::Signer" category = "main" optional = false python-versions = ">=3.6" [package.dependencies] -"aws-cdk.core" = "1.130.0" +"aws-cdk.core" = "1.148.0" constructs = ">=3.3.69,<4.0.0" -jsii = ">=1.41.0,<2.0.0" +jsii = ">=1.54.0,<2.0.0" publication = ">=0.0.3" [[package]] name = "aws-cdk.aws-sns" -version = "1.130.0" +version = "1.148.0" description = "The CDK Construct Library for AWS::SNS" category = "main" optional = false python-versions = ">=3.6" [package.dependencies] -"aws-cdk.aws-cloudwatch" = "1.130.0" -"aws-cdk.aws-codestarnotifications" = "1.130.0" -"aws-cdk.aws-events" = "1.130.0" -"aws-cdk.aws-iam" = "1.130.0" -"aws-cdk.aws-kms" = "1.130.0" -"aws-cdk.aws-sqs" = "1.130.0" -"aws-cdk.core" = "1.130.0" +"aws-cdk.aws-cloudwatch" = "1.148.0" +"aws-cdk.aws-codestarnotifications" = "1.148.0" +"aws-cdk.aws-events" = "1.148.0" +"aws-cdk.aws-iam" = "1.148.0" +"aws-cdk.aws-kms" = "1.148.0" +"aws-cdk.aws-sqs" = "1.148.0" +"aws-cdk.core" = "1.148.0" constructs = ">=3.3.69,<4.0.0" -jsii = ">=1.41.0,<2.0.0" +jsii = ">=1.54.0,<2.0.0" publication = ">=0.0.3" [[package]] name = "aws-cdk.aws-sqs" -version = "1.130.0" +version = "1.148.0" description = "The CDK Construct Library for AWS::SQS" category = "main" optional = false python-versions = ">=3.6" [package.dependencies] -"aws-cdk.aws-cloudwatch" = "1.130.0" -"aws-cdk.aws-iam" = "1.130.0" -"aws-cdk.aws-kms" = "1.130.0" -"aws-cdk.core" = "1.130.0" +"aws-cdk.aws-cloudwatch" = "1.148.0" +"aws-cdk.aws-iam" = "1.148.0" +"aws-cdk.aws-kms" = "1.148.0" +"aws-cdk.core" = "1.148.0" constructs = ">=3.3.69,<4.0.0" -jsii = ">=1.41.0,<2.0.0" +jsii = ">=1.54.0,<2.0.0" publication = ">=0.0.3" [[package]] name = "aws-cdk.aws-ssm" -version = "1.130.0" +version = "1.148.0" description = "The CDK Construct Library for AWS::SSM" category = "main" optional = false python-versions = ">=3.6" [package.dependencies] -"aws-cdk.aws-iam" = "1.130.0" -"aws-cdk.aws-kms" = "1.130.0" -"aws-cdk.cloud-assembly-schema" = "1.130.0" -"aws-cdk.core" = "1.130.0" +"aws-cdk.aws-iam" = "1.148.0" +"aws-cdk.aws-kms" = "1.148.0" +"aws-cdk.cloud-assembly-schema" = "1.148.0" +"aws-cdk.core" = "1.148.0" constructs = ">=3.3.69,<4.0.0" -jsii = ">=1.41.0,<2.0.0" +jsii = ">=1.54.0,<2.0.0" publication = ">=0.0.3" [[package]] name = "aws-cdk.cloud-assembly-schema" -version = "1.130.0" +version = "1.148.0" description = "Cloud Assembly Schema" category = "main" optional = false python-versions = ">=3.6" [package.dependencies] -jsii = ">=1.41.0,<2.0.0" +jsii = ">=1.54.0,<2.0.0" publication = ">=0.0.3" [[package]] name = "aws-cdk.core" -version = "1.130.0" +version = "1.148.0" description = "AWS Cloud Development Kit Core Library" category = "main" optional = false python-versions = ">=3.6" [package.dependencies] -"aws-cdk.cloud-assembly-schema" = "1.130.0" -"aws-cdk.cx-api" = "1.130.0" -"aws-cdk.region-info" = "1.130.0" +"aws-cdk.cloud-assembly-schema" = "1.148.0" +"aws-cdk.cx-api" = "1.148.0" +"aws-cdk.region-info" = "1.148.0" constructs = ">=3.3.69,<4.0.0" -jsii = ">=1.41.0,<2.0.0" +jsii = ">=1.54.0,<2.0.0" publication = ">=0.0.3" [[package]] name = "aws-cdk.custom-resources" -version = "1.130.0" +version = "1.148.0" description = "Constructs for implementing CDK custom resources" category = "main" optional = false python-versions = ">=3.6" [package.dependencies] -"aws-cdk.aws-cloudformation" = "1.130.0" -"aws-cdk.aws-ec2" = "1.130.0" -"aws-cdk.aws-iam" = "1.130.0" -"aws-cdk.aws-lambda" = "1.130.0" -"aws-cdk.aws-logs" = "1.130.0" -"aws-cdk.aws-sns" = "1.130.0" -"aws-cdk.core" = "1.130.0" +"aws-cdk.aws-cloudformation" = "1.148.0" +"aws-cdk.aws-ec2" = "1.148.0" +"aws-cdk.aws-iam" = "1.148.0" +"aws-cdk.aws-lambda" = "1.148.0" +"aws-cdk.aws-logs" = "1.148.0" +"aws-cdk.aws-sns" = "1.148.0" +"aws-cdk.core" = "1.148.0" constructs = ">=3.3.69,<4.0.0" -jsii = ">=1.41.0,<2.0.0" +jsii = ">=1.54.0,<2.0.0" publication = ">=0.0.3" [[package]] name = "aws-cdk.cx-api" -version = "1.130.0" +version = "1.148.0" description = "Cloud executable protocol" category = "main" optional = false python-versions = ">=3.6" [package.dependencies] -"aws-cdk.cloud-assembly-schema" = "1.130.0" -jsii = ">=1.41.0,<2.0.0" +"aws-cdk.cloud-assembly-schema" = "1.148.0" +jsii = ">=1.54.0,<2.0.0" publication = ">=0.0.3" [[package]] name = "aws-cdk.region-info" -version = "1.130.0" +version = "1.148.0" description = "AWS region information, such as service principal names" category = "main" optional = false python-versions = ">=3.6" [package.dependencies] -jsii = ">=1.41.0,<2.0.0" +jsii = ">=1.54.0,<2.0.0" publication = ">=0.0.3" [[package]] @@ -665,7 +701,7 @@ dev = ["bumpversion", "wheel", "watchdog", "flake8", "tox", "coverage", "sphinx" [[package]] name = "cattrs" -version = "1.8.0" +version = "1.10.0" description = "Composable complex class support for attrs and dataclasses." category = "main" optional = false @@ -673,17 +709,18 @@ python-versions = ">=3.7,<4.0" [package.dependencies] attrs = ">=20" +typing_extensions = {version = "*", markers = "python_version >= \"3.7\" and python_version < \"3.8\""} [[package]] name = "constructs" -version = "3.3.161" +version = "3.3.239" description = "A programming model for composable configuration" category = "main" optional = false python-versions = ">=3.6" [package.dependencies] -jsii = ">=1.37.0,<2.0.0" +jsii = ">=1.55.0,<2.0.0" publication = ">=0.0.3" [[package]] @@ -703,7 +740,7 @@ testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest- [[package]] name = "jsii" -version = "1.42.0" +version = "1.55.0" description = "Python client for jsii runtime" category = "main" optional = false @@ -713,11 +750,11 @@ python-versions = "~=3.6" attrs = ">=21.2,<22.0" cattrs = [ {version = ">=1.0.0,<1.1.0", markers = "python_version < \"3.7\""}, - {version = ">=1.8.0,<1.9.0", markers = "python_version >= \"3.7\""}, + {version = ">=1.8,<1.11", markers = "python_version >= \"3.7\""}, ] importlib-resources = {version = "*", markers = "python_version < \"3.7\""} python-dateutil = "*" -typing-extensions = ">=3.7,<4.0" +typing-extensions = ">=3.7,<5.0" [[package]] name = "publication" @@ -748,11 +785,11 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" [[package]] name = "typing-extensions" -version = "3.10.0.2" -description = "Backported and Experimental Type Hints for Python 3.5+" +version = "4.1.1" +description = "Backported and Experimental Type Hints for Python 3.6+" category = "main" optional = false -python-versions = "*" +python-versions = ">=3.6" [[package]] name = "zipp" @@ -768,175 +805,183 @@ testing = ["pytest (>=4.6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytes [metadata] lock-version = "1.1" -python-versions = ">=3.6.2, <3.10" -content-hash = "6d22ad86171a44206a94d9e9d051c12bb4caf0215a7af535ae5e7d371011afc1" +python-versions = ">=3.6.2, <3.11" +content-hash = "9f90e4f68ba2e716c30094305af07863b127dd0b6a80c5df87d41dd27b2716cb" [metadata.files] attrs = [ - {file = "attrs-21.2.0-py2.py3-none-any.whl", hash = "sha256:149e90d6d8ac20db7a955ad60cf0e6881a3f20d37096140088356da6c716b0b1"}, - {file = "attrs-21.2.0.tar.gz", hash = "sha256:ef6aaac3ca6cd92904cdd0d83f629a15f18053ec84e6432106f7a4d04ae4f5fb"}, + {file = "attrs-21.4.0-py2.py3-none-any.whl", hash = "sha256:2d27e3784d7a565d36ab851fe94887c5eccd6a463168875832a1be79c82828b4"}, + {file = "attrs-21.4.0.tar.gz", hash = "sha256:626ba8234211db98e869df76230a137c4c40a12d72445c45d5f5b716f076e2fd"}, ] "aws-cdk.assets" = [ - {file = "aws-cdk.assets-1.130.0.tar.gz", hash = "sha256:89628550ecfd4f2b3713cc515c5937ee766cc68cd39fc65dc15095a4fc92140f"}, - {file = "aws_cdk.assets-1.130.0-py3-none-any.whl", hash = "sha256:88ee75118c7b34506acac8a3390e0f6360227f95764749ecf0cb8160532fef8d"}, + {file = "aws-cdk.assets-1.148.0.tar.gz", hash = "sha256:c786862b78fdf06224c23bda18f28d5f18cbd780cf32d5211608d788b02fa0c9"}, + {file = "aws_cdk.assets-1.148.0-py3-none-any.whl", hash = "sha256:37f45d702ca70cc7e10e94a8aabdba5471bfbcd231f53096c28b37570776f200"}, +] +"aws-cdk.aws-acmpca" = [ + {file = "aws-cdk.aws-acmpca-1.148.0.tar.gz", hash = "sha256:72b0b84146d077527c4c630d234a50055ebc52747ea0f68f3f1bc0853ef56fe0"}, + {file = "aws_cdk.aws_acmpca-1.148.0-py3-none-any.whl", hash = "sha256:47aa34a106d21c0ad995057fa0d427850bc69aad889b63000074ec50170c26a1"}, ] "aws-cdk.aws-applicationautoscaling" = [ - {file = "aws-cdk.aws-applicationautoscaling-1.130.0.tar.gz", hash = "sha256:c60000e6a2b86392efcfb32066207cff19adbdbe0b68e1ee4281cf5b52255b29"}, - {file = "aws_cdk.aws_applicationautoscaling-1.130.0-py3-none-any.whl", hash = "sha256:0bed99bbc03ae733450e03bd0c6b075fadc13ae0d9363fffa047e6de0d68be60"}, + {file = "aws-cdk.aws-applicationautoscaling-1.148.0.tar.gz", hash = "sha256:3db9a5f1dd4eb16b2155cae95a34051ce3f096993ec0be33de51901230c60ce6"}, + {file = "aws_cdk.aws_applicationautoscaling-1.148.0-py3-none-any.whl", hash = "sha256:7005b070be833c5eb2f621fe93d597cd083352fd5397219ec63d46eca433ef83"}, ] "aws-cdk.aws-autoscaling-common" = [ - {file = "aws-cdk.aws-autoscaling-common-1.130.0.tar.gz", hash = "sha256:bdc5eee7f30163daf0a40b78e888d356da9815057153791daa6bc2b3d1288541"}, - {file = "aws_cdk.aws_autoscaling_common-1.130.0-py3-none-any.whl", hash = "sha256:46bd7dffa2ff4bcb2c3ee86e4881d7994924f23f76b59fb346cbc48a7e5b90e4"}, + {file = "aws-cdk.aws-autoscaling-common-1.148.0.tar.gz", hash = "sha256:7b104e309737acd3146491c4cba9b70b6243bf9d6aefb2f6587e93c35d1bc107"}, + {file = "aws_cdk.aws_autoscaling_common-1.148.0-py3-none-any.whl", hash = "sha256:b1e87e6304b2f5517b56bb7e21a087365c5812f31f14945fc600c53fbe558880"}, ] "aws-cdk.aws-certificatemanager" = [ - {file = "aws-cdk.aws-certificatemanager-1.130.0.tar.gz", hash = "sha256:e95cb1c48e5b37afa10ff0bdac0c0793d276f0c00d26140c6707a1fb0db74dc8"}, - {file = "aws_cdk.aws_certificatemanager-1.130.0-py3-none-any.whl", hash = "sha256:23ceb0486f5e17ed230a651401ce9807faf3efffe793b0e1cef7e224f6ed25c9"}, + {file = "aws-cdk.aws-certificatemanager-1.148.0.tar.gz", hash = "sha256:3ef28550f8724fd60bf1ddfccfd9f2727947fffa27079c5f841d64e7f2c2bddf"}, + {file = "aws_cdk.aws_certificatemanager-1.148.0-py3-none-any.whl", hash = "sha256:dfd018cf0c079b3862b79532c07ab91417f34f23eeb806904f7d195968ddc2ce"}, ] "aws-cdk.aws-cloudformation" = [ - {file = "aws-cdk.aws-cloudformation-1.130.0.tar.gz", hash = "sha256:c2176461dfd6bf46ad3143f9ca270e209e74d6a1f8d52e2260f4893b4b9ae228"}, - {file = "aws_cdk.aws_cloudformation-1.130.0-py3-none-any.whl", hash = "sha256:0509fc5b6b6a6bae3752fe04a4b3f24776254e28bc5688238602b904852bd2ec"}, + {file = "aws-cdk.aws-cloudformation-1.148.0.tar.gz", hash = "sha256:f0d6f17eb6831bafda8bbcf106ec700ecf9c48c5b7def4675e4365f410b07581"}, + {file = "aws_cdk.aws_cloudformation-1.148.0-py3-none-any.whl", hash = "sha256:2e0794b8d35b5d0efca4330810bb7882639d80672dc9a6f1531fae80b2997236"}, ] "aws-cdk.aws-cloudwatch" = [ - {file = "aws-cdk.aws-cloudwatch-1.130.0.tar.gz", hash = "sha256:1034ca75148e8292d014927911ba45cb18fad459371988ed32afd4b9de999449"}, - {file = "aws_cdk.aws_cloudwatch-1.130.0-py3-none-any.whl", hash = "sha256:10cbd1b7047267a6a1f566e7f1bfd1e85932a709bbca5419226d1b84b7e0a0ee"}, + {file = "aws-cdk.aws-cloudwatch-1.148.0.tar.gz", hash = "sha256:c185339b527d82066a9948c5c5e4e18a90dba4cae15d78b5e7f5af76de38d2ae"}, + {file = "aws_cdk.aws_cloudwatch-1.148.0-py3-none-any.whl", hash = "sha256:981003c97f7268e8acbc51a792fa2f4fb96c7b4dcff2e33230f389dcdff0e1e7"}, ] "aws-cdk.aws-codeguruprofiler" = [ - {file = "aws-cdk.aws-codeguruprofiler-1.130.0.tar.gz", hash = "sha256:b9d9473a3e052e3164759c3f1ee694b7fc9d604c92b4a3df36c31a1a92306917"}, - {file = "aws_cdk.aws_codeguruprofiler-1.130.0-py3-none-any.whl", hash = "sha256:0462eb79554b407bed707eda3f840956ec81d442ddfad4a1e93da20c89152835"}, + {file = "aws-cdk.aws-codeguruprofiler-1.148.0.tar.gz", hash = "sha256:5959a3d9800ae15299b1532bfd1da9098a2fec4a64fa12324427f2159ca34106"}, + {file = "aws_cdk.aws_codeguruprofiler-1.148.0-py3-none-any.whl", hash = "sha256:22cf0244a5522eba69dcb839a25735630effd128d6cb14a24f841f9cba09f3df"}, ] "aws-cdk.aws-codestarnotifications" = [ - {file = "aws-cdk.aws-codestarnotifications-1.130.0.tar.gz", hash = "sha256:3c7f66d4c377e4f509b2719be4a2b1ac6efdbc4ab416eb56947a57ddd9290e27"}, - {file = "aws_cdk.aws_codestarnotifications-1.130.0-py3-none-any.whl", hash = "sha256:89b8a5374616e732475f374acb1f8b26de20721e0d939dda733f7135754848e3"}, + {file = "aws-cdk.aws-codestarnotifications-1.148.0.tar.gz", hash = "sha256:849f1b5278f8b7d60932ae93b7955966590bd96c534fe33c6a02916daff5624d"}, + {file = "aws_cdk.aws_codestarnotifications-1.148.0-py3-none-any.whl", hash = "sha256:7b4c1a307973a0a495e38814fa3fc2cc56b9ae84b8046791d37527d832ff2ac0"}, ] "aws-cdk.aws-ec2" = [ - {file = "aws-cdk.aws-ec2-1.130.0.tar.gz", hash = "sha256:e0220bc03d44ad4e7f04c8efacd65c52c32faeac3d62a752d114e5606c47a6c2"}, - {file = "aws_cdk.aws_ec2-1.130.0-py3-none-any.whl", hash = "sha256:fde2b2252debcbdd309a74bf7f3c1b7aaa83a671511eb9f753105687e59cafc3"}, + {file = "aws-cdk.aws-ec2-1.148.0.tar.gz", hash = "sha256:92d9b31b6b8797da5f8765a9691d71e8009421a5a380c4afc0318fdd5ebf365f"}, + {file = "aws_cdk.aws_ec2-1.148.0-py3-none-any.whl", hash = "sha256:eb2d7a39d878d2fe72ebbf570503662863e960c5965bd71e9cdf04b2953428c2"}, ] "aws-cdk.aws-ecr" = [ - {file = "aws-cdk.aws-ecr-1.130.0.tar.gz", hash = "sha256:0c3aad603cc3f8e7cf2901d9a1365fe5110ff46f7d739b89333691219b186b92"}, - {file = "aws_cdk.aws_ecr-1.130.0-py3-none-any.whl", hash = "sha256:7a2f8720d2f23c3578979c53f486c66a8449e0fd8135c6e4f82d4bd653151ce9"}, + {file = "aws-cdk.aws-ecr-1.148.0.tar.gz", hash = "sha256:9a9524db3b066a575c7e6a3d48f4487535990ba67cbee18f61c2013accecd84c"}, + {file = "aws_cdk.aws_ecr-1.148.0-py3-none-any.whl", hash = "sha256:d35dbedb1534619060822f91238a534a54c1aba4f37bd74c5b36b094ff97ce44"}, ] "aws-cdk.aws-ecr-assets" = [ - {file = "aws-cdk.aws-ecr-assets-1.130.0.tar.gz", hash = "sha256:40ca779cde59bdc3fcd979385a2b87b8e5cb052e1a4ef76e43bd781458ea5ce3"}, - {file = "aws_cdk.aws_ecr_assets-1.130.0-py3-none-any.whl", hash = "sha256:ddf5078a87529b4e5c2216bb71579fc0489b4dcdab6e7d5246dd1e1d10263e29"}, + {file = "aws-cdk.aws-ecr-assets-1.148.0.tar.gz", hash = "sha256:8f2242dbf91fe7a031bb5c35fd3621eb4770f8797a5b48ec909151ae30d0c691"}, + {file = "aws_cdk.aws_ecr_assets-1.148.0-py3-none-any.whl", hash = "sha256:626cdf326b126ce1bac0e5d11ff41097a029ec0f92212cfac4a118170c2fbec2"}, ] "aws-cdk.aws-efs" = [ - {file = "aws-cdk.aws-efs-1.130.0.tar.gz", hash = "sha256:8ed017fe4599bbfaa03dac74aa41cded39984813c8a6b14e280896aed0c8a39a"}, - {file = "aws_cdk.aws_efs-1.130.0-py3-none-any.whl", hash = "sha256:ccf15abb0711725620d478f7b53e58f2f6109b77f6c47c5878dc00d70e196827"}, + {file = "aws-cdk.aws-efs-1.148.0.tar.gz", hash = "sha256:671fe5fbfeb74165e90bbc14723e8ebb3019a19ac2947931b9b96d8fc3ed34e2"}, + {file = "aws_cdk.aws_efs-1.148.0-py3-none-any.whl", hash = "sha256:b178ef83310427abf4ac2eae36fcce5ac8a5dfaea7e7054f6aea423a32b23112"}, ] "aws-cdk.aws-events" = [ - {file = "aws-cdk.aws-events-1.130.0.tar.gz", hash = "sha256:6ee24457c50eeda8c9c241596cfa6b123bb50ea2138787fef3e4bb54e4b47f13"}, - {file = "aws_cdk.aws_events-1.130.0-py3-none-any.whl", hash = "sha256:df91c72843d9734a49017040090b1615be41de020906a57e6c708d860e8a4139"}, + {file = "aws-cdk.aws-events-1.148.0.tar.gz", hash = "sha256:b5575bccce915c491f3f9f3597b6d2f9bc3c600dd396201212d0ac0bf9567f6b"}, + {file = "aws_cdk.aws_events-1.148.0-py3-none-any.whl", hash = "sha256:60846d46e859b42abc32e0fdacf15854a3e64d203f11551e71e0e690d484f1a8"}, ] "aws-cdk.aws-glue" = [ - {file = "aws-cdk.aws-glue-1.130.0.tar.gz", hash = "sha256:4ddda00ad580ffe207f2241a3cc66ab6c5a225580a9daa6adcd03c3299017d9a"}, - {file = "aws_cdk.aws_glue-1.130.0-py3-none-any.whl", hash = "sha256:93f136d74b866619bd3aec2086b5a2c2b930acfaad7cc23cfa2f0b2a2eb85f90"}, + {file = "aws-cdk.aws-glue-1.148.0.tar.gz", hash = "sha256:018d84ecc8ecc77947ffbf6ae0615538a0249c0cdf16cbca97245e595c787fd0"}, + {file = "aws_cdk.aws_glue-1.148.0-py3-none-any.whl", hash = "sha256:b885bfe9e65f774c987332e1579d63de704b1dc8e7fd1c1b3f26cff05aae2160"}, ] "aws-cdk.aws-iam" = [ - {file = "aws-cdk.aws-iam-1.130.0.tar.gz", hash = "sha256:d2bf02a2d3f2bd81c1b9598e7b4424b0dc0d4694b57338d7efac43a89fb6409c"}, - {file = "aws_cdk.aws_iam-1.130.0-py3-none-any.whl", hash = "sha256:3a3272745da9363177ebd8b138f42ce9407439f909ed9177c226e584022f4ff0"}, + {file = "aws-cdk.aws-iam-1.148.0.tar.gz", hash = "sha256:100535871b86d7a639a9406b7903a538c9d99ffb37459532ec366fa29ca81872"}, + {file = "aws_cdk.aws_iam-1.148.0-py3-none-any.whl", hash = "sha256:15fb4515a8d92dcc5db397c9ff7195ec9545b4bbe76d9f39edaddb9e8d59d70c"}, ] "aws-cdk.aws-kms" = [ - {file = "aws-cdk.aws-kms-1.130.0.tar.gz", hash = "sha256:1ece4b6753b0271d9164b32c0c94919e2f2a587677b19c554c2a990b5b0803b7"}, - {file = "aws_cdk.aws_kms-1.130.0-py3-none-any.whl", hash = "sha256:de50127ab5f5f3838b6e4e549696ccfcd2cf18f7edd50616f82b1a0ddcd10075"}, + {file = "aws-cdk.aws-kms-1.148.0.tar.gz", hash = "sha256:9eeb5e5308a57d2e231527bc0bdde2d7c9f3e4082a5f03a829f84f5031f7b0c5"}, + {file = "aws_cdk.aws_kms-1.148.0-py3-none-any.whl", hash = "sha256:e430666831993b26cd1b28e0aca8656f0f3e738c6d308059d356b4ec0f7fc162"}, ] "aws-cdk.aws-lakeformation" = [ - {file = "aws-cdk.aws-lakeformation-1.130.0.tar.gz", hash = "sha256:bdf37b0047ed48c4fa70c5a9398b596f278a73abf4b912b6eb289fa8aeb96ca7"}, - {file = "aws_cdk.aws_lakeformation-1.130.0-py3-none-any.whl", hash = "sha256:5bcd04992577dc2b67d437e0d73b3367e3b57315859a5c9426f15501db049151"}, + {file = "aws-cdk.aws-lakeformation-1.148.0.tar.gz", hash = "sha256:35793a07cde6c26b6e43ea929563e25802b00159ed7be72bd3fb90d8fa31170c"}, + {file = "aws_cdk.aws_lakeformation-1.148.0-py3-none-any.whl", hash = "sha256:398f7a2887a80120ca5a92c3b7a42041e729dd8caf4150182616336e4f0d27b2"}, ] "aws-cdk.aws-lambda" = [ - {file = "aws-cdk.aws-lambda-1.130.0.tar.gz", hash = "sha256:c3ee7c637f1a590ead83e75803865f58c0c18193ff841d94b0a0b51ea1e9d6fb"}, - {file = "aws_cdk.aws_lambda-1.130.0-py3-none-any.whl", hash = "sha256:6c8dec3aad5d3900888aab52b0a844d3c05e94f977ff04ec26083302cc76edc8"}, + {file = "aws-cdk.aws-lambda-1.148.0.tar.gz", hash = "sha256:160edb2000a273c827c4b17b86bec5333db349b4ee24f3d90c98b5dcf4d5d90f"}, + {file = "aws_cdk.aws_lambda-1.148.0-py3-none-any.whl", hash = "sha256:9f1ac7900fadead264c67ba816e68cb2c923c6636bc5018af46d59cc473e1eec"}, ] "aws-cdk.aws-logs" = [ - {file = "aws-cdk.aws-logs-1.130.0.tar.gz", hash = "sha256:d022ec78f953f1276d710e903ee75857fe86a05b1f44f1610ac4d52b8652ddfc"}, - {file = "aws_cdk.aws_logs-1.130.0-py3-none-any.whl", hash = "sha256:da8ff0e9ed334bb4bc34cac698ad46ae8e815c7e9018e3754c9a342b84f26bbb"}, + {file = "aws-cdk.aws-logs-1.148.0.tar.gz", hash = "sha256:a63966962fbf79bbed974b1385954fa5b1adcf166ce59b07e4bc44dcaed9ca68"}, + {file = "aws_cdk.aws_logs-1.148.0-py3-none-any.whl", hash = "sha256:2c7fe4395c5f875acb7bf93c9120553fe1306f5308084f832170a9c38c26be1d"}, +] +"aws-cdk.aws-neptune" = [ + {file = "aws-cdk.aws-neptune-1.148.0.tar.gz", hash = "sha256:98cb27f33d0821d0b9432b2f807f6d42bf3fcc5b68beaf3b14c2f1cf8f1b2602"}, + {file = "aws_cdk.aws_neptune-1.148.0-py3-none-any.whl", hash = "sha256:81016e389af8aa8baeacaf642cb4fd0620676059989f14bbf39dea921a5ca9f6"}, ] "aws-cdk.aws-opensearchservice" = [ - {file = "aws-cdk.aws-opensearchservice-1.130.0.tar.gz", hash = "sha256:4194f91d28b50a4dc7b97d773871798a79bd93774146cfb8d2fe0ad30030328b"}, - {file = "aws_cdk.aws_opensearchservice-1.130.0-py3-none-any.whl", hash = "sha256:b4bb3b0a80f883aeeae79417ef45c5fc1f46abd05dfa9c46bd02476d5083af39"}, + {file = "aws-cdk.aws-opensearchservice-1.148.0.tar.gz", hash = "sha256:d95aada4dd6c6ac487ed56af0625721f94ff02ff2e227a65f4ea5d2843a8c5a3"}, + {file = "aws_cdk.aws_opensearchservice-1.148.0-py3-none-any.whl", hash = "sha256:4878ba34a85411023fc284cbc205165ac2b9b972dba8129235372c496002897e"}, ] "aws-cdk.aws-rds" = [ - {file = "aws-cdk.aws-rds-1.130.0.tar.gz", hash = "sha256:316abaa5786703bf1459f538d8d1bcc02f5b4c75df320fe2e9d62821f92fa7f4"}, - {file = "aws_cdk.aws_rds-1.130.0-py3-none-any.whl", hash = "sha256:a781ca1b945f655797f06106eb72142be4d1d6b9278e707a29a7e75d7e8dea73"}, + {file = "aws-cdk.aws-rds-1.148.0.tar.gz", hash = "sha256:16c65384cacec36cceeae8bff66b5ac0e0f9dcfda0f6d2f6a751589cef1b855a"}, + {file = "aws_cdk.aws_rds-1.148.0-py3-none-any.whl", hash = "sha256:0ad4a4eb06b43274952edeb4c270fe4965b868962a5cee5441a8800031d25050"}, ] "aws-cdk.aws-redshift" = [ - {file = "aws-cdk.aws-redshift-1.130.0.tar.gz", hash = "sha256:7447af727af2ff2014aad2d04a96ef70ffc6e65142d575dffb762cd147067e06"}, - {file = "aws_cdk.aws_redshift-1.130.0-py3-none-any.whl", hash = "sha256:e60832a9a042eaeeb646769a40753a82b807dc1154df58c20d524010e361c5b0"}, + {file = "aws-cdk.aws-redshift-1.148.0.tar.gz", hash = "sha256:f652fadf4e756e680cb92fd4bbade49c0f3f07d2ea2a5d04d8b29264c72a90ad"}, + {file = "aws_cdk.aws_redshift-1.148.0-py3-none-any.whl", hash = "sha256:7ea7f922bfdeabf162cea76c2f79c9846851605e78c2fd3ad3b2d23e99c041f8"}, ] "aws-cdk.aws-route53" = [ - {file = "aws-cdk.aws-route53-1.130.0.tar.gz", hash = "sha256:6d1a209505e794922718cbf2f8f432f8d51b305da63ad4f10008b8f1f535f526"}, - {file = "aws_cdk.aws_route53-1.130.0-py3-none-any.whl", hash = "sha256:270877be4a1469f84c3022300baba2b982cd1644b4ea01d65fb0522adcf9b822"}, + {file = "aws-cdk.aws-route53-1.148.0.tar.gz", hash = "sha256:335afd7eaa518122027aff0a3842ecbde9e75ff4c0ae5dee57cf6750576e844a"}, + {file = "aws_cdk.aws_route53-1.148.0-py3-none-any.whl", hash = "sha256:e171b3d9df7ec1c1c9893d2ce3124f0aff91728ac018548070c12bffa7e7feaf"}, ] "aws-cdk.aws-s3" = [ - {file = "aws-cdk.aws-s3-1.130.0.tar.gz", hash = "sha256:940bcb081783937e774cf4f44f77ba7a8211ebe9440cca2d7225b310f4272f79"}, - {file = "aws_cdk.aws_s3-1.130.0-py3-none-any.whl", hash = "sha256:9fac2a150adf92700c05a02c603d0ff1185894235443980fafc874354c380f52"}, + {file = "aws-cdk.aws-s3-1.148.0.tar.gz", hash = "sha256:24274f28d2351dbb98319b24cb02e79825202fde0be87d7221ded89048f6add8"}, + {file = "aws_cdk.aws_s3-1.148.0-py3-none-any.whl", hash = "sha256:5d8f1cb8a595af2a352fa5298e5b6644d9db2fd0961c3c5e5b412c7199c2c005"}, ] "aws-cdk.aws-s3-assets" = [ - {file = "aws-cdk.aws-s3-assets-1.130.0.tar.gz", hash = "sha256:db33b348222895ad14cb9d52d5582b1e80d0e9ff008f8c10ea912499ab7c14f1"}, - {file = "aws_cdk.aws_s3_assets-1.130.0-py3-none-any.whl", hash = "sha256:01a5b0f2c759a88176929569c6f69d0efb8901452fe112cfd3b3f4782fec12ab"}, + {file = "aws-cdk.aws-s3-assets-1.148.0.tar.gz", hash = "sha256:2b84b33b4181f4606d8a1a249b51857030d69e1b4fc78abd5c45242b46b5d28a"}, + {file = "aws_cdk.aws_s3_assets-1.148.0-py3-none-any.whl", hash = "sha256:b008adcb99fd016e394573bd00f546b91b8182b6ee7f40e354ecf74762220b51"}, ] "aws-cdk.aws-sam" = [ - {file = "aws-cdk.aws-sam-1.130.0.tar.gz", hash = "sha256:564877af10684b99a76d7ae83b888f9dfc1f7894caed81d5349a059f51430836"}, - {file = "aws_cdk.aws_sam-1.130.0-py3-none-any.whl", hash = "sha256:dbd38e5e52b5f94aff76bc18640e8ba11ae0d0b183867f747942c753935bf326"}, + {file = "aws-cdk.aws-sam-1.148.0.tar.gz", hash = "sha256:3c0ff5c4b5e1c7995a4708313814280fd61e0f2114ca0f08ce151f53525ee202"}, + {file = "aws_cdk.aws_sam-1.148.0-py3-none-any.whl", hash = "sha256:7b3df8068e4ff6797ef73ed27c404c6551347359211e30cbfb6d70d26e7f1852"}, ] "aws-cdk.aws-secretsmanager" = [ - {file = "aws-cdk.aws-secretsmanager-1.130.0.tar.gz", hash = "sha256:96e52bd3e6523b22f1d60aadeb0b6f435a5276a1ec794e4cfe2294f8ac26259a"}, - {file = "aws_cdk.aws_secretsmanager-1.130.0-py3-none-any.whl", hash = "sha256:a929ef9fea760b37d5306a1ee9deeecbac2530ab2ea7ec1fc1085544e6af1ca0"}, + {file = "aws-cdk.aws-secretsmanager-1.148.0.tar.gz", hash = "sha256:7be5554509806a9a2363acd124c7bf9af795a44625c2764fc07c52e24e7e3fb3"}, + {file = "aws_cdk.aws_secretsmanager-1.148.0-py3-none-any.whl", hash = "sha256:9ffbe7093604f4680779b286c1e86a34bf45b41dcf5e70ea8186eb205cb2ab60"}, ] "aws-cdk.aws-signer" = [ - {file = "aws-cdk.aws-signer-1.130.0.tar.gz", hash = "sha256:f453d608a491dd0ff7d97fa597f17480d3bf43a0eaedd975e0846bf03de0ab0d"}, - {file = "aws_cdk.aws_signer-1.130.0-py3-none-any.whl", hash = "sha256:10a5981156c83c8725f565931167b376db24c08d43b325a8ad0e4a10559b32df"}, + {file = "aws-cdk.aws-signer-1.148.0.tar.gz", hash = "sha256:96b3337ff03e8254aeca9e6282217e6be00a82611a974fbe5970e5e5c475d120"}, + {file = "aws_cdk.aws_signer-1.148.0-py3-none-any.whl", hash = "sha256:b12079cf55c7e6a4a7ec4c926bf528ae371701b13544e4d1a123190e3113625a"}, ] "aws-cdk.aws-sns" = [ - {file = "aws-cdk.aws-sns-1.130.0.tar.gz", hash = "sha256:a2494dd42513b870ef94c0f013e734473fb8a02042b21da5864e3b8bd6609963"}, - {file = "aws_cdk.aws_sns-1.130.0-py3-none-any.whl", hash = "sha256:7b6dfc5c50cdc0005caac683731772502a9d26d6ef415256f21746bef0b7b444"}, + {file = "aws-cdk.aws-sns-1.148.0.tar.gz", hash = "sha256:7ad75ed8d6de304e482d93f567cbbc7341a42cc25e4270880323ca0c57f22085"}, + {file = "aws_cdk.aws_sns-1.148.0-py3-none-any.whl", hash = "sha256:996482bc3ddd0199165a7240f6406e595ea9d3af3c6d34ea9118ae376ef101b8"}, ] "aws-cdk.aws-sqs" = [ - {file = "aws-cdk.aws-sqs-1.130.0.tar.gz", hash = "sha256:baef9bfc74c33ad5e9ff65a4d48477f68fb503950d58d21e9cc657e8a9914c0f"}, - {file = "aws_cdk.aws_sqs-1.130.0-py3-none-any.whl", hash = "sha256:bd40f528012fd38398dd7cc6a8c91c62da634e2e620ecfa6530ae43a5d1890b5"}, + {file = "aws-cdk.aws-sqs-1.148.0.tar.gz", hash = "sha256:d60507533610d24cb0a3f9888b2678e169ab8db9c207def50b5acba5e77a9f68"}, + {file = "aws_cdk.aws_sqs-1.148.0-py3-none-any.whl", hash = "sha256:62d8eb222f3928124c7178b6733212f4417a076fe3c778fc649e2ffcc66483cf"}, ] "aws-cdk.aws-ssm" = [ - {file = "aws-cdk.aws-ssm-1.130.0.tar.gz", hash = "sha256:2c0a2e400b82864233e76973020dc16e88afc35aa0ef4dd5250d0404e1236de0"}, - {file = "aws_cdk.aws_ssm-1.130.0-py3-none-any.whl", hash = "sha256:dd84d306f4794433b921f75081d3db41dfe6fdc6078bfa377a096a1457adc9a9"}, + {file = "aws-cdk.aws-ssm-1.148.0.tar.gz", hash = "sha256:e120fcef439e91fb5c15d2f841730acc1e20b4755289a94fae52b12108b5e197"}, + {file = "aws_cdk.aws_ssm-1.148.0-py3-none-any.whl", hash = "sha256:cbddca0c74203b210468ec7b7e9815fd0a9e67767a4f96694ebf2e3a9dc8954a"}, ] "aws-cdk.cloud-assembly-schema" = [ - {file = "aws-cdk.cloud-assembly-schema-1.130.0.tar.gz", hash = "sha256:31231d1fa14037f2af0a0a27657c7e603103c876464868bb8a5731698dba9d7f"}, - {file = "aws_cdk.cloud_assembly_schema-1.130.0-py3-none-any.whl", hash = "sha256:3eadde99a914ca53e101e66a403b554537435a29e1954cb13e94cdc9305da48a"}, + {file = "aws-cdk.cloud-assembly-schema-1.148.0.tar.gz", hash = "sha256:a031a14740209eba20158e3fa19cf154b897005bc3178ae5bffdf54e5ac29c0a"}, + {file = "aws_cdk.cloud_assembly_schema-1.148.0-py3-none-any.whl", hash = "sha256:a13c65c434c4cb9c6da7575f5570122a7c27b665fe0881b9a6c77fcaefb037c8"}, ] "aws-cdk.core" = [ - {file = "aws-cdk.core-1.130.0.tar.gz", hash = "sha256:d07b98dad35b18481e46b92b6fde7061b76730ac9d1111849db321e519ebdc52"}, - {file = "aws_cdk.core-1.130.0-py3-none-any.whl", hash = "sha256:7b3f1d0e9f83263763694cfb814346c38984041226180fe298056670fa5a5bd9"}, + {file = "aws-cdk.core-1.148.0.tar.gz", hash = "sha256:78c80d483ad1319ac532571af697ad184cdcc6352ae9c620f1515e157399d25a"}, + {file = "aws_cdk.core-1.148.0-py3-none-any.whl", hash = "sha256:9e5e73826e6f3d50290b0819d182cdbe095d84fcb54210d9ecd709a9d8c4681d"}, ] "aws-cdk.custom-resources" = [ - {file = "aws-cdk.custom-resources-1.130.0.tar.gz", hash = "sha256:c212447b64f79d3605db6e072d23acc6fa1135e5399162a8cd258bc1d22e03e2"}, - {file = "aws_cdk.custom_resources-1.130.0-py3-none-any.whl", hash = "sha256:07c8a6c99bfe53d251303a7cf50b109fa974ddfd2fdbd22f3e94534271a2f666"}, + {file = "aws-cdk.custom-resources-1.148.0.tar.gz", hash = "sha256:fa533e42bda9ac333f78d009f046a12ba69e7ba8c35f3bf65846e0cb26c6e0e7"}, + {file = "aws_cdk.custom_resources-1.148.0-py3-none-any.whl", hash = "sha256:3d3e609aa57a718dcd1c83bd25f661d717e20d5bb6f5095723b4077ff86645a7"}, ] "aws-cdk.cx-api" = [ - {file = "aws-cdk.cx-api-1.130.0.tar.gz", hash = "sha256:3640cdc3c34566bbd0f32fd899fd5ea969d266d0efcd14f67784e557d2c7192c"}, - {file = "aws_cdk.cx_api-1.130.0-py3-none-any.whl", hash = "sha256:26b425e11e0718f531b6578e0621f141089ec1946ccfa124f929ae932f8340a6"}, + {file = "aws-cdk.cx-api-1.148.0.tar.gz", hash = "sha256:403d4b11d88e1cb79f00028a331cb792e74d3d1b0a47cbc93840732c6d9eaa50"}, + {file = "aws_cdk.cx_api-1.148.0-py3-none-any.whl", hash = "sha256:83d14f3078430d9a455013ab30d3e374bc5f3617fc821dd4a75b775e774c9da8"}, ] "aws-cdk.region-info" = [ - {file = "aws-cdk.region-info-1.130.0.tar.gz", hash = "sha256:f5534c3c02cc25215cca2d74aee4dc70cd34b35d86550415a085db65851b135e"}, - {file = "aws_cdk.region_info-1.130.0-py3-none-any.whl", hash = "sha256:2d4110779dd87f405270bfb31c73f315898698af04ec23b8069cc444d0bd896e"}, + {file = "aws-cdk.region-info-1.148.0.tar.gz", hash = "sha256:bad2c7a9bbf4e7550040dad2c95618e155652b74c0410e471fd3cd0fc3f9f4e3"}, + {file = "aws_cdk.region_info-1.148.0-py3-none-any.whl", hash = "sha256:411f14a98c0a43e63b7dc37cd274acab977b93a8c424fcf2589686fbaa719def"}, ] cattrs = [ {file = "cattrs-1.0.0-py2.py3-none-any.whl", hash = "sha256:616972ae3dfa6e623a40ad3cb845420e64942989152774ab055e5c2b2f89f997"}, {file = "cattrs-1.0.0.tar.gz", hash = "sha256:b7ab5cf8ad127c42eefd01410c1c6e28569a45a255ea80ed968511873c433c7a"}, - {file = "cattrs-1.8.0-py3-none-any.whl", hash = "sha256:901fb2040529ae8fc9d93f48a2cdf7de3e983312ffb2a164ffa4e9847f253af1"}, - {file = "cattrs-1.8.0.tar.gz", hash = "sha256:5c121ab06a7cac494813c228721a7feb5a6423b17316eeaebf13f5a03e5b0d53"}, + {file = "cattrs-1.10.0-py3-none-any.whl", hash = "sha256:35dd9063244263e63bd0bd24ea61e3015b00272cead084b2c40d788b0f857c46"}, + {file = "cattrs-1.10.0.tar.gz", hash = "sha256:211800f725cdecedcbcf4c753bbd22d248312b37d130f06045434acb7d9b34e1"}, ] constructs = [ - {file = "constructs-3.3.161-py3-none-any.whl", hash = "sha256:3215f2a3628584ad8e6a5ebabf4e1cc0b125367f2347e6fa0d9ccfd735ac2bbb"}, - {file = "constructs-3.3.161.tar.gz", hash = "sha256:2b33c412ff0f1d21205d85f778e4594a35c9c98b65cb47fea7533fbe40de1730"}, + {file = "constructs-3.3.239-py3-none-any.whl", hash = "sha256:df09d47f15a7dbd4865c794da5c9e8d4b867f1c3dc7aef5a828f68890525818e"}, + {file = "constructs-3.3.239.tar.gz", hash = "sha256:792ecde6d465c7bca090e41f40b76798358f000c6800b55435d0b51cf8d8e9e4"}, ] importlib-resources = [ {file = "importlib_resources-5.4.0-py3-none-any.whl", hash = "sha256:33a95faed5fc19b4bc16b29a6eeae248a3fe69dd55d4d229d2b480e23eeaad45"}, {file = "importlib_resources-5.4.0.tar.gz", hash = "sha256:d756e2f85dd4de2ba89be0b21dba2a3bbec2e871a42a3a16719258a11f87506b"}, ] jsii = [ - {file = "jsii-1.42.0-py3-none-any.whl", hash = "sha256:29a4c87c8e1ad7eb67b65b03775f37bdd2212088a1eb854e84f5b541b9eaceb4"}, - {file = "jsii-1.42.0.tar.gz", hash = "sha256:44a1874464c3c9b48417523d5a4790ee792dab6e6f522bc6e6e2c84e42417323"}, + {file = "jsii-1.55.0-py3-none-any.whl", hash = "sha256:68a25d3b5fcb21a7bf9b58012ce7eb7e0c00c5654efed9294598a457d19bf9d7"}, + {file = "jsii-1.55.0.tar.gz", hash = "sha256:143188278318eaf74c11cb9c9beca91c3151488f001eae85f358d9b492a56642"}, ] publication = [ {file = "publication-0.0.3-py2.py3-none-any.whl", hash = "sha256:0248885351febc11d8a1098d5c8e3ab2dabcf3e8c0c96db1e17ecd12b53afbe6"}, @@ -951,9 +996,8 @@ six = [ {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, ] typing-extensions = [ - {file = "typing_extensions-3.10.0.2-py2-none-any.whl", hash = "sha256:d8226d10bc02a29bcc81df19a26e56a9647f8b0a6d4a83924139f4a8b01f17b7"}, - {file = "typing_extensions-3.10.0.2-py3-none-any.whl", hash = "sha256:f1d25edafde516b146ecd0613dabcc61409817af4766fbbcfb8d1ad4ec441a34"}, - {file = "typing_extensions-3.10.0.2.tar.gz", hash = "sha256:49f75d16ff11f1cd258e1b988ccff82a3ca5570217d7ad8c5f48205dd99a677e"}, + {file = "typing_extensions-4.1.1-py3-none-any.whl", hash = "sha256:21c85e0fe4b9a155d0799430b0ad741cdce7e359660ccbd8b530613e8df88ce2"}, + {file = "typing_extensions-4.1.1.tar.gz", hash = "sha256:1a9462dcc3347a79b1f1c0271fbe79e844580bb598bafa1ed208b94da3cdcd42"}, ] zipp = [ {file = "zipp-3.6.0-py3-none-any.whl", hash = "sha256:9fe5ea21568a0a70e50f273397638d39b03353731e6cbbb3fd8502a33fec40bc"}, diff --git a/test_infra/pyproject.toml b/test_infra/pyproject.toml index fbff94103..f2bc420e6 100644 --- a/test_infra/pyproject.toml +++ b/test_infra/pyproject.toml @@ -7,16 +7,17 @@ license = "Apache License 2.0" [tool.poetry.dependencies] python = ">=3.6.2, <3.11" -"aws-cdk.core" = "^1.124.0" -"aws-cdk.aws-ec2" = "^1.124.0" -"aws-cdk.aws-glue" = "^1.124.0" -"aws-cdk.aws-iam" = "^1.124.0" -"aws-cdk.aws-kms" = "^1.124.0" -"aws-cdk.aws-logs" = "^1.124.0" -"aws-cdk.aws-s3" = "^1.124.0" -"aws-cdk.aws-redshift" = "^1.124.0" -"aws-cdk.aws-rds" = "^1.124.0" -"aws-cdk.aws-secretsmanager" = "^1.124.0" -"aws-cdk.aws-ssm" = "^1.124.0" -"aws-cdk.aws-opensearchservice" = "^1.124.0" -"aws-cdk.aws-lakeformation" = "^1.124.0" +"aws-cdk.core" = "^1.148.0" +"aws-cdk.aws-ec2" = "^1.148.0" +"aws-cdk.aws-glue" = "^1.148.0" +"aws-cdk.aws-iam" = "^1.148.0" +"aws-cdk.aws-kms" = "^1.148.0" +"aws-cdk.aws-logs" = "^1.148.0" +"aws-cdk.aws-s3" = "^1.148.0" +"aws-cdk.aws-redshift" = "^1.148.0" +"aws-cdk.aws-rds" = "^1.148.0" +"aws-cdk.aws-secretsmanager" = "^1.148.0" +"aws-cdk.aws-ssm" = "^1.148.0" +"aws-cdk.aws-opensearchservice" = "^1.148.0" +"aws-cdk.aws-lakeformation" = "^1.148.0" +"aws-cdk.aws-neptune" = "^1.148.0" diff --git a/test_infra/stacks/databases_stack.py b/test_infra/stacks/databases_stack.py index 0f7c0454d..3b9b53b02 100644 --- a/test_infra/stacks/databases_stack.py +++ b/test_infra/stacks/databases_stack.py @@ -5,6 +5,7 @@ from aws_cdk import aws_iam as iam from aws_cdk import aws_kms as kms from aws_cdk import aws_lakeformation as lf +from aws_cdk import aws_neptune as neptune from aws_cdk import aws_rds as rds from aws_cdk import aws_redshift as redshift from aws_cdk import aws_s3 as s3 @@ -40,6 +41,7 @@ def __init__( self._setup_mysql() self._setup_mysql_serverless() self._setup_sqlserver() + self._setup_neptune() def _set_db_infra(self) -> None: self.db_username = "test" @@ -562,3 +564,18 @@ def _setup_sqlserver(self) -> None: cdk.CfnOutput(self, "SqlServerPort", value=str(port)) cdk.CfnOutput(self, "SqlServerDatabase", value=database) cdk.CfnOutput(self, "SqlServerSchema", value=schema) + + def _setup_neptune(self, iam_enabled: bool = False, port: int = 8182) -> None: + cluster = neptune.DatabaseCluster( + self, + "DataWrangler", + vpc=self.vpc, + instance_type=neptune.InstanceType.R5_LARGE, + iam_authentication=iam_enabled, + security_groups=[self.db_security_group], + ) + + cdk.CfnOutput(self, "NeptuneClusterEndpoint", value=cluster.cluster_endpoint.hostname) + cdk.CfnOutput(self, "NeptuneReaderEndpoint", value=cluster.cluster_read_endpoint.hostname) + cdk.CfnOutput(self, "NeptunePort", value=str(port)) + cdk.CfnOutput(self, "NeptuneIAMEnabled", value=str(iam_enabled)) diff --git a/tests/test_moto.py b/tests/test_moto.py index 600d89f8a..b486347c2 100644 --- a/tests/test_moto.py +++ b/tests/test_moto.py @@ -66,6 +66,7 @@ def moto_dynamodb(): TableName="table", KeySchema=[{"AttributeName": "key", "KeyType": "HASH"}], AttributeDefinitions=[{"AttributeName": "key", "AttributeType": "N"}], + BillingMode="PAY_PER_REQUEST", ) yield dynamodb diff --git a/tests/test_neptune.py b/tests/test_neptune.py new file mode 100644 index 000000000..29af98bb4 --- /dev/null +++ b/tests/test_neptune.py @@ -0,0 +1,383 @@ +import logging +import random +import string +import uuid +from typing import Any, Dict + +import pandas as pd +import pytest # type: ignore +from gremlin_python.process.traversal import Direction, T + +import awswrangler as wr + +from ._utils import extract_cloudformation_outputs + +logging.getLogger("awswrangler").setLevel(logging.DEBUG) + + +@pytest.fixture(scope="session") +def cloudformation_outputs(): + return extract_cloudformation_outputs() + + +@pytest.fixture(scope="session") +def neptune_endpoint(cloudformation_outputs) -> str: + return cloudformation_outputs["NeptuneClusterEndpoint"] + + +@pytest.fixture(scope="session") +def neptune_port(cloudformation_outputs) -> int: + return cloudformation_outputs["NeptunePort"] + + +@pytest.fixture(scope="session") +def neptune_iam_enabled(cloudformation_outputs) -> int: + return cloudformation_outputs["NeptuneIAMEnabled"] + + +def test_connection_neptune_https(neptune_endpoint, neptune_port, neptune_iam_enabled): + client = wr.neptune.connect(host=neptune_endpoint, port=neptune_port, iam_enabled=neptune_iam_enabled) + resp = client.status() + assert resp["status"] == "healthy" + + +def test_connection_neptune_https_iam(neptune_endpoint, neptune_port): + client = wr.neptune.connect(neptune_endpoint, neptune_port, iam_enabled=True) + resp = client.status() + assert resp["status"] == "healthy" + + +def test_opencypher_query(neptune_endpoint, neptune_port) -> Dict[str, Any]: + client = wr.neptune.connect(neptune_endpoint, neptune_port, iam_enabled=False) + wr.neptune.execute_opencypher(client, "create (a:Foo { name: 'foo' })-[:TEST]->(b {name : 'bar'})") + df = wr.neptune.execute_opencypher(client, "MATCH (n) RETURN n LIMIT 1") + assert isinstance(df, pd.DataFrame) + assert df.shape == (1, 1) + + assert isinstance(df, pd.DataFrame) + df = wr.neptune.execute_opencypher(client, "MATCH (n) RETURN n LIMIT 2") + assert df.shape == (2, 1) + + df = wr.neptune.execute_opencypher(client, "MATCH p=(n)-[r]->(d) RETURN p LIMIT 1") + assert isinstance(df, pd.DataFrame) + assert df.shape == (1, 1) + + df = wr.neptune.execute_opencypher(client, "MATCH (n) RETURN id(n), labels(n) LIMIT 1") + assert isinstance(df, pd.DataFrame) + assert df.shape == (1, 2) + row = df.iloc[0] + assert row["id(n)"] + assert row["labels(n)"] + + +def test_flatten_df(neptune_endpoint, neptune_port) -> Dict[str, Any]: + client = wr.neptune.connect(neptune_endpoint, neptune_port, iam_enabled=False) + wr.neptune.execute_opencypher(client, "create (a:Foo1 { name: 'foo' })-[:TEST]->(b {name : 'bar'})") + df = wr.neptune.execute_opencypher(client, "MATCH (n:Foo1) RETURN n LIMIT 1") + df_test = wr.neptune.flatten_nested_df(df) + assert isinstance(df_test, pd.DataFrame) + assert df_test.shape == (1, 6) + row = df_test.iloc[0] + assert row["n_~properties_name"] + + df_test = wr.neptune.flatten_nested_df(df, include_prefix=False) + assert isinstance(df_test, pd.DataFrame) + assert df_test.shape == (1, 6) + row = df_test.iloc[0] + assert row["_~properties_name"] + + df_test = wr.neptune.flatten_nested_df(df, seperator="|") + assert isinstance(df_test, pd.DataFrame) + assert df_test.shape == (1, 6) + row = df_test.iloc[0] + assert row["n|~properties|name"] + + df_new = pd.DataFrame([{"~id": "0", "~labels": ["version"], "~properties": {"type": "version"}}]) + df_test = wr.neptune.flatten_nested_df(df_new) + assert df_test.shape == (1, 4) + row = df_test.iloc[0] + assert row["~properties_type"] + + +def test_opencypher_malformed_query(neptune_endpoint, neptune_port) -> Dict[str, Any]: + client = wr.neptune.connect(neptune_endpoint, neptune_port, iam_enabled=False) + with pytest.raises(wr.exceptions.QueryFailed): + wr.neptune.execute_opencypher(client, "MATCH (n) LIMIT 2") + with pytest.raises(wr.exceptions.QueryFailed): + wr.neptune.execute_opencypher(client, "") + + +def test_gremlin_malformed_query(neptune_endpoint, neptune_port) -> Dict[str, Any]: + client = wr.neptune.connect(neptune_endpoint, neptune_port, iam_enabled=False) + with pytest.raises(wr.exceptions.QueryFailed): + wr.neptune.execute_gremlin(client, "g.V().limit(1") + with pytest.raises(wr.exceptions.QueryFailed): + wr.neptune.execute_gremlin(client, "") + + +def test_sparql_malformed_query(neptune_endpoint, neptune_port) -> Dict[str, Any]: + client = wr.neptune.connect(neptune_endpoint, neptune_port, iam_enabled=False) + with pytest.raises(wr.exceptions.QueryFailed): + wr.neptune.execute_sparql(client, "SELECT ?s ?p ?o {?s ?pLIMIT 1") + with pytest.raises(wr.exceptions.QueryFailed): + wr.neptune.execute_sparql(client, "") + + +def test_gremlin_query_vertices(neptune_endpoint, neptune_port) -> Dict[str, Any]: + client = wr.neptune.connect(neptune_endpoint, neptune_port, iam_enabled=False) + + wr.neptune.execute_gremlin(client, f"g.addV().property(T.id, '{uuid.uuid4()}')") + df = wr.neptune.execute_gremlin(client, "g.V().limit(1)") + assert isinstance(df, pd.DataFrame) + assert df.shape == (1, 2) + + df = wr.neptune.execute_gremlin(client, "g.V().limit(2)") + assert isinstance(df, pd.DataFrame) + assert df.shape == (2, 2) + + +def test_gremlin_query_edges(neptune_endpoint, neptune_port) -> Dict[str, Any]: + client = wr.neptune.connect(neptune_endpoint, neptune_port, iam_enabled=False) + + wr.neptune.execute_gremlin(client, "g.addE('bar').from(addV('foo')).to(addV('foo'))") + df = wr.neptune.execute_gremlin(client, "g.E().limit(1)") + assert isinstance(df, pd.DataFrame) + assert df.shape == (1, 4) + + df = wr.neptune.execute_gremlin(client, "g.E().limit(2)") + assert isinstance(df, pd.DataFrame) + assert df.shape == (2, 4) + + +def test_gremlin_query_no_results(neptune_endpoint, neptune_port) -> Dict[str, Any]: + client = wr.neptune.connect(neptune_endpoint, neptune_port, iam_enabled=False) + + df = wr.neptune.execute_gremlin(client, "g.V('foo').drop()") + assert isinstance(df, pd.DataFrame) + + +def test_sparql_query(neptune_endpoint, neptune_port) -> Dict[str, Any]: + client = wr.neptune.connect(neptune_endpoint, neptune_port, iam_enabled=False) + df = wr.neptune.execute_sparql(client, "INSERT DATA { }") + df = wr.neptune.execute_sparql(client, "INSERT DATA { }") + df = wr.neptune.execute_sparql(client, "SELECT ?s ?p ?o {?s ?p ?o} LIMIT 1") + assert isinstance(df, pd.DataFrame) + assert df.shape == (1, 3) + + df = wr.neptune.execute_sparql(client, "SELECT ?s ?p ?o {?s ?p ?o} LIMIT 2") + assert isinstance(df, pd.DataFrame) + assert df.shape == (2, 3) + + +def test_gremlin_write_updates(neptune_endpoint, neptune_port) -> Dict[str, Any]: + client = wr.neptune.connect(neptune_endpoint, neptune_port, iam_enabled=False) + id = uuid.uuid4() + wr.neptune.execute_gremlin(client, f"g.addV().property(T.id, '{str(id)}')") + + data = [{"~id": id, "age": 50, "name": "foo"}] + df = pd.DataFrame(data) + res = wr.neptune.to_property_graph(client, df) + res = wr.neptune.execute_gremlin(client, f"g.V('{id}').valueMap().with(WithOptions.tokens)") + saved_row = res.iloc[0] + assert saved_row["age"] == 50 + + final_df = wr.neptune.execute_gremlin(client, f"g.V('{str(id)}').values('age')") + assert final_df.iloc[0][0] == 50 + + # check write cardinality + data = [{"~id": id, "age(single)": 55, "name": "bar"}] + df = pd.DataFrame(data) + res = wr.neptune.to_property_graph(client, df, use_header_cardinality=True) + res = wr.neptune.execute_gremlin(client, f"g.V('{id}').valueMap().with(WithOptions.tokens)") + saved_row = res.iloc[0] + assert saved_row["age"] == 55 + assert saved_row["name"] == ["foo", "bar"] + res = wr.neptune.to_property_graph(client, df, use_header_cardinality=False) + res = wr.neptune.execute_gremlin(client, f"g.V('{id}').valueMap().with(WithOptions.tokens)") + saved_row = res.iloc[0] + assert saved_row["age(single)"] == 55 + assert saved_row["name"] == ["foo", "bar"] + + +def test_gremlin_write_vertices(neptune_endpoint, neptune_port) -> Dict[str, Any]: + client = wr.neptune.connect(neptune_endpoint, neptune_port, iam_enabled=False) + wr.neptune.execute_gremlin(client, "g.addV('foo')") + initial_cnt_df = wr.neptune.execute_gremlin(client, "g.V().hasLabel('foo').count()") + data = [_create_dummy_vertex(), _create_dummy_vertex(), _create_dummy_vertex()] + df = pd.DataFrame(data) + res = wr.neptune.to_property_graph(client, df) + assert res + + original_row = df.iloc[0] + res = wr.neptune.execute_gremlin(client, f"g.V('{original_row['~id']}').elementMap()") + saved_row = res.iloc[0] + assert saved_row[T.id] == original_row["~id"] + assert saved_row[T.label] == original_row["~label"] + assert saved_row["int"] == original_row["int"] + assert saved_row["str"] == original_row["str"] + + final_cnt_df = wr.neptune.execute_gremlin(client, "g.V().hasLabel('foo').count()") + assert final_cnt_df.iloc[0][0] == initial_cnt_df.iloc[0][0] + 3 + + # check to make sure batch addition of vertices works + data = [] + for i in range(0, 50): + data.append(_create_dummy_vertex()) + + df = pd.DataFrame(data) + res = wr.neptune.to_property_graph(client, df) + assert res + + batch_cnt_df = wr.neptune.execute_gremlin(client, "g.V().hasLabel('foo').count()") + assert batch_cnt_df.iloc[0][0] == final_cnt_df.iloc[0][0] + 50 + + # check write cardinality + v = _create_dummy_vertex() + v2 = _create_dummy_vertex() + v2["~id"] = v["~id"] + df = pd.DataFrame([v]) + res = wr.neptune.to_property_graph(client, df) + original_row = df.iloc[0] + + # save it a second time to make sure it updates correctly when re-adding + df = pd.DataFrame([v2]) + df.rename(columns={"int": "int(single)"}, inplace=True) + res = wr.neptune.to_property_graph(client, df, use_header_cardinality=True) + res = wr.neptune.execute_gremlin(client, f"g.V('{original_row['~id']}').valueMap().with(WithOptions.tokens)") + saved_row = res.iloc[0] + assert saved_row[T.id] == original_row["~id"] + assert saved_row[T.label] == original_row["~label"] + assert saved_row["int"] == v2["int"] + assert len(saved_row["str"]) == 2 + + # Check that it is respecting the header cardinality + df = pd.DataFrame([v2]) + df.rename(columns={"int": "int(single)"}, inplace=True) + res = wr.neptune.to_property_graph(client, df, use_header_cardinality=True) + res = wr.neptune.execute_gremlin(client, f"g.V('{original_row['~id']}').valueMap().with(WithOptions.tokens)") + saved_row = res.iloc[0] + assert saved_row[T.id] == original_row["~id"] + assert saved_row[T.label] == original_row["~label"] + assert saved_row["int"] == v2["int"] + assert len(saved_row["str"]) == 2 + + +def test_gremlin_write_edges(neptune_endpoint, neptune_port) -> Dict[str, Any]: + client = wr.neptune.connect(neptune_endpoint, neptune_port, iam_enabled=False) + + initial_cnt_df = wr.neptune.execute_gremlin(client, "g.E().hasLabel('bar').count()") + + data = [_create_dummy_edge(), _create_dummy_edge(), _create_dummy_edge()] + df = pd.DataFrame(data) + res = wr.neptune.to_property_graph(client, df) + assert res + + original_row = df.iloc[0] + res = wr.neptune.execute_gremlin(client, f"g.E('{original_row['~id']}').elementMap()") + saved_row = res.iloc[0] + assert saved_row[T.id] == original_row["~id"] + assert saved_row[T.label] == original_row["~label"] + assert saved_row[Direction.IN][T.id] == original_row["~to"] + assert saved_row[Direction.OUT][T.id] == original_row["~from"] + assert saved_row["int"] == original_row["int"] + assert saved_row["str"] == original_row["str"] + + final_cnt_df = wr.neptune.execute_gremlin(client, "g.E().hasLabel('bar').count()") + assert final_cnt_df.iloc[0][0] == initial_cnt_df.iloc[0][0] + 3 + + # check to make sure batch addition of edges works + data = [] + for i in range(0, 50): + data.append(_create_dummy_edge()) + + df = pd.DataFrame(data) + res = wr.neptune.to_property_graph(client, df) + assert res + + batch_cnt_df = wr.neptune.execute_gremlin(client, "g.E().hasLabel('bar').count()") + assert batch_cnt_df.iloc[0][0] == final_cnt_df.iloc[0][0] + 50 + + +def test_sparql_write_triples(neptune_endpoint, neptune_port) -> Dict[str, Any]: + client = wr.neptune.connect(neptune_endpoint, neptune_port, iam_enabled=False) + initial_df = wr.neptune.execute_sparql(client, "SELECT ?p ?o WHERE { ?p ?o .}") + + data = [_create_dummy_triple(), _create_dummy_triple(), _create_dummy_triple()] + df = pd.DataFrame(data) + res = wr.neptune.to_rdf_graph(client, df) + assert res + + final_df = wr.neptune.execute_sparql(client, "SELECT ?p ?o WHERE { ?p ?o .}") + assert len(final_df.index) == len(initial_df.index) + 3 + + # check to make sure batch addition of edges works + data = [] + for i in range(0, 50): + data.append(_create_dummy_triple()) + + df = pd.DataFrame(data) + res = wr.neptune.to_rdf_graph(client, df) + assert res + + batch_df = wr.neptune.execute_sparql(client, "SELECT ?p ?o WHERE { ?p ?o .}") + assert len(batch_df.index) == len(final_df.index) + 50 + + +def test_sparql_write_quads(neptune_endpoint, neptune_port) -> Dict[str, Any]: + client = wr.neptune.connect(neptune_endpoint, neptune_port, iam_enabled=False) + initial_df = wr.neptune.execute_sparql(client, "SELECT ?p ?o FROM WHERE { ?p ?o .}") + + data = [_create_dummy_quad(), _create_dummy_quad(), _create_dummy_quad()] + df = pd.DataFrame(data) + res = wr.neptune.to_rdf_graph(client, df) + assert res + + final_df = wr.neptune.execute_sparql(client, "SELECT ?p ?o FROM WHERE { ?p ?o .}") + assert len(final_df.index) == len(initial_df.index) + 3 + + # check to make sure batch addition of edges works + data = [] + for i in range(0, 50): + data.append(_create_dummy_quad()) + + df = pd.DataFrame(data) + res = wr.neptune.to_rdf_graph(client, df) + assert res + + batch_df = wr.neptune.execute_sparql(client, "SELECT ?p ?o FROM WHERE { ?p ?o .}") + assert len(batch_df.index) == len(final_df.index) + 50 + + +def _create_dummy_vertex() -> Dict[str, Any]: + data = dict() + data["~id"] = str(uuid.uuid4()) + data["~label"] = "foo" + data["int"] = random.randint(0, 1000) + data["str"] = "".join(random.choice(string.ascii_lowercase) for i in range(10)) + data["list"] = [random.randint(0, 1000), random.randint(0, 1000)] + return data + + +def _create_dummy_edge() -> Dict[str, Any]: + data = dict() + data["~id"] = str(uuid.uuid4()) + data["~label"] = "bar" + data["~to"] = str(uuid.uuid4()) + data["~from"] = str(uuid.uuid4()) + data["int"] = random.randint(0, 1000) + data["str"] = "".join(random.choice(string.ascii_lowercase) for i in range(10)) + return data + + +def _create_dummy_triple() -> Dict[str, Any]: + data = dict() + data["s"] = "foo" + data["p"] = str(uuid.uuid4()) + data["o"] = random.randint(0, 1000) + return data + + +def _create_dummy_quad() -> Dict[str, Any]: + data = _create_dummy_triple() + data["g"] = "bar" + return data diff --git a/tests/test_neptune_parsing.py b/tests/test_neptune_parsing.py new file mode 100644 index 000000000..1650ff682 --- /dev/null +++ b/tests/test_neptune_parsing.py @@ -0,0 +1,211 @@ +import logging + +import pandas as pd +import pytest # type: ignore +from gremlin_python.process.traversal import T +from gremlin_python.structure.graph import Edge, Path, Property, Vertex, VertexProperty + +import awswrangler as wr + +logging.getLogger("awswrangler").setLevel(logging.DEBUG) + + +@pytest.fixture(scope="session") +def gremlin_parser() -> wr.neptune.GremlinParser: + c = object.__new__(wr.neptune.GremlinParser) + return c + + +# parse Vertex elements +def test_parse_gremlin_vertex_elements(gremlin_parser): + # parse vertex elements + v = Vertex("foo") + input = [v] + out = gremlin_parser.gremlin_results_to_dict(input) + df = pd.DataFrame.from_records(out) + row = df.iloc[0] + assert df.shape == (1, 2) + assert row["id"] == "foo" + assert row["label"] == "vertex" + + # parse multiple vertex elements + v1 = Vertex("bar") + input = [v, v1] + out = gremlin_parser.gremlin_results_to_dict(input) + df = pd.DataFrame.from_records(out) + row = df.iloc[1] + assert df.shape == (2, 2) + assert row["id"] == "bar" + assert row["label"] == "vertex" + + +# parse Edge elements +def test_parse_gremlin_edge_elements(gremlin_parser): + # parse edge elements + v = Edge("foo", "out1", "label", "in1") + input = [v] + out = gremlin_parser.gremlin_results_to_dict(input) + df = pd.DataFrame.from_records(out) + row = df.iloc[0] + assert df.shape == (1, 4) + assert row["id"] == "foo" + assert row["outV"] == "out1" + assert row["label"] == "label" + assert row["inV"] == "in1" + + # parse multiple edge elements + v1 = Edge("bar", "out1", "label", "in2") + input = [v, v1] + out = gremlin_parser.gremlin_results_to_dict(input) + df = pd.DataFrame.from_records(out) + row = df.iloc[1] + assert df.shape == (2, 4) + assert row["id"] == "bar" + assert row["outV"] == "out1" + assert row["label"] == "label" + assert row["inV"] == "in2" + + +# parse Property elements +def test_parse_gremlin_property_elements(gremlin_parser): + # parse VertexProperty elements + v = VertexProperty("foo", "name", "bar", "v1") + input = [v] + out = gremlin_parser.gremlin_results_to_dict(input) + df = pd.DataFrame.from_records(out) + row = df.iloc[0] + assert df.shape == (1, 5) + assert row["id"] == "foo" + assert row["label"] == "name" + assert row["value"] == "bar" + assert row["key"] == "name" + assert row["vertex"] == "v1" + + v = Property("foo", "name", "bar") + input = [v] + out = gremlin_parser.gremlin_results_to_dict(input) + df = pd.DataFrame.from_records(out) + row = df.iloc[0] + assert df.shape == (1, 3) + assert row["element"] == "bar" + assert row["value"] == "name" + assert row["key"] == "foo" + + +# parse Path elements +def test_parse_gremlin_path_elements(gremlin_parser): + # parse path with elements + v = Vertex("foo") + v2 = Vertex("bar") + e1 = Edge("e1", "foo", "label", "bar") + p = Path(labels=["vertex", "label", "vertex"], objects=[v, e1, v2]) + out = gremlin_parser.gremlin_results_to_dict([p]) + df = pd.DataFrame.from_records(out) + row = df.iloc[0] + assert df.shape == (1, 3) + assert row[0] == {"id": "foo", "label": "vertex"} + assert row[1] == {"id": "e1", "label": "label", "outV": "foo", "inV": "bar"} + assert row[2] == {"id": "bar", "label": "vertex"} + + # parse path with multiple elements + e2 = Edge("bar", "out1", "label", "in2") + v3 = Vertex("in2") + p1 = Path(labels=["vertex", "label", "vertex"], objects=[v2, e2, v3]) + out = gremlin_parser.gremlin_results_to_dict([p, p1]) + df = pd.DataFrame.from_records(out) + row = df.iloc[1] + assert df.shape == (2, 3) + assert row[0] == {"id": "bar", "label": "vertex"} + assert row[1] == {"id": "bar", "label": "label", "outV": "out1", "inV": "in2"} + assert row[2] == {"id": "in2", "label": "vertex"} + + # parse path with maps + p = Path( + labels=["vertex", "label", "vertex"], + objects=[{"name": "foo", "age": 29}, {"dist": 32}, {"name": "bar", "age": 40}], + ) + out = gremlin_parser.gremlin_results_to_dict([p]) + df = pd.DataFrame.from_records(out) + row = df.iloc[0] + assert df.shape == (1, 3) + assert row[0]["name"] == "foo" + assert row[0]["age"] == 29 + assert row[1]["dist"] == 32 + assert row[2]["name"] == "bar" + assert row[2]["age"] == 40 + + # parse path with mixed elements and maps + p = Path( + labels=["vertex", "label", "vertex"], + objects=[{"name": "foo", "age": 29}, Edge("bar", "out1", "label", "in2"), {"name": "bar", "age": 40}], + ) + out = gremlin_parser.gremlin_results_to_dict([p]) + df = pd.DataFrame.from_records(out) + row = df.iloc[0] + assert df.shape == (1, 3) + assert row[0]["name"] == "foo" + assert row[0]["age"] == 29 + assert row[1] == {"id": "bar", "label": "label", "outV": "out1", "inV": "in2"} + assert row[2]["name"] == "bar" + assert row[2]["age"] == 40 + + +# parse vertex valueMap +def test_parse_gremlin_maps(gremlin_parser): + # parse map + m = {"name": "foo", "age": 29} + input = [m] + out = gremlin_parser.gremlin_results_to_dict(input) + df = pd.DataFrame.from_records(out) + row = df.iloc[0] + assert df.shape == (1, 2) + assert row["name"] == "foo" + assert row["age"] == 29 + + # parse multiple maps with T + m1 = {"name": ["foo"], T.id: "2", "age": [40], T.label: "vertex"} + input = [m, m1] + out = gremlin_parser.gremlin_results_to_dict(input) + df = pd.DataFrame.from_records(out) + row = df.iloc[1] + assert df.shape == (2, 4) + assert row["name"] == "foo" + assert row["age"] == 40 + assert row[T.id] == "2" + assert row[T.label] == "vertex" + m2 = {"name": ["foo", "bar"], T.id: "2", T.label: "vertex"} + input = [m, m1, m2] + out = gremlin_parser.gremlin_results_to_dict(input) + df = pd.DataFrame.from_records(out) + row = df.iloc[2] + assert df.shape == (3, 4) + assert row["name"] == ["foo", "bar"] + assert row[T.id] == "2" + assert row[T.label] == "vertex" + + +# parse scalar +def test_parse_gremlin_scalar(gremlin_parser): + # parse map + m = 12 + n = "Foo" + input = [m, n] + out = gremlin_parser.gremlin_results_to_dict(input) + df = pd.DataFrame.from_records(out) + row = df.iloc[0] + assert df.shape == (2, 1) + assert row[0] == 12 + row = df.iloc[1] + assert row[0] == "Foo" + + +# parse subgraph +def test_parse_gremlin_subgraph(gremlin_parser): + m = {"@type": "tinker:graph", "@value": {"vertices": ["v[45]", "v[9]"], "edges": ["e[3990][9-route->45]"]}} + input = [m] + out = gremlin_parser.gremlin_results_to_dict(input) + df = pd.DataFrame.from_records(out) + row = df.iloc[0] + assert df.shape == (1, 2) + assert row["@type"] == "tinker:graph" + assert row["@value"] == {"vertices": ["v[45]", "v[9]"], "edges": ["e[3990][9-route->45]"]} diff --git a/tutorials/033 - Amazon Neptune.ipynb b/tutorials/033 - Amazon Neptune.ipynb new file mode 100644 index 000000000..e5cf3e4c3 --- /dev/null +++ b/tutorials/033 - Amazon Neptune.ipynb @@ -0,0 +1,522 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "b0ee9a28", + "metadata": {}, + "source": [ + "[![AWS Data Wrangler](_static/logo.png \"AWS Data Wrangler\")](https://github.com/awslabs/aws-data-wrangler)" + ] + }, + { + "cell_type": "markdown", + "id": "3a2a7b51", + "metadata": {}, + "source": [ + "# 33 - Amazon Neptune" + ] + }, + { + "cell_type": "markdown", + "id": "42724a76", + "metadata": {}, + "source": [ + "## Initialize\n", + "\n", + "The first step to using AWS Data Wrangler with Amazon Neptune is to import the library and create a client connection.\n", + "\n", + "
Note: Connecting to Amazon Neptune requires that the application you are running has access to the Private VPC where Neptune is located. Without this access you will not be able to connect using AWS Data Wrangler.
" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "fd098b2c", + "metadata": {}, + "outputs": [], + "source": [ + "import awswrangler as wr\n", + "import pandas as pd\n", + "\n", + "url='' # The Neptune Cluster endpoint\n", + "iam_enabled = False # Set to True/False based on the configuration of your cluster\n", + "neptune_port = 8182 # Set to the Neptune Cluster Port, Default is 8182\n", + "client = wr.neptune.connect(url, neptune_port, iam_enabled=iam_enabled)" + ] + }, + { + "cell_type": "markdown", + "id": "1e9499ea", + "metadata": {}, + "source": [ + "## Return the status of the cluster" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "57903cf4", + "metadata": {}, + "outputs": [], + "source": [ + "print(client.status())" + ] + }, + { + "cell_type": "markdown", + "id": "6f13f0cb", + "metadata": {}, + "source": [ + "## Retrieve Data from Neptune using AWS Data Wrangler\n", + "\n", + "AWS Data Wrangler supports querying Amazon Neptune using TinkerPop Gremlin and openCypher for property graph data or SPARQL for RDF data.\n", + "\n", + "### Gremlin" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2801f447", + "metadata": {}, + "outputs": [], + "source": [ + "query = \"g.E().project('source', 'target').by(outV().id()).by(inV().id()).limit(5)\"\n", + "df = wr.neptune.execute_gremlin(client, query)\n", + "display(df.head(5))" + ] + }, + { + "cell_type": "markdown", + "id": "a7666d80", + "metadata": {}, + "source": [ + "### SPARQL" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "91b52363", + "metadata": {}, + "outputs": [], + "source": [ + "query = \"SELECT ?s ?o WHERE { ?s ?p ?o .} LIMIT 5\"\n", + "df = wr.neptune.execute_sparql(client, query)\n", + "display(df.head(5))" + ] + }, + { + "cell_type": "markdown", + "id": "367791b9", + "metadata": {}, + "source": [ + "### openCypher" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ce5df2ee", + "metadata": {}, + "outputs": [], + "source": [ + "query = \"MATCH (n)-[r]->(d) RETURN id(n) as source, id(d) as target LIMIT 5\"\n", + "df = wr.neptune.execute_opencypher(client, query)\n", + "display(df.head(5))" + ] + }, + { + "cell_type": "markdown", + "id": "f91b967c", + "metadata": {}, + "source": [ + "## Saving Data using AWS Data Wrangler\n", + "\n", + "AWS Data Wrangler supports saving Pandas DataFrames into Amazon Neptune using either a property graph or RDF data model. \n", + "\n", + "### Property Graph\n", + "\n", + "If writing to a property graph then DataFrames for vertices and edges must be written separately. DataFrames for vertices must have a `~label` column with the label and a `~id` column for the vertex id.\n", + "\n", + "If the `~id` column does not exist, the specified id does not exists, or is empty then a new vertex will be added.\n", + "\n", + "If no `~label` column exists then writing to the graph will be treated as an update of the element with the specified `~id` value.\n", + "\n", + "DataFrames for edges must have a `~id`, `~label`, `~to`, and `~from` column. If the `~id` column does not exist the specified id does not exists, or is empty then a new edge will be added. If no `~label`, `~to`, or `~from` column exists an exception will be thrown.\n", + "\n", + "#### Add Vertices/Nodes" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "579fd9c0", + "metadata": {}, + "outputs": [], + "source": [ + "import uuid\n", + "import random\n", + "import string\n", + "def _create_dummy_vertex():\n", + " data = dict()\n", + " data[\"~id\"] = uuid.uuid4()\n", + " data[\"~label\"] = \"foo\"\n", + " data[\"int\"] = random.randint(0, 1000)\n", + " data[\"str\"] = \"\".join(random.choice(string.ascii_lowercase) for i in range(10))\n", + " data[\"list\"] = [random.randint(0, 1000), random.randint(0, 1000)]\n", + " return data\n", + "\n", + "data = [_create_dummy_vertex(), _create_dummy_vertex(), _create_dummy_vertex()]\n", + "df = pd.DataFrame(data)\n", + "res = wr.neptune.to_property_graph(client, df)\n", + "query = f\"MATCH (s) WHERE id(s)='{data[0]['~id']}' RETURN s\"\n", + "df = wr.neptune.execute_opencypher(client, query)\n", + "display(df)" + ] + }, + { + "cell_type": "markdown", + "id": "fd5fc8a2", + "metadata": {}, + "source": [ + "#### Add Edges" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "515f7a0f", + "metadata": {}, + "outputs": [], + "source": [ + "import uuid\n", + "import random\n", + "import string\n", + "def _create_dummy_edge():\n", + " data = dict()\n", + " data[\"~id\"] = uuid.uuid4()\n", + " data[\"~label\"] = \"bar\"\n", + " data[\"~to\"] = uuid.uuid4()\n", + " data[\"~from\"] = uuid.uuid4()\n", + " data[\"int\"] = random.randint(0, 1000)\n", + " data[\"str\"] = \"\".join(random.choice(string.ascii_lowercase) for i in range(10))\n", + " return data\n", + "\n", + "data = [_create_dummy_edge(), _create_dummy_edge(), _create_dummy_edge()]\n", + "df = pd.DataFrame(data)\n", + "res = wr.neptune.to_property_graph(client, df)\n", + "query = f\"MATCH (s)-[r]->(d) WHERE id(r)='{data[0]['~id']}' RETURN r\"\n", + "df = wr.neptune.execute_opencypher(client, query)\n", + "display(df)" + ] + }, + { + "cell_type": "markdown", + "id": "efe6eaaf", + "metadata": {}, + "source": [ + "#### Update Existing Nodes" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d831c7a3", + "metadata": {}, + "outputs": [], + "source": [ + "idval=uuid.uuid4()\n", + "wr.neptune.execute_gremlin(client, f\"g.addV().property(T.id, '{str(idval)}')\")\n", + "query = f\"MATCH (s) WHERE id(s)='{idval}' RETURN s\"\n", + "df = wr.neptune.execute_opencypher(client, query)\n", + "print(\"Before\")\n", + "display(df)\n", + "data = [{\"~id\": idval, \"age\": 50}]\n", + "df = pd.DataFrame(data)\n", + "res = wr.neptune.to_property_graph(client, df)\n", + "df = wr.neptune.execute_opencypher(client, query)\n", + "print(\"After\")\n", + "display(df)" + ] + }, + { + "cell_type": "markdown", + "id": "bff6a1fc", + "metadata": {}, + "source": [ + "#### Setting cardinality based on the header\n", + "\n", + " If you would like to save data using `single` cardinality then you can postfix (single) to the column header and\n", + " set `use_header_cardinality=True` (default). e.g. A column named `name(single)` will save the `name` property as single cardinality. You can disable this by setting by setting `use_header_cardinality=False`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1010c2f5", + "metadata": {}, + "outputs": [], + "source": [ + "data = [_create_dummy_vertex()]\n", + "df = pd.DataFrame(data)\n", + "# Adding (single) to the column name in the DataFrame will cause it to write that property as `single` cardinality\n", + "df.rename(columns={\"int\": \"int(single)\"}, inplace=True)\n", + "res = wr.neptune.to_property_graph(client, df, use_header_cardinality=True)\n", + "\n", + "\n", + "# This can be disabled by setting `use_header_cardinality = False`\n", + "df.rename(columns={\"int\": \"int(single)\"}, inplace=True)\n", + "res = wr.neptune.to_property_graph(client, df, use_header_cardinality=False)" + ] + }, + { + "cell_type": "markdown", + "id": "beca9dab", + "metadata": {}, + "source": [ + "### RDF\n", + "\n", + "The DataFrame must consist of triples with column names for the subject, predicate, and object specified. If none are provided than `s`, `p`, and `o` are the default.\n", + "\n", + "If you want to add data into a named graph then you will also need the graph column, default is `g`.\n", + "\n", + "#### Write Triples" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1f8427b9", + "metadata": {}, + "outputs": [], + "source": [ + "def _create_dummy_triple():\n", + " data = dict()\n", + " data[\"s\"] = \"foo\"\n", + " data[\"p\"] = uuid.uuid4()\n", + " data[\"o\"] = random.randint(0, 1000)\n", + " return data\n", + "\n", + "data = [_create_dummy_triple(), _create_dummy_triple(), _create_dummy_triple()]\n", + "df = pd.DataFrame(data)\n", + "res = wr.neptune.to_rdf_graph(client, df)\n", + "query = \"SELECT ?o WHERE { <\" + str(data[0]['p']) + \"> ?o .}\"\n", + "df = wr.neptune.execute_sparql(client, query)\n", + "display(df)" + ] + }, + { + "cell_type": "markdown", + "id": "b7a45c6a", + "metadata": {}, + "source": [ + "#### Write Quads" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "819f6a04", + "metadata": {}, + "outputs": [], + "source": [ + "def _create_dummy_quad():\n", + " data = _create_dummy_triple()\n", + " data[\"g\"] = \"bar\"\n", + " return data\n", + " \n", + "data = [_create_dummy_quad(), _create_dummy_quad(), _create_dummy_quad()]\n", + "df = pd.DataFrame(data)\n", + "res = wr.neptune.to_rdf_graph(client, df)\n", + "query = \"SELECT ?o WHERE { <\" + str(data[0]['p']) + \"> ?o .}\"\n", + "df = wr.neptune.execute_sparql(client, query)\n", + "display(df)" + ] + }, + { + "cell_type": "markdown", + "id": "8370b377", + "metadata": {}, + "source": [ + "## Flatten DataFrames\n", + "\n", + "One of the complexities of working with a row/columns paradigm, such as Pandas, with graph results set is that it is very common for graph results to return complex and nested objects. To help simplify using the results returned from a graph within a more tabular format we have added a method to flatten the returned Pandas DataFrame.\n", + "\n", + "### Flattening the DataFrame" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4488e185", + "metadata": {}, + "outputs": [], + "source": [ + "client = wr.neptune.connect(url, 8182, iam_enabled=False)\n", + "query = \"MATCH (n) RETURN n LIMIT 1\"\n", + "df = wr.neptune.execute_opencypher(client, query)\n", + "print(\"Original\")\n", + "display(df)\n", + "df_new=wr.neptune.flatten_nested_df(df)\n", + "print(\"Flattened\")\n", + "display(df_new)" + ] + }, + { + "cell_type": "markdown", + "id": "9324bff7", + "metadata": {}, + "source": [ + "### Removing the prefixing of the parent column name" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7e95099c", + "metadata": {}, + "outputs": [], + "source": [ + "df_new=wr.neptune.flatten_nested_df(df, include_prefix=False)\n", + "display(df_new)" + ] + }, + { + "cell_type": "markdown", + "id": "21738d39", + "metadata": {}, + "source": [ + "### Specifying the column header seperator" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8f4bcbe3", + "metadata": {}, + "outputs": [], + "source": [ + "df_new=wr.neptune.flatten_nested_df(df, seperator='|')\n", + "display(df_new)" + ] + }, + { + "cell_type": "markdown", + "id": "1bded05b", + "metadata": {}, + "source": [ + "## Putting it into a workflow" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9129f173", + "metadata": {}, + "outputs": [], + "source": [ + "pip install igraph networkx" + ] + }, + { + "cell_type": "markdown", + "id": "cd49d635", + "metadata": {}, + "source": [ + "### Running PageRank using NetworkX" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ecd88fe2", + "metadata": {}, + "outputs": [], + "source": [ + "import networkx as nx\n", + "\n", + "# Retrieve Data from neptune\n", + "client = wr.neptune.connect(url, 8182, iam_enabled=False)\n", + "query = \"MATCH (n)-[r]->(d) RETURN id(n) as source, id(d) as target LIMIT 100\"\n", + "df = wr.neptune.execute_opencypher(client, query)\n", + "\n", + "# Run PageRank\n", + "G=nx.from_pandas_edgelist(df, edge_attr=True)\n", + "pg = nx.pagerank(G)\n", + "\n", + "# Save values back into Neptune\n", + "rows=[]\n", + "for k in pg.keys():\n", + " rows.append({'~id': k, 'pageRank_nx(single)': pg[k]})\n", + "pg_df=pd.DataFrame(rows, columns=['~id','pageRank_nx(single)'])\n", + "res = wr.neptune.to_property_graph(client, pg_df, use_header_cardinality=True)\n", + "\n", + "# Retrieve newly saved data\n", + "query = \"MATCH (n:airport) WHERE n.pageRank_nx IS NOT NULL RETURN n.code, n.pageRank_nx ORDER BY n.pageRank_nx DESC LIMIT 5\"\n", + "df = wr.neptune.execute_opencypher(client, query)\n", + "display(df)" + ] + }, + { + "cell_type": "markdown", + "id": "783a599e", + "metadata": {}, + "source": [ + "### Running PageRank using iGraph" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "abb8c7ab", + "metadata": {}, + "outputs": [], + "source": [ + "import igraph as ig\n", + "\n", + "# Retrieve Data from neptune\n", + "client = wr.neptune.connect(url, 8182, iam_enabled=False)\n", + "query = \"MATCH (n)-[r]->(d) RETURN id(n) as source, id(d) as target LIMIT 100\"\n", + "df = wr.neptune.execute_opencypher(client, query)\n", + "\n", + "# Run PageRank\n", + "g = ig.Graph.TupleList(df.itertuples(index=False), directed=True, weights=False)\n", + "pg = g.pagerank()\n", + "\n", + "# Save values back into Neptune\n", + "rows=[]\n", + "for idx, v in enumerate(g.vs):\n", + " rows.append({'~id': v['name'], 'pageRank_ig(single)': pg[idx]}) \n", + "pg_df=pd.DataFrame(rows, columns=['~id','pageRank_ig(single)'])\n", + "res = wr.neptune.to_property_graph(client, pg_df, use_header_cardinality=True)\n", + "\n", + "# Retrieve newly saved data\n", + "query = \"MATCH (n:airport) WHERE n.pageRank_ig IS NOT NULL RETURN n.code, n.pageRank_ig ORDER BY n.pageRank_ig DESC LIMIT 5\"\n", + "df = wr.neptune.execute_opencypher(client, query)\n", + "display(df)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.7.12" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +}