From a15a4fbf4ece3d7418de3d32c17a07f2c3993e50 Mon Sep 17 00:00:00 2001 From: Bryan Ngo Date: Fri, 2 Dec 2022 14:01:59 -0800 Subject: [PATCH 01/36] basic flowgraph implementation --- src/flowgraph/node.py | 187 +++++++++++++++++++++++++++++++++++++ src/flowgraph/node_test.py | 102 ++++++++++++++++++++ 2 files changed, 289 insertions(+) create mode 100644 src/flowgraph/node.py create mode 100644 src/flowgraph/node_test.py diff --git a/src/flowgraph/node.py b/src/flowgraph/node.py new file mode 100644 index 000000000..a8737c6f1 --- /dev/null +++ b/src/flowgraph/node.py @@ -0,0 +1,187 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# +# Represents a flowgraph in HAMMER that can be run and verified. +# See README.config for more details. +# +# See LICENSE for licence details. + +# pylint: disable=invalid-name + +import json +import queue +from copy import deepcopy +from dataclasses import asdict, dataclass, field +from enum import Enum +from typing import Optional + +import networkx as nx + + +class Status(Enum): + """Represents the status of a node in the flowgraph. + https://tinyurl.com/2bstth7y + """ + NOT_RUN = "NOT_RUN" + RUNNING = "RUNNING" + INCOMPLETE = "INCOMPLETE" + INVALID = "INVALID" + COMPLETE = "COMPLETE" + + +class StatusEncoder(json.JSONEncoder): + def default(self, o: Status) -> str: + if isinstance(o, Status): + return o.name + return super().default(o) + + +def as_status(dct): + if "status" in dct: + dct["status"] = Status[dct["status"]] + return dct + + +# make sure union of required/optional outs is superset of children required/optional inputs +# separate required validity checking and optional validity checking +# meta dict for tech compatibilty +# for cycles, reduce to DAG via cloning of one of the nodes + +@dataclass +class Node: + action: str + tool: str + push_dir: str + pull_dir: str + required_inputs: list[str] + required_outputs: list[str] + children: list + optional_inputs: list[str] = field(default_factory=list) + optional_outputs: list[str] = field(default_factory=list) + status: Status = Status.NOT_RUN + + def __key(self) -> tuple: + """Key value for hashing. + + Returns: + tuple: All fields concatenated. + """ + return ( + self.action, + self.tool, + self.push_dir, + self.pull_dir, + tuple(self.required_inputs), + tuple(self.required_outputs), + tuple(self.children), + tuple(self.optional_inputs), + tuple(self.optional_outputs), + self.status + ) + + def __hash__(self) -> int: + return hash(self.__key) + + def to_json(self) -> dict: + """Writes the node to a JSON string. + + Args: + fname (str): File name to write to. + + Returns: + str: Node represented as a JSON. + """ + return asdict(self) + + +@dataclass +class Graph: + root: Node + + def __post_init__(self) -> None: + self.networkx = self.to_networkx() + + def to_json(self, indent: Optional[int] = None) -> str: + """Writes the graph as a JSON string and saves it to a file. + + Returns: + dict: Entire flowgraph as a JSON. + """ + out_dict = asdict(self.root) + return json.dumps(out_dict, indent=indent, cls=StatusEncoder) + + def to_networkx(self) -> nx.DiGraph: + """Turns our graph into an NetworkX directed graph. + + Returns: + nx.DiGraph: NetworkX directed graph. + """ + q = queue.LifoQueue() + explored = [] + q.put(self.root) + edge_list = {} + while not q.empty(): + v = q.get() + if v not in explored: + explored.append(v) + edge_list[v] = tuple(c for c in v.children) + for c in v.children: + q.put(c) + return nx.DiGraph(edge_list) + + @staticmethod + def from_json(dump: str) -> dict: + """Converts a JSON into an instance of Graph. + + Args: + dump (str): JSON with the correct schema for a Graph. + + Returns: + dict: Dictionary containing graph information. + """ + return json.loads(dump, object_hook=as_status) + + def verify(self) -> bool: + """Checks if a graph is valid via its inputs and outputs. + + Returns: + bool: If graph is valid. + """ + return all(self.__process(v) for v in nx.nodes(self.networkx)) + + def __process(self, v: Node) -> bool: + """Process a specific vertex of a graph. + + Args: + v (Node): Node to check the validity of. + + Returns: + bool: If the particular node is valid. + """ + if v == self.root: + return True + parent_outs = \ + set().union(*(set(p.required_outputs) for p in self.networkx.predecessors(v))) \ + | set().union(*(set(p.optional_outputs) for p in self.networkx.predecessors(v))) + inputs = set(v.required_inputs) | set(v.optional_inputs) + return parent_outs >= inputs + + +def convert_to_acyclic(g: Graph) -> Graph: + """Eliminates cycles in a flowgraph for analysis. + + Args: + g (Graph): (presumably) cyclic graph to transform. + + Returns: + Graph: Graph with cloned nodes. + """ + g_copy = deepcopy(g) + cycles = nx.simple_cycles(g_copy.networkx) + for cycle in cycles: + start, end = cycle[0], cycle[1] + end_copy = deepcopy(end) + end_copy.children = [] + start.children[start.children.index(end)] = end_copy + print(start.children[start.children.index(end_copy)].children) + return Graph(g_copy.root) diff --git a/src/flowgraph/node_test.py b/src/flowgraph/node_test.py new file mode 100644 index 000000000..f9a405744 --- /dev/null +++ b/src/flowgraph/node_test.py @@ -0,0 +1,102 @@ +import logging +import unittest + +import networkx as nx +import node +from node import Graph, Node + + +class NodeTest(unittest.TestCase): + + def test_initialize_node(self) -> None: + """Test that we can instantiate a node.""" + test = Node( + "syn", "nop", "syn_dir", "", + ["bryan-test.yml"], + ["syn-out.json"], + [], + [] + ) + # logging.info(test) + self.assertEqual(test.action, "syn") + + def test_complex_graph(self) -> None: + """Creating a more complex graph.""" + child1 = Node( + "par", "nop", "syn_dir", "par_dir", + ["syn-out.json"], + ["par-out.json"], + [], + [] + ) + root = Node( + "syn", "nop", "syn_dir", "", + ["bryan-test.yml"], + ["syn-out.json"], + [child1], + [] + ) + graph = Graph(root) + # logging.info(nx.nodes(graph.networkx)) + self.assertTrue(graph.verify()) + self.assertEqual(graph.root.children[0], child1) + + def test_to_json(self) -> None: + """Test nodal JSON output.""" + # logging.info(test.to_json()) + child1 = Node( + "par", "nop", "syn_dir", "par_dir", + ["syn-out.json"], + ["par-out.json"], + [], + [] + ) + root = Node( + "syn", "nop", "syn_dir", "", + ["bryan-test.yml"], + ["syn-out.json"], + [child1], + [] + ) + graph = Graph(root) + graph_json = graph.to_json(indent=4) + # logging.info(graph_json) + # logging.info(node.Graph.from_json(graph_json)) + + def test_cycle_reduction(self) -> None: + """Test that cycles are reduced to an acyclic graph.""" + v0 = Node( + "v0", "nop", "v0_dir", "v1_dir", + ["v0-out.json"], + ["v1-out.json"], + [], + [] + ) + v1 = Node( + "v1", "nop", "v1_dir", "v2_dir", + ["v1-out.json"], + ["v2-out.json"], + [], + [] + ) + v2 = Node( + "v2", "nop", "v2_dir", "v0_dir", + ["v2-out.json"], + ["v0-out.json"], + [], + [] + ) + v0.children.append(v1) + v1.children.append(v2) + v2.children.append(v0) + g = Graph(v0) + self.assertTrue(len(nx.find_cycle(g.networkx)) > 0) + g_acyclic = node.convert_to_acyclic(g) + logging.info(g_acyclic.networkx) + with self.assertRaises(nx.NetworkXNoCycle): + nx.find_cycle(g_acyclic.networkx) + + +if __name__ == "__main__": + logging.basicConfig(level=logging.DEBUG) + unittest.main() From 0f1f305637145f8345c3a9ed87a0ff5cb95da771 Mon Sep 17 00:00:00 2001 From: Bryan Ngo Date: Fri, 20 Jan 2023 11:40:05 -0800 Subject: [PATCH 02/36] add visualization test --- src/flowgraph/node_test.py | 68 ++++++++++++++++++++++++++++++++++---- 1 file changed, 62 insertions(+), 6 deletions(-) diff --git a/src/flowgraph/node_test.py b/src/flowgraph/node_test.py index f9a405744..83a831919 100644 --- a/src/flowgraph/node_test.py +++ b/src/flowgraph/node_test.py @@ -1,6 +1,7 @@ import logging import unittest +import matplotlib.pyplot as plt import networkx as nx import node from node import Graph, Node @@ -67,24 +68,21 @@ def test_cycle_reduction(self) -> None: """Test that cycles are reduced to an acyclic graph.""" v0 = Node( "v0", "nop", "v0_dir", "v1_dir", + ["v0-in.json"], ["v0-out.json"], - ["v1-out.json"], [], - [] ) v1 = Node( "v1", "nop", "v1_dir", "v2_dir", + ["v0-out.json"], ["v1-out.json"], - ["v2-out.json"], [], - [] ) v2 = Node( "v2", "nop", "v2_dir", "v0_dir", + ["v1-out.json"], ["v2-out.json"], - ["v0-out.json"], [], - [] ) v0.children.append(v1) v1.children.append(v2) @@ -96,6 +94,64 @@ def test_cycle_reduction(self) -> None: with self.assertRaises(nx.NetworkXNoCycle): nx.find_cycle(g_acyclic.networkx) + def test_visualization(self) -> None: + """Test visualization of flowgraph.""" + v0 = Node( + "syn", "nop", "syn_dir", "par_dir", + ["syn-in.json"], + ["syn-out.json"], + [], + ) + v1 = Node( + "par", "nop", "par_dir", "drc_dir", + ["syn-out.json", "par-in.json", "drc-out.json"], + ["par-out.json"], + [], + ) + v2 = Node( + "drc", "nop", "drc_dir", "par_dir", + ["par-out.json", "drc-in.json"], + ["drc-out.json"], + [], + ) + v0.children.append(v1) + v1.children.append(v2) + v2.children.append(v1) + g = Graph(v0).networkx + g.add_edge(v0.pull_dir, v0.action) + g.add_edge(v0.action, v0.push_dir) + g.add_edge(v1.pull_dir, v1.action) + g.add_edge(v1.action, v1.push_dir) + g.add_edge(v2.pull_dir, v2.action) + g.add_edge(v2.action, v2.push_dir) + pos = nx.planar_layout(g) + blue = "#003262" + yellow = "#fdb515" + nx.draw_networkx_nodes(g, pos=pos, + nodelist=[v0.action, v1.action, v2.action], node_size=1500, node_color=blue, label="Action") + nx.draw_networkx_nodes(g, pos=pos, + nodelist=[ + v0.pull_dir, v0.push_dir, + v1.pull_dir, v1.push_dir, + v2.pull_dir, v2.push_dir + ], node_size=1500, node_color=yellow, label="Push/Pull Directory") + nx.draw_networkx_labels(g, pos=pos, font_size=8, font_color="whitesmoke") + nx.draw_networkx_edges(g, pos=pos, + nodelist=[v0.action, v1.action, v2.action], + node_size=1500, arrowsize=15, connectionstyle="arc3, rad=0.2", edge_color=blue) + nx.draw_networkx_edges(g, pos=pos, + edgelist=[ + (v0.pull_dir, v0.action), + (v0.action, v0.push_dir), + (v1.pull_dir, v1.action), + (v1.action, v1.push_dir), + (v2.pull_dir, v2.action), + (v2.action, v2.push_dir), + ], node_size=1500, arrowsize=15, connectionstyle="arc3, rad=0.2", edge_color=yellow) + plt.axis("off") + plt.legend(loc="upper left", markerscale=0.2) + plt.savefig("/home/bngo/Research/hammer/graph.png", bbox_inches="tight", dpi=200) + if __name__ == "__main__": logging.basicConfig(level=logging.DEBUG) From c513c7ed10b9214e3de53781ed5242e35c70296e Mon Sep 17 00:00:00 2001 From: Bryan Ngo Date: Fri, 20 Jan 2023 11:40:15 -0800 Subject: [PATCH 03/36] refactor --- src/flowgraph/node.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/flowgraph/node.py b/src/flowgraph/node.py index a8737c6f1..0c0482479 100644 --- a/src/flowgraph/node.py +++ b/src/flowgraph/node.py @@ -14,6 +14,7 @@ from dataclasses import asdict, dataclass, field from enum import Enum from typing import Optional +import uuid import networkx as nx @@ -51,14 +52,15 @@ def as_status(dct): class Node: action: str tool: str - push_dir: str pull_dir: str + push_dir: str required_inputs: list[str] required_outputs: list[str] children: list optional_inputs: list[str] = field(default_factory=list) optional_outputs: list[str] = field(default_factory=list) - status: Status = Status.NOT_RUN + status: Status = Status.NOT_RUN + __uuid: uuid.UUID = field(default_factory=uuid.uuid4) def __key(self) -> tuple: """Key value for hashing. @@ -124,7 +126,7 @@ def to_networkx(self) -> nx.DiGraph: v = q.get() if v not in explored: explored.append(v) - edge_list[v] = tuple(c for c in v.children) + edge_list[v.action] = tuple(c.action for c in v.children) for c in v.children: q.put(c) return nx.DiGraph(edge_list) @@ -185,3 +187,6 @@ def convert_to_acyclic(g: Graph) -> Graph: start.children[start.children.index(end)] = end_copy print(start.children[start.children.index(end_copy)].children) return Graph(g_copy.root) + +# TODO: refresh graph +# TODO: unique id for nodes From 5030e1b8a5bc69b099617b38d7badd42061a8d5f Mon Sep 17 00:00:00 2001 From: Bryan Ngo Date: Fri, 27 Jan 2023 02:10:12 -0800 Subject: [PATCH 04/36] pre-branch --- src/flowgraph/node.py | 24 ++++++++++++++++-------- src/flowgraph/node_test.py | 9 +++------ 2 files changed, 19 insertions(+), 14 deletions(-) diff --git a/src/flowgraph/node.py b/src/flowgraph/node.py index 0c0482479..e10c4ebee 100644 --- a/src/flowgraph/node.py +++ b/src/flowgraph/node.py @@ -57,10 +57,10 @@ class Node: required_inputs: list[str] required_outputs: list[str] children: list - optional_inputs: list[str] = field(default_factory=list) - optional_outputs: list[str] = field(default_factory=list) status: Status = Status.NOT_RUN __uuid: uuid.UUID = field(default_factory=uuid.uuid4) + optional_inputs: list[str] = field(default_factory=list) + optional_outputs: list[str] = field(default_factory=list) def __key(self) -> tuple: """Key value for hashing. @@ -126,7 +126,8 @@ def to_networkx(self) -> nx.DiGraph: v = q.get() if v not in explored: explored.append(v) - edge_list[v.action] = tuple(c.action for c in v.children) + # edge_list[v.action] = tuple(c.action for c in v.children) + edge_list[v] = tuple(c for c in v.children) for c in v.children: q.put(c) return nx.DiGraph(edge_list) @@ -179,14 +180,21 @@ def convert_to_acyclic(g: Graph) -> Graph: Graph: Graph with cloned nodes. """ g_copy = deepcopy(g) - cycles = nx.simple_cycles(g_copy.networkx) + cycles = sorted(nx.simple_cycles(g_copy.networkx)) for cycle in cycles: start, end = cycle[0], cycle[1] - end_copy = deepcopy(end) - end_copy.children = [] - start.children[start.children.index(end)] = end_copy - print(start.children[start.children.index(end_copy)].children) + end_copy = Node( + end.action, + end.tool, + end.pull_dir, end.push_dir, + end.required_inputs, end.required_outputs, + end.status, + end.optional_inputs, end.optional_outputs + ) + end.children = [] return Graph(g_copy.root) +# TODO: networkx backend +# TODO: use run_main_args_parsed # TODO: refresh graph # TODO: unique id for nodes diff --git a/src/flowgraph/node_test.py b/src/flowgraph/node_test.py index 83a831919..40bb34ca9 100644 --- a/src/flowgraph/node_test.py +++ b/src/flowgraph/node_test.py @@ -16,7 +16,6 @@ def test_initialize_node(self) -> None: ["bryan-test.yml"], ["syn-out.json"], [], - [] ) # logging.info(test) self.assertEqual(test.action, "syn") @@ -28,14 +27,12 @@ def test_complex_graph(self) -> None: ["syn-out.json"], ["par-out.json"], [], - [] ) root = Node( "syn", "nop", "syn_dir", "", ["bryan-test.yml"], ["syn-out.json"], [child1], - [] ) graph = Graph(root) # logging.info(nx.nodes(graph.networkx)) @@ -50,14 +47,12 @@ def test_to_json(self) -> None: ["syn-out.json"], ["par-out.json"], [], - [] ) root = Node( "syn", "nop", "syn_dir", "", ["bryan-test.yml"], ["syn-out.json"], [child1], - [] ) graph = Graph(root) graph_json = graph.to_json(indent=4) @@ -87,10 +82,12 @@ def test_cycle_reduction(self) -> None: v0.children.append(v1) v1.children.append(v2) v2.children.append(v0) + g = Graph(v0) self.assertTrue(len(nx.find_cycle(g.networkx)) > 0) + g_acyclic = node.convert_to_acyclic(g) - logging.info(g_acyclic.networkx) + print(g_acyclic) with self.assertRaises(nx.NetworkXNoCycle): nx.find_cycle(g_acyclic.networkx) From 93eeac3740db958b690f0aa094dadbd7386d09b8 Mon Sep 17 00:00:00 2001 From: Bryan Ngo Date: Fri, 27 Jan 2023 02:53:52 -0800 Subject: [PATCH 05/36] new backend --- src/flowgraph/node.py | 82 ++++++++------------------------------ src/flowgraph/node_test.py | 58 ++++++--------------------- 2 files changed, 30 insertions(+), 110 deletions(-) diff --git a/src/flowgraph/node.py b/src/flowgraph/node.py index e10c4ebee..396f5b4fa 100644 --- a/src/flowgraph/node.py +++ b/src/flowgraph/node.py @@ -9,11 +9,8 @@ # pylint: disable=invalid-name import json -import queue -from copy import deepcopy from dataclasses import asdict, dataclass, field from enum import Enum -from typing import Optional import uuid import networkx as nx @@ -56,7 +53,6 @@ class Node: push_dir: str required_inputs: list[str] required_outputs: list[str] - children: list status: Status = Status.NOT_RUN __uuid: uuid.UUID = field(default_factory=uuid.uuid4) optional_inputs: list[str] = field(default_factory=list) @@ -75,7 +71,6 @@ def __key(self) -> tuple: self.pull_dir, tuple(self.required_inputs), tuple(self.required_outputs), - tuple(self.children), tuple(self.optional_inputs), tuple(self.optional_outputs), self.status @@ -98,51 +93,10 @@ def to_json(self) -> dict: @dataclass class Graph: - root: Node + edge_list: dict[Node, list[Node]] def __post_init__(self) -> None: - self.networkx = self.to_networkx() - - def to_json(self, indent: Optional[int] = None) -> str: - """Writes the graph as a JSON string and saves it to a file. - - Returns: - dict: Entire flowgraph as a JSON. - """ - out_dict = asdict(self.root) - return json.dumps(out_dict, indent=indent, cls=StatusEncoder) - - def to_networkx(self) -> nx.DiGraph: - """Turns our graph into an NetworkX directed graph. - - Returns: - nx.DiGraph: NetworkX directed graph. - """ - q = queue.LifoQueue() - explored = [] - q.put(self.root) - edge_list = {} - while not q.empty(): - v = q.get() - if v not in explored: - explored.append(v) - # edge_list[v.action] = tuple(c.action for c in v.children) - edge_list[v] = tuple(c for c in v.children) - for c in v.children: - q.put(c) - return nx.DiGraph(edge_list) - - @staticmethod - def from_json(dump: str) -> dict: - """Converts a JSON into an instance of Graph. - - Args: - dump (str): JSON with the correct schema for a Graph. - - Returns: - dict: Dictionary containing graph information. - """ - return json.loads(dump, object_hook=as_status) + self.networkx = nx.DiGraph(self.edge_list) def verify(self) -> bool: """Checks if a graph is valid via its inputs and outputs. @@ -161,13 +115,11 @@ def __process(self, v: Node) -> bool: Returns: bool: If the particular node is valid. """ - if v == self.root: - return True parent_outs = \ set().union(*(set(p.required_outputs) for p in self.networkx.predecessors(v))) \ | set().union(*(set(p.optional_outputs) for p in self.networkx.predecessors(v))) inputs = set(v.required_inputs) | set(v.optional_inputs) - return parent_outs >= inputs + return self.networkx.in_degree(v) == 0 or parent_outs >= inputs def convert_to_acyclic(g: Graph) -> Graph: @@ -179,22 +131,22 @@ def convert_to_acyclic(g: Graph) -> Graph: Returns: Graph: Graph with cloned nodes. """ - g_copy = deepcopy(g) - cycles = sorted(nx.simple_cycles(g_copy.networkx)) + cycles = sorted(nx.simple_cycles(g.networkx)) + new_edge_list = g.edge_list.copy() for cycle in cycles: - start, end = cycle[0], cycle[1] - end_copy = Node( - end.action, - end.tool, - end.pull_dir, end.push_dir, - end.required_inputs, end.required_outputs, - end.status, - end.optional_inputs, end.optional_outputs + cut_start, cut_end = cycle[0], cycle[1] + cut_end_copy = Node( + cut_end.action, + cut_end.tool, + cut_end.pull_dir, cut_end.push_dir, + cut_end.required_inputs, cut_end.required_outputs, + cut_end.status, + cut_end.optional_inputs, cut_end.optional_outputs ) - end.children = [] - return Graph(g_copy.root) + cut_start_children = new_edge_list[cut_start] + new_edge_list[cut_start] = [] + new_edge_list[cut_end_copy] = cut_start_children + return Graph(new_edge_list) -# TODO: networkx backend # TODO: use run_main_args_parsed # TODO: refresh graph -# TODO: unique id for nodes diff --git a/src/flowgraph/node_test.py b/src/flowgraph/node_test.py index 40bb34ca9..7cb26ad62 100644 --- a/src/flowgraph/node_test.py +++ b/src/flowgraph/node_test.py @@ -1,7 +1,6 @@ import logging import unittest -import matplotlib.pyplot as plt import networkx as nx import node from node import Graph, Node @@ -15,49 +14,24 @@ def test_initialize_node(self) -> None: "syn", "nop", "syn_dir", "", ["bryan-test.yml"], ["syn-out.json"], - [], ) # logging.info(test) self.assertEqual(test.action, "syn") def test_complex_graph(self) -> None: """Creating a more complex graph.""" - child1 = Node( - "par", "nop", "syn_dir", "par_dir", - ["syn-out.json"], - ["par-out.json"], - [], - ) root = Node( "syn", "nop", "syn_dir", "", ["bryan-test.yml"], ["syn-out.json"], - [child1], ) - graph = Graph(root) - # logging.info(nx.nodes(graph.networkx)) - self.assertTrue(graph.verify()) - self.assertEqual(graph.root.children[0], child1) - - def test_to_json(self) -> None: - """Test nodal JSON output.""" - # logging.info(test.to_json()) child1 = Node( "par", "nop", "syn_dir", "par_dir", ["syn-out.json"], ["par-out.json"], - [], ) - root = Node( - "syn", "nop", "syn_dir", "", - ["bryan-test.yml"], - ["syn-out.json"], - [child1], - ) - graph = Graph(root) - graph_json = graph.to_json(indent=4) - # logging.info(graph_json) - # logging.info(node.Graph.from_json(graph_json)) + graph = Graph({root: [child1]}) + self.assertTrue(graph.verify()) def test_cycle_reduction(self) -> None: """Test that cycles are reduced to an acyclic graph.""" @@ -65,56 +39,50 @@ def test_cycle_reduction(self) -> None: "v0", "nop", "v0_dir", "v1_dir", ["v0-in.json"], ["v0-out.json"], - [], ) v1 = Node( "v1", "nop", "v1_dir", "v2_dir", ["v0-out.json"], ["v1-out.json"], - [], ) v2 = Node( "v2", "nop", "v2_dir", "v0_dir", ["v1-out.json"], ["v2-out.json"], - [], ) - v0.children.append(v1) - v1.children.append(v2) - v2.children.append(v0) - - g = Graph(v0) + g = Graph({ + v0: [v1], + v1: [v2], + v2: [v0], + }) self.assertTrue(len(nx.find_cycle(g.networkx)) > 0) - g_acyclic = node.convert_to_acyclic(g) - print(g_acyclic) with self.assertRaises(nx.NetworkXNoCycle): nx.find_cycle(g_acyclic.networkx) def test_visualization(self) -> None: """Test visualization of flowgraph.""" + import matplotlib.pyplot as plt v0 = Node( "syn", "nop", "syn_dir", "par_dir", ["syn-in.json"], ["syn-out.json"], - [], ) v1 = Node( "par", "nop", "par_dir", "drc_dir", ["syn-out.json", "par-in.json", "drc-out.json"], ["par-out.json"], - [], ) v2 = Node( "drc", "nop", "drc_dir", "par_dir", ["par-out.json", "drc-in.json"], ["drc-out.json"], - [], ) - v0.children.append(v1) - v1.children.append(v2) - v2.children.append(v1) - g = Graph(v0).networkx + g = Graph({ + v0.action: [v1.action], + v1.action: [v2.action], + v2.action: [] + }).networkx g.add_edge(v0.pull_dir, v0.action) g.add_edge(v0.action, v0.push_dir) g.add_edge(v1.pull_dir, v1.action) From b49bf0bea6cb3e63d62f4878495ffaf5bab18ae3 Mon Sep 17 00:00:00 2001 From: Bryan Ngo Date: Fri, 27 Jan 2023 03:10:07 -0800 Subject: [PATCH 06/36] rebase master with pypi packaging --- {src => hammer}/flowgraph/node.py | 0 src/flowgraph/node_test.py => tests/test_node.py | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename {src => hammer}/flowgraph/node.py (100%) rename src/flowgraph/node_test.py => tests/test_node.py (100%) diff --git a/src/flowgraph/node.py b/hammer/flowgraph/node.py similarity index 100% rename from src/flowgraph/node.py rename to hammer/flowgraph/node.py diff --git a/src/flowgraph/node_test.py b/tests/test_node.py similarity index 100% rename from src/flowgraph/node_test.py rename to tests/test_node.py From f8fc5c59d3c0078db7e74d33cdbfd6ff34331f6a Mon Sep 17 00:00:00 2001 From: Bryan Ngo Date: Mon, 30 Jan 2023 10:49:39 -0800 Subject: [PATCH 07/36] preliminary run graph algo --- hammer/flowgraph/node.py | 52 +++++++++++++++++++++++++++++++++++++--- poetry.lock | 21 +++++++++++++++- pyproject.toml | 1 + tests/test_node.py | 4 ++-- 4 files changed, 72 insertions(+), 6 deletions(-) diff --git a/hammer/flowgraph/node.py b/hammer/flowgraph/node.py index 396f5b4fa..bb19a6eaf 100644 --- a/hammer/flowgraph/node.py +++ b/hammer/flowgraph/node.py @@ -9,12 +9,15 @@ # pylint: disable=invalid-name import json +import os +import uuid from dataclasses import asdict, dataclass, field from enum import Enum -import uuid import networkx as nx +from hammer.vlsi import cli_driver + class Status(Enum): """Represents the status of a node in the flowgraph. @@ -104,7 +107,7 @@ def verify(self) -> bool: Returns: bool: If graph is valid. """ - return all(self.__process(v) for v in nx.nodes(self.networkx)) + return all(self.__process(v) for v in convert_to_acyclic(self).networkx) def __process(self, v: Node) -> bool: """Process a specific vertex of a graph. @@ -121,6 +124,50 @@ def __process(self, v: Node) -> bool: inputs = set(v.required_inputs) | set(v.optional_inputs) return self.networkx.in_degree(v) == 0 or parent_outs >= inputs + def run(self, start: Node) -> None: + """Run a HAMMER flowgraph.""" + if not self.verify(): + raise RuntimeError("Flowgraph is invalid") + if start not in self.networkx: + raise RuntimeError("Node not in flowgraph") + + start.status = Status.RUNNING + arg_list = { + "action": start.action, + 'environment_config': None, + 'configs': [os.path.join(start.pull_dir, i) for i in start.required_inputs], + 'log': None, + 'obj_dir': start.push_dir, + 'syn_rundir': '', + 'par_rundir': '', + 'drc_rundir': '', + 'lvs_rundir': '', + 'sim_rundir': '', + 'power_rundir': '', + 'formal_rundir': '', + 'timing_rundir': '', + # TODO: sub-step determinations + 'from_step': None, + 'after_step': None, + 'to_step': None, + 'until_step': None, + 'only_step': None, + 'output': 'output.json', + 'verilog': None, + 'firrtl': None, + 'top': None, + 'cad_files': None + } + + driver = cli_driver.CLIDriver() + try: + driver.run_main_parsed(arg_list) + start.status = Status.COMPLETE + for c in nx.neighbors(self.networkx, start): + self.run(c) + except Exception as e: + start.status = Status.INCOMPLETE + raise e def convert_to_acyclic(g: Graph) -> Graph: """Eliminates cycles in a flowgraph for analysis. @@ -148,5 +195,4 @@ def convert_to_acyclic(g: Graph) -> Graph: new_edge_list[cut_end_copy] = cut_start_children return Graph(new_edge_list) -# TODO: use run_main_args_parsed # TODO: refresh graph diff --git a/poetry.lock b/poetry.lock index 7ca376e95..9ebff9f13 100644 --- a/poetry.lock +++ b/poetry.lock @@ -666,6 +666,25 @@ linkify = ["linkify-it-py (>=1.0,<2.0)"] rtd = ["ipython", "sphinx-book-theme", "sphinx-design", "sphinxcontrib.mermaid (>=0.7.1,<0.8.0)", "sphinxext-opengraph (>=0.6.3,<0.7.0)", "sphinxext-rediraffe (>=0.2.7,<0.3.0)"] testing = ["beautifulsoup4", "coverage[toml]", "pytest (>=6,<7)", "pytest-cov", "pytest-param-files (>=0.3.4,<0.4.0)", "pytest-regressions", "sphinx (<5.2)", "sphinx-pytest"] +[[package]] +name = "networkx" +version = "3.0" +description = "Python package for creating and manipulating graphs and networks" +category = "main" +optional = false +python-versions = ">=3.8" +files = [ + {file = "networkx-3.0-py3-none-any.whl", hash = "sha256:58058d66b1818043527244fab9d41a51fcd7dcc271748015f3c181b8a90c8e2e"}, + {file = "networkx-3.0.tar.gz", hash = "sha256:9a9992345353618ae98339c2b63d8201c381c2944f38a2ab49cb45a4c667e412"}, +] + +[package.extras] +default = ["matplotlib (>=3.4)", "numpy (>=1.20)", "pandas (>=1.3)", "scipy (>=1.8)"] +developer = ["mypy (>=0.991)", "pre-commit (>=2.20)"] +doc = ["nb2plots (>=0.6)", "numpydoc (>=1.5)", "pillow (>=9.2)", "pydata-sphinx-theme (>=0.11)", "sphinx (==5.2.3)", "sphinx-gallery (>=0.11)", "texext (>=0.6.7)"] +extra = ["lxml (>=4.6)", "pydot (>=1.4.2)", "pygraphviz (>=1.10)", "sympy (>=1.10)"] +test = ["codecov (>=2.1)", "pytest (>=7.2)", "pytest-cov (>=4.0)"] + [[package]] name = "numpy" version = "1.24.1" @@ -1412,4 +1431,4 @@ asap7-gdstk = ["gdstk"] [metadata] lock-version = "2.0" python-versions = "^3.9" -content-hash = "010b3a88ee8645e703e98c359f877f1b24bb2accc6082e9ade79bcc57a808056" +content-hash = "67c4116b3ad38c850c787570708e14362df542402503fa53b6414f7aaa598644" diff --git a/pyproject.toml b/pyproject.toml index df9aac953..b630cebed 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -24,6 +24,7 @@ python = "^3.9" pydantic = "^1.9.2" PyYAML = "^6.0" "ruamel.yaml" = "^0.17.21" +networkx = "^3.0" numpy = "^1.23.0" gdstk = { version = "^0.9.0", optional = true } diff --git a/tests/test_node.py b/tests/test_node.py index 7cb26ad62..5fd463eac 100644 --- a/tests/test_node.py +++ b/tests/test_node.py @@ -2,8 +2,8 @@ import unittest import networkx as nx -import node -from node import Graph, Node +from hammer.flowgraph import node +from hammer.flowgraph.node import Graph, Node class NodeTest(unittest.TestCase): From 05a4043614078fdc2cf1d1ff3ee09a92f4ffa2a0 Mon Sep 17 00:00:00 2001 From: Bryan Ngo Date: Tue, 31 Jan 2023 18:19:57 -0800 Subject: [PATCH 08/36] implementing graph running --- hammer/flowgraph/node.py | 33 +++------------- tests/test_node.py | 84 +++++++++++++++++++++++++++++++++++++++- 2 files changed, 88 insertions(+), 29 deletions(-) diff --git a/hammer/flowgraph/node.py b/hammer/flowgraph/node.py index bb19a6eaf..9b7299b90 100644 --- a/hammer/flowgraph/node.py +++ b/hammer/flowgraph/node.py @@ -8,14 +8,14 @@ # pylint: disable=invalid-name -import json import os import uuid -from dataclasses import asdict, dataclass, field +from dataclasses import dataclass, field from enum import Enum import networkx as nx +from hammer.logging import HammerVLSILogging from hammer.vlsi import cli_driver @@ -30,19 +30,6 @@ class Status(Enum): COMPLETE = "COMPLETE" -class StatusEncoder(json.JSONEncoder): - def default(self, o: Status) -> str: - if isinstance(o, Status): - return o.name - return super().default(o) - - -def as_status(dct): - if "status" in dct: - dct["status"] = Status[dct["status"]] - return dct - - # make sure union of required/optional outs is superset of children required/optional inputs # separate required validity checking and optional validity checking # meta dict for tech compatibilty @@ -82,18 +69,6 @@ def __key(self) -> tuple: def __hash__(self) -> int: return hash(self.__key) - def to_json(self) -> dict: - """Writes the node to a JSON string. - - Args: - fname (str): File name to write to. - - Returns: - str: Node represented as a JSON. - """ - return asdict(self) - - @dataclass class Graph: edge_list: dict[Node, list[Node]] @@ -132,6 +107,8 @@ def run(self, start: Node) -> None: raise RuntimeError("Node not in flowgraph") start.status = Status.RUNNING + ctxt = HammerVLSILogging.context() + ctxt.info(f"Running graph step {start.action}") arg_list = { "action": start.action, 'environment_config': None, @@ -152,7 +129,7 @@ def run(self, start: Node) -> None: 'to_step': None, 'until_step': None, 'only_step': None, - 'output': 'output.json', + 'output': os.path.join(start.push_dir, start.required_outputs[0]), 'verilog': None, 'firrtl': None, 'top': None, diff --git a/tests/test_node.py b/tests/test_node.py index 5fd463eac..8acb3f98a 100644 --- a/tests/test_node.py +++ b/tests/test_node.py @@ -1,7 +1,12 @@ import logging +import os +import tempfile import unittest import networkx as nx +import pytest +from networkx.readwrite import json_graph + from hammer.flowgraph import node from hammer.flowgraph.node import Graph, Node @@ -15,7 +20,6 @@ def test_initialize_node(self) -> None: ["bryan-test.yml"], ["syn-out.json"], ) - # logging.info(test) self.assertEqual(test.action, "syn") def test_complex_graph(self) -> None: @@ -32,6 +36,8 @@ def test_complex_graph(self) -> None: ) graph = Graph({root: [child1]}) self.assertTrue(graph.verify()) + self.assertEqual(len(graph.networkx), 2) + self.assertEqual(graph.networkx.number_of_edges(), 1) def test_cycle_reduction(self) -> None: """Test that cycles are reduced to an acyclic graph.""" @@ -59,7 +65,10 @@ def test_cycle_reduction(self) -> None: g_acyclic = node.convert_to_acyclic(g) with self.assertRaises(nx.NetworkXNoCycle): nx.find_cycle(g_acyclic.networkx) + self.assertEqual(len(g_acyclic.networkx), 4) + self.assertEqual(g.networkx.number_of_edges(), 3) + @pytest.mark.xfail(raises=ImportError, reason="Matplotlib currently not imported") def test_visualization(self) -> None: """Test visualization of flowgraph.""" import matplotlib.pyplot as plt @@ -117,6 +126,79 @@ def test_visualization(self) -> None: plt.legend(loc="upper left", markerscale=0.2) plt.savefig("/home/bngo/Research/hammer/graph.png", bbox_inches="tight", dpi=200) + def test_run_basic(self) -> None: + """Test a basic syn -> par -> drc flow, all with nop tools.""" + with tempfile.TemporaryDirectory() as td: + os.mkdir(os.path.join(td, "syn_dir")) + os.mkdir(os.path.join(td, "par_dir")) + os.mkdir(os.path.join(td, "drc_dir")) + + with open(os.path.join(td, "syn_dir", "syn-in.yml"), 'w', encoding="utf-8") as tf1: + tf1.write(""" +synthesis.inputs: + input_files: ["LICENSE", "README.md"] + top_module: "z1top.xdc" + +par.inputs: + input_files: ["LICENSE", "README.md"] + top_module: "z1top.xdc" + +drc.inputs: + input_files: ["LICENSE", "README.md"] + top_module: "z1top.xdc" + +lvs.inputs: + input_files: ["LICENSE", "README.md"] + schematic_files: ["LICENSE", "README.md"] + top_module: "z1top.xdc" + hcells_list: [] + +pcb.inputs: + top_module: "z1top.xdc" + +formal.inputs: + input_files: ["LICENSE", "README.md"] + top_module: "z1top.xdc" + +sim.inputs: + input_files: ["LICENSE", "README.md"] + top_module: "z1top.xdc" + +vlsi: + core: + technology: "hammer.technology.nop" + + synthesis_tool: "hammer.synthesis.nop" + par_tool: "hammer.par.nop" + drc_tool: "hammer.drc.nop" + lvs_tool: "hammer.lvs.nop" + power_tool: "hammer.power.nop" + sim_tool: "mocksim" +""") + + v0 = Node( + "syn-to-par", "nop", os.path.join(td, "syn_dir"), os.path.join(td, "par_dir"), + ["syn-in.yml"], + ["syn-out.json"], + ) + v1 = Node( + "par-to-drc", "nop", os.path.join(td, "par_dir"), os.path.join(td, "drc_dir"), + ["syn-out.json"], + ["par-out.json"], + ) + v2 = Node( + "drc", "nop", os.path.join(td, "drc_dir"), os.path.join(td, "out_dir"), + ["par-out.json"], + ["drc-out.json"], + ) + g = Graph({ + v0: [v1], + v1: [v2], + v2: [] + }) + g.run(v0) + + if __name__ == "__main__": logging.basicConfig(level=logging.DEBUG) From e51170e64fd89d8caf688270bda901d8677955ed Mon Sep 17 00:00:00 2001 From: Bryan Ngo Date: Thu, 2 Feb 2023 18:02:15 -0800 Subject: [PATCH 09/36] passing basic run test --- hammer/flowgraph/node.py | 6 +++--- tests/test_node.py | 40 +++++++++++++++++++++++----------------- 2 files changed, 26 insertions(+), 20 deletions(-) diff --git a/hammer/flowgraph/node.py b/hammer/flowgraph/node.py index 9b7299b90..c2ddb1bfe 100644 --- a/hammer/flowgraph/node.py +++ b/hammer/flowgraph/node.py @@ -107,8 +107,6 @@ def run(self, start: Node) -> None: raise RuntimeError("Node not in flowgraph") start.status = Status.RUNNING - ctxt = HammerVLSILogging.context() - ctxt.info(f"Running graph step {start.action}") arg_list = { "action": start.action, 'environment_config': None, @@ -129,7 +127,7 @@ def run(self, start: Node) -> None: 'to_step': None, 'until_step': None, 'only_step': None, - 'output': os.path.join(start.push_dir, start.required_outputs[0]), + 'output': os.path.join(start.push_dir, start.required_outputs[0]), # TODO: fix this 'verilog': None, 'firrtl': None, 'top': None, @@ -138,6 +136,8 @@ def run(self, start: Node) -> None: driver = cli_driver.CLIDriver() try: + ctxt = HammerVLSILogging.context(start.action) + # ctxt.info(f"Running graph step {start.action}") driver.run_main_parsed(arg_list) start.status = Status.COMPLETE for c in nx.neighbors(self.networkx, start): diff --git a/tests/test_node.py b/tests/test_node.py index 8acb3f98a..9e603e2c5 100644 --- a/tests/test_node.py +++ b/tests/test_node.py @@ -1,14 +1,13 @@ -import logging import os import tempfile import unittest import networkx as nx import pytest -from networkx.readwrite import json_graph from hammer.flowgraph import node -from hammer.flowgraph.node import Graph, Node +from hammer.flowgraph.node import Graph, Node, Status +from hammer.logging import HammerVLSILogging class NodeTest(unittest.TestCase): @@ -127,7 +126,10 @@ def test_visualization(self) -> None: plt.savefig("/home/bngo/Research/hammer/graph.png", bbox_inches="tight", dpi=200) def test_run_basic(self) -> None: - """Test a basic syn -> par -> drc flow, all with nop tools.""" + """Test a basic syn -> par flow, all with nop tools.""" + HammerVLSILogging.clear_callbacks() + HammerVLSILogging.add_callback(HammerVLSILogging.callback_buffering) + with tempfile.TemporaryDirectory() as td: os.mkdir(os.path.join(td, "syn_dir")) os.mkdir(os.path.join(td, "par_dir")) @@ -176,30 +178,34 @@ def test_run_basic(self) -> None: sim_tool: "mocksim" """) - v0 = Node( - "syn-to-par", "nop", os.path.join(td, "syn_dir"), os.path.join(td, "par_dir"), + syn = Node( + "syn", "nop", + os.path.join(td, "syn_dir"), os.path.join(td, "s2p_dir"), ["syn-in.yml"], ["syn-out.json"], ) - v1 = Node( - "par-to-drc", "nop", os.path.join(td, "par_dir"), os.path.join(td, "drc_dir"), + s2p = Node( + "syn-to-par", "nop", + os.path.join(td, "s2p_dir"), os.path.join(td, "par_dir"), ["syn-out.json"], - ["par-out.json"], + ["s2p-out.json"], ) - v2 = Node( - "drc", "nop", os.path.join(td, "drc_dir"), os.path.join(td, "out_dir"), + par = Node( + "par", "nop", + os.path.join(td, "par_dir"), os.path.join(td, "out_dir"), + ["s2p-out.json"], ["par-out.json"], - ["drc-out.json"], ) g = Graph({ - v0: [v1], - v1: [v2], - v2: [] + syn: [s2p], + s2p: [par], + par: [] }) - g.run(v0) + g.run(syn) + for n in g.networkx: + self.assertEqual(n.status, Status.COMPLETE) if __name__ == "__main__": - logging.basicConfig(level=logging.DEBUG) unittest.main() From 4a41864f741c59839b0a35cc1ca948c19142c5df Mon Sep 17 00:00:00 2001 From: Bryan Ngo Date: Fri, 3 Feb 2023 11:50:20 -0800 Subject: [PATCH 10/36] more cycle reduction tests --- tests/test_node.py | 277 +++++++++++++++++++++++++++++++++++++-------- 1 file changed, 232 insertions(+), 45 deletions(-) diff --git a/tests/test_node.py b/tests/test_node.py index 9e603e2c5..3be15a9d9 100644 --- a/tests/test_node.py +++ b/tests/test_node.py @@ -1,6 +1,7 @@ import os import tempfile import unittest +from textwrap import dedent import networkx as nx import pytest @@ -16,7 +17,7 @@ def test_initialize_node(self) -> None: """Test that we can instantiate a node.""" test = Node( "syn", "nop", "syn_dir", "", - ["bryan-test.yml"], + ["foo.yml"], ["syn-out.json"], ) self.assertEqual(test.action, "syn") @@ -25,7 +26,7 @@ def test_complex_graph(self) -> None: """Creating a more complex graph.""" root = Node( "syn", "nop", "syn_dir", "", - ["bryan-test.yml"], + ["foo.yml"], ["syn-out.json"], ) child1 = Node( @@ -34,9 +35,24 @@ def test_complex_graph(self) -> None: ["par-out.json"], ) graph = Graph({root: [child1]}) - self.assertTrue(graph.verify()) self.assertEqual(len(graph.networkx), 2) self.assertEqual(graph.networkx.number_of_edges(), 1) + self.assertTrue(graph.verify()) + + def test_invalid_graph(self) -> None: + """Test that invalid flowgraphs are detected.""" + root = Node( + "syn", "nop", "syn_dir", "", + ["foo.yml"], + ["syn-out.json"], + ) + child1 = Node( + "par", "nop", "syn_dir", "par_dir", + ["syn-in.json"], + ["par-out.json"], + ) + graph = Graph({root: [child1]}) + self.assertFalse(graph.verify()) def test_cycle_reduction(self) -> None: """Test that cycles are reduced to an acyclic graph.""" @@ -67,6 +83,86 @@ def test_cycle_reduction(self) -> None: self.assertEqual(len(g_acyclic.networkx), 4) self.assertEqual(g.networkx.number_of_edges(), 3) + def test_big_cycle_reduction(self) -> None: + """Test that larger cycles are reduced to an acyclic graph.""" + v0 = Node( + "v0", "nop", "v0_dir", "v1_dir", + ["v0-in.json"], + ["v0-out.json"], + ) + v1 = Node( + "v1", "nop", "v1_dir", "v2_dir", + ["v0-out.json"], + ["v1-out.json"], + ) + v2 = Node( + "v2", "nop", "v2_dir", "v3_dir", + ["v1-out.json"], + ["v2-out.json"], + ) + v3 = Node( + "v3", "nop", "v3_dir", "v0_dir", + ["v2-out.json"], + ["v3-out.json"], + ) + g = Graph({ + v0: [v1], + v1: [v2], + v2: [v3], + v3: [v0] + }) + self.assertTrue(len(nx.find_cycle(g.networkx)) > 0) + g_acyclic = node.convert_to_acyclic(g) + with self.assertRaises(nx.NetworkXNoCycle): + nx.find_cycle(g_acyclic.networkx) + self.assertEqual(len(g_acyclic.networkx), 5) + self.assertEqual(g.networkx.number_of_edges(), 4) + + def test_multi_cycle_reduction(self) -> None: + """Test that multiple cycles are reduced to an acyclic graph.""" + v0 = Node( + "v0", "nop", "v0_dir", "v1_dir", + ["v0-in.json"], + ["v0-out.json"], + ) + v1 = Node( + "v1", "nop", "v1_dir", "v2_dir", + ["v0-out.json"], + ["v1-out.json"], + ) + v2 = Node( + "v2", "nop", "v2_dir", "v0_dir", + ["v1-out.json"], + ["v2-out.json"], + ) + v3 = Node( + "v3", "nop", "v3_dir", "v4_dir", + ["v2-out.json"], + ["v3-out.json"], + ) + v4 = Node( + "v4", "nop", "v4_dir", "v5_dir", + ["v3-out.json"], + ["v4-out.json"], + ) + v5 = Node( + "v5", "nop", "v5_dir", "v3_dir", + ["v4-out.json"], + ["v3-out.json"], + ) + g = Graph({ + v0: [v1], + v1: [v2], + v2: [v0, v3], + v3: [v4, v2], + v4: [v5], + v5: [v3] + }) + self.assertTrue(len(nx.find_cycle(g.networkx)) > 0) + g_acyclic = node.convert_to_acyclic(g) + with self.assertRaises(nx.NetworkXNoCycle): + nx.find_cycle(g_acyclic.networkx) + @pytest.mark.xfail(raises=ImportError, reason="Matplotlib currently not imported") def test_visualization(self) -> None: """Test visualization of flowgraph.""" @@ -130,53 +226,54 @@ def test_run_basic(self) -> None: HammerVLSILogging.clear_callbacks() HammerVLSILogging.add_callback(HammerVLSILogging.callback_buffering) + cfg = dedent(""" + synthesis.inputs: + input_files: ["LICENSE", "README.md"] + top_module: "z1top.xdc" + + par.inputs: + input_files: ["LICENSE", "README.md"] + top_module: "z1top.xdc" + + drc.inputs: + input_files: ["LICENSE", "README.md"] + top_module: "z1top.xdc" + + lvs.inputs: + input_files: ["LICENSE", "README.md"] + schematic_files: ["LICENSE", "README.md"] + top_module: "z1top.xdc" + hcells_list: [] + + pcb.inputs: + top_module: "z1top.xdc" + + formal.inputs: + input_files: ["LICENSE", "README.md"] + top_module: "z1top.xdc" + + sim.inputs: + input_files: ["LICENSE", "README.md"] + top_module: "z1top.xdc" + + vlsi: + core: + technology: "hammer.technology.nop" + + synthesis_tool: "hammer.synthesis.nop" + par_tool: "hammer.par.nop" + drc_tool: "hammer.drc.nop" + lvs_tool: "hammer.lvs.nop" + power_tool: "hammer.power.nop" + sim_tool: "mocksim" + """) + with tempfile.TemporaryDirectory() as td: os.mkdir(os.path.join(td, "syn_dir")) os.mkdir(os.path.join(td, "par_dir")) - os.mkdir(os.path.join(td, "drc_dir")) with open(os.path.join(td, "syn_dir", "syn-in.yml"), 'w', encoding="utf-8") as tf1: - tf1.write(""" -synthesis.inputs: - input_files: ["LICENSE", "README.md"] - top_module: "z1top.xdc" - -par.inputs: - input_files: ["LICENSE", "README.md"] - top_module: "z1top.xdc" - -drc.inputs: - input_files: ["LICENSE", "README.md"] - top_module: "z1top.xdc" - -lvs.inputs: - input_files: ["LICENSE", "README.md"] - schematic_files: ["LICENSE", "README.md"] - top_module: "z1top.xdc" - hcells_list: [] - -pcb.inputs: - top_module: "z1top.xdc" - -formal.inputs: - input_files: ["LICENSE", "README.md"] - top_module: "z1top.xdc" - -sim.inputs: - input_files: ["LICENSE", "README.md"] - top_module: "z1top.xdc" - -vlsi: - core: - technology: "hammer.technology.nop" - - synthesis_tool: "hammer.synthesis.nop" - par_tool: "hammer.par.nop" - drc_tool: "hammer.drc.nop" - lvs_tool: "hammer.lvs.nop" - power_tool: "hammer.power.nop" - sim_tool: "mocksim" -""") + tf1.write(cfg) syn = Node( "syn", "nop", @@ -206,6 +303,96 @@ def test_run_basic(self) -> None: for n in g.networkx: self.assertEqual(n.status, Status.COMPLETE) + def test_invalid_run(self) -> None: + """ + Test that a failing run should not run + other steps and exit gracefully. + """ + HammerVLSILogging.clear_callbacks() + HammerVLSILogging.add_callback(HammerVLSILogging.callback_buffering) + + cfg = dedent(""" + synthesis.inputs: + input_files: ["LICENSE", "README.md"] + top_module: "z1top.xdc" + + par.inputs: + input_files: ["LICENSE", "README.md"] + top_module: "z1top.xdc" + + drc.inputs: + input_files: ["LICENSE", "README.md"] + top_module: "z1top.xdc" + + lvs.inputs: + input_files: ["LICENSE", "README.md"] + schematic_files: ["LICENSE", "README.md"] + top_module: "z1top.xdc" + hcells_list: [] + + pcb.inputs: + top_module: "z1top.xdc" + + formal.inputs: + input_files: ["LICENSE", "README.md"] + top_module: "z1top.xdc" + + sim.inputs: + input_files: ["LICENSE", "README.md"] + top_module: "z1top.xdc" + + vlsi: + core: + technology: "hammer.technology.nop" + + synthesis_tool: "hammer.synthesis.nop" + par_tool: "hammer.par.nop" + drc_tool: "hammer.drc.nop" + lvs_tool: "hammer.lvs.nop" + power_tool: "hammer.power.nop" + sim_tool: "mocksim" + """) + + with tempfile.TemporaryDirectory() as td: + os.mkdir(os.path.join(td, "syn_dir")) + os.mkdir(os.path.join(td, "par_dir")) + + with open(os.path.join(td, "syn_dir", "syn-in.yml"), 'w', encoding="utf-8") as tf1: + tf1.write(cfg) + + syn = Node( + "syn", "nop", + os.path.join(td, "syn_dir"), os.path.join(td, "s2p_dir"), + ["syn-in.yml"], + ["syn-out.json"], + ) + s2p_bad = Node( + "blah", "nop", + os.path.join(td, "s2p_dir"), os.path.join(td, "par_dir"), + ["syn-out.json"], + ["s2p-out.json"], + ) + par = Node( + "par", "nop", + os.path.join(td, "par_dir"), os.path.join(td, "out_dir"), + ["s2p-out.json"], + ["par-out.json"], + ) + g = Graph({ + syn: [s2p_bad], + s2p_bad: [par], + par: [] + }) + with pytest.raises(Exception): + g.run(syn) + + print(syn.status) + print(s2p_bad.status) + print(par.status) + self.assertEqual(syn.status, Status.COMPLETE) + self.assertEqual(s2p_bad.status, Status.INCOMPLETE) + self.assertEqual(par.status, Status.NOT_RUN) + if __name__ == "__main__": unittest.main() From e81c1a0869bfb70a21ff42840b63c90f54b7fbc8 Mon Sep 17 00:00:00 2001 From: Bryan Ngo Date: Fri, 3 Feb 2023 11:50:37 -0800 Subject: [PATCH 11/36] better capture of errors --- hammer/flowgraph/node.py | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/hammer/flowgraph/node.py b/hammer/flowgraph/node.py index c2ddb1bfe..ca8d6c518 100644 --- a/hammer/flowgraph/node.py +++ b/hammer/flowgraph/node.py @@ -30,10 +30,8 @@ class Status(Enum): COMPLETE = "COMPLETE" -# make sure union of required/optional outs is superset of children required/optional inputs # separate required validity checking and optional validity checking # meta dict for tech compatibilty -# for cycles, reduce to DAG via cloning of one of the nodes @dataclass class Node: @@ -134,17 +132,18 @@ def run(self, start: Node) -> None: 'cad_files': None } + ctxt = HammerVLSILogging.context(start.action) + ctxt.info(f"Running graph step {start.action}") driver = cli_driver.CLIDriver() - try: - ctxt = HammerVLSILogging.context(start.action) - # ctxt.info(f"Running graph step {start.action}") - driver.run_main_parsed(arg_list) + code = driver.run_main_parsed(arg_list) + if code == 0: start.status = Status.COMPLETE - for c in nx.neighbors(self.networkx, start): - self.run(c) - except Exception as e: + else: start.status = Status.INCOMPLETE - raise e + raise RuntimeError(f"Step {start.action} failed") + + for c in nx.neighbors(self.networkx, start): + self.run(c) def convert_to_acyclic(g: Graph) -> Graph: """Eliminates cycles in a flowgraph for analysis. @@ -155,7 +154,7 @@ def convert_to_acyclic(g: Graph) -> Graph: Returns: Graph: Graph with cloned nodes. """ - cycles = sorted(nx.simple_cycles(g.networkx)) + cycles = nx.simple_cycles(g.networkx) new_edge_list = g.edge_list.copy() for cycle in cycles: cut_start, cut_end = cycle[0], cycle[1] @@ -171,5 +170,3 @@ def convert_to_acyclic(g: Graph) -> Graph: new_edge_list[cut_start] = [] new_edge_list[cut_end_copy] = cut_start_children return Graph(new_edge_list) - -# TODO: refresh graph From f6219f593c35fdfd6b6042916fadd8a2a6bf1a45 Mon Sep 17 00:00:00 2001 From: Bryan Ngo Date: Fri, 3 Mar 2023 11:17:28 -0800 Subject: [PATCH 12/36] add serialization test --- tests/test_node.py | 90 +++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 86 insertions(+), 4 deletions(-) diff --git a/tests/test_node.py b/tests/test_node.py index 3be15a9d9..1d29600c1 100644 --- a/tests/test_node.py +++ b/tests/test_node.py @@ -1,3 +1,4 @@ +import json import os import tempfile import unittest @@ -5,13 +6,14 @@ import networkx as nx import pytest +from networkx.readwrite import json_graph from hammer.flowgraph import node from hammer.flowgraph.node import Graph, Node, Status from hammer.logging import HammerVLSILogging -class NodeTest(unittest.TestCase): +class TestNode(unittest.TestCase): def test_initialize_node(self) -> None: """Test that we can instantiate a node.""" @@ -386,13 +388,93 @@ def test_invalid_run(self) -> None: with pytest.raises(Exception): g.run(syn) - print(syn.status) - print(s2p_bad.status) - print(par.status) self.assertEqual(syn.status, Status.COMPLETE) self.assertEqual(s2p_bad.status, Status.INCOMPLETE) self.assertEqual(par.status, Status.NOT_RUN) + def test_encode_decode(self) -> None: + """ + Test that a flowgraph can be encoded and decoded. + """ + HammerVLSILogging.clear_callbacks() + HammerVLSILogging.add_callback(HammerVLSILogging.callback_buffering) + + cfg = dedent(""" + synthesis.inputs: + input_files: ["LICENSE", "README.md"] + top_module: "z1top.xdc" + + par.inputs: + input_files: ["LICENSE", "README.md"] + top_module: "z1top.xdc" + + drc.inputs: + input_files: ["LICENSE", "README.md"] + top_module: "z1top.xdc" + + lvs.inputs: + input_files: ["LICENSE", "README.md"] + schematic_files: ["LICENSE", "README.md"] + top_module: "z1top.xdc" + hcells_list: [] + + pcb.inputs: + top_module: "z1top.xdc" + + formal.inputs: + input_files: ["LICENSE", "README.md"] + top_module: "z1top.xdc" + + sim.inputs: + input_files: ["LICENSE", "README.md"] + top_module: "z1top.xdc" + + vlsi: + core: + technology: "hammer.technology.nop" + + synthesis_tool: "hammer.synthesis.nop" + par_tool: "hammer.par.nop" + drc_tool: "hammer.drc.nop" + lvs_tool: "hammer.lvs.nop" + power_tool: "hammer.power.nop" + sim_tool: "mocksim" + """) + + with tempfile.TemporaryDirectory() as td: + os.mkdir(os.path.join(td, "syn_dir")) + os.mkdir(os.path.join(td, "par_dir")) + + with open(os.path.join(td, "syn_dir", "syn-in.yml"), 'w', encoding="utf-8") as tf1: + tf1.write(cfg) + syn = Node( + "syn", "nop", + os.path.join(td, "syn_dir"), os.path.join(td, "s2p_dir"), + ["syn-in.yml"], + ["syn-out.json"], + ) + s2p = Node( + "syn-to-par", "nop", + os.path.join(td, "s2p_dir"), os.path.join(td, "par_dir"), + ["syn-out.json"], + ["s2p-out.json"], + ) + par = Node( + "par", "nop", + os.path.join(td, "par_dir"), os.path.join(td, "out_dir"), + ["s2p-out.json"], + ["par-out.json"], + ) + g = Graph({ + syn: [s2p], + s2p: [par], + par: [] + }) + + out = json.dumps(g.to_json(), cls=node.NodeEncoder) + g_dec = json.loads(out, object_hook=node.as_node) + # print(g.to_json()) + print(json_graph.node_link_graph(g_dec).nodes) if __name__ == "__main__": unittest.main() From cbede149e6758a6e8869b7f3d8779c98be6712b4 Mon Sep 17 00:00:00 2001 From: Bryan Ngo Date: Fri, 3 Mar 2023 11:17:57 -0800 Subject: [PATCH 13/36] using property decorators --- hammer/config/config_src.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/hammer/config/config_src.py b/hammer/config/config_src.py index 99a3fadb9..a7b437d3a 100644 --- a/hammer/config/config_src.py +++ b/hammer/config/config_src.py @@ -717,6 +717,7 @@ def get_config(self) -> dict: self.__config_cache_dirty = False return self.__config_cache + @property def get_config_types(self) -> dict: """ Get the types for the configuration of a database. @@ -818,9 +819,9 @@ def get_setting_type(self, key: str, nullvalue: Any = None) -> Any: :param nullvalue: Value to return for nulls. :return: Data type of key. """ - if key not in self.get_config_types(): + if key not in self.get_config_types: raise KeyError(f"Key type {key} is missing") - value = self.get_config_types()[key] + value = self.get_config_types[key] return nullvalue if value is None else value def set_setting_type(self, key: str, value: Any) -> None: @@ -840,7 +841,7 @@ def has_setting_type(self, key: str) -> bool: :param key: Desired key. :return: True if the given setting exists. """ - return key in self.get_config_types() + return key in self.get_config_types def check_setting(self, key: str, cfg: Optional[dict] = None) -> bool: """ @@ -852,11 +853,11 @@ def check_setting(self, key: str, cfg: Optional[dict] = None) -> bool: if cfg is None: cfg = self.get_config() - if key not in self.get_config_types(): + if key not in self.get_config_types: self.logger.warning(f"Key {key} is not associated with a type") return True try: - exp_value_type = parse_setting_type(self.get_config_types()[key]) + exp_value_type = parse_setting_type(self.get_config_types[key]) except ValueError as ve: raise ValueError(f'Key {key} has an invalid outer type: perhaps you have "List" instead of "list" or "Dict" instead of "dict"?') from ve From 62b262df8b015eccc7eb6677b85ba0a6eaee5bae Mon Sep 17 00:00:00 2001 From: Bryan Ngo Date: Fri, 10 Mar 2023 02:16:48 -0800 Subject: [PATCH 14/36] add step control and custom driver --- hammer/flowgraph/node.py | 146 ++++++++++++++++++++++++++++++++++----- 1 file changed, 130 insertions(+), 16 deletions(-) diff --git a/hammer/flowgraph/node.py b/hammer/flowgraph/node.py index ca8d6c518..c179f5cac 100644 --- a/hammer/flowgraph/node.py +++ b/hammer/flowgraph/node.py @@ -8,12 +8,16 @@ # pylint: disable=invalid-name +import importlib +import json import os import uuid -from dataclasses import dataclass, field +from dataclasses import dataclass, field, asdict from enum import Enum +from typing import Any, Union import networkx as nx +from networkx.readwrite import json_graph from hammer.logging import HammerVLSILogging from hammer.vlsi import cli_driver @@ -35,6 +39,11 @@ class Status(Enum): @dataclass class Node: + """Defines a node for an action in a flowgraph. + + Returns: + Node: Complete description of an action. + """ action: str tool: str pull_dir: str @@ -42,9 +51,17 @@ class Node: required_inputs: list[str] required_outputs: list[str] status: Status = Status.NOT_RUN - __uuid: uuid.UUID = field(default_factory=uuid.uuid4) + # __uuid: uuid.UUID = field(default_factory=uuid.uuid4) + driver: str = "" optional_inputs: list[str] = field(default_factory=list) optional_outputs: list[str] = field(default_factory=list) + step_controls: dict[str, str] = field(default_factory=lambda: { + "from_step": "", + "after_step": "", + "to_step": "", + "until_step": "", + "only_step": "", + }) def __key(self) -> tuple: """Key value for hashing. @@ -61,15 +78,69 @@ def __key(self) -> tuple: tuple(self.required_outputs), tuple(self.optional_inputs), tuple(self.optional_outputs), - self.status + self.status, + tuple(self.step_controls.items()) ) def __hash__(self) -> int: + """Dunder method for uniquely hashing a `Node` object. + + Returns: + int: Hash of a `Node`. + """ return hash(self.__key) + def __is_privileged(self) -> bool: + """Private method for checking if + step control is applied to a `Node`. + + Returns: + bool: If the node is allowed to be the starting point of a flow. + """ + return any(i != "" for i in self.step_controls.values()) + + @property + def privileged(self) -> bool: + """Property for determining node privilege. + + Returns: + bool: If the node is allowed to be the starting point of a flow. + """ + return self.__is_privileged() + +class NodeEncoder(json.JSONEncoder): + def default(self, o: Any) -> Any: + if isinstance(o, Node): + return asdict(o) + elif isinstance(o, Status): + return o.value + return super().default(o) + +def as_node(dct: dict) -> Union[Node, dict]: + if "action" in dct: + return Node( + dct["action"], + dct["tool"], + dct["pull_dir"], + dct["push_dir"], + dct["required_inputs"], + dct["required_outputs"], + Status(dct["status"]), + dct["optional_inputs"], + dct["optional_outputs"], + ) + return dct + @dataclass class Graph: + """Defines a flowgraph. + + Returns: + Graph: HAMMER flowgraph. + """ edge_list: dict[Node, list[Node]] + driver: str = "" + # driver: cli_driver.CLIDriver = field(default_factory=cli_driver.CLIDriver) def __post_init__(self) -> None: self.networkx = nx.DiGraph(self.edge_list) @@ -97,14 +168,32 @@ def __process(self, v: Node) -> bool: inputs = set(v.required_inputs) | set(v.optional_inputs) return self.networkx.in_degree(v) == 0 or parent_outs >= inputs - def run(self, start: Node) -> None: - """Run a HAMMER flowgraph.""" + def run(self, start: Node) -> Any: + """Runs a flowgraph. + + Args: + start (Node): Node to start the run on. + + Raises: + RuntimeError: If the flowgraph is invalid. + RuntimeError: If the starting node is not in the flowgraph. + """ if not self.verify(): - raise RuntimeError("Flowgraph is invalid") + raise RuntimeError("Flowgraph is invalid. Please check your flow's inputs and outputs.") if start not in self.networkx: - raise RuntimeError("Node not in flowgraph") + raise RuntimeError("Node not in flowgraph. Did you construct the graph correctly?") + if not start.privileged and any(i.privileged for i in self.networkx): + raise RuntimeError("Attempting to run non-privileged node in privileged flow. Please complete your stepped flow first.") + + if start.driver != "": + driver_pkg_path, driver_module = self.driver.rsplit('.', 1) + driver_pkg = importlib.import_module(driver_pkg_path) + driver = getattr(driver_pkg, driver_module)() + if not isinstance(driver, cli_driver.CLIDriver): + raise TypeError(f"Driver {driver} does not extend CLIDriver, cannot run a flow.") + else: + driver = cli_driver.CLIDriver() - start.status = Status.RUNNING arg_list = { "action": start.action, 'environment_config': None, @@ -120,31 +209,47 @@ def run(self, start: Node) -> None: 'formal_rundir': '', 'timing_rundir': '', # TODO: sub-step determinations - 'from_step': None, - 'after_step': None, - 'to_step': None, - 'until_step': None, - 'only_step': None, + 'from_step': start.step_controls["from_step"], + 'after_step': start.step_controls["after_step"], + 'to_step': start.step_controls["to_step"], + 'until_step': start.step_controls["until_step"], + 'only_step': start.step_controls["only_step"], 'output': os.path.join(start.push_dir, start.required_outputs[0]), # TODO: fix this 'verilog': None, 'firrtl': None, 'top': None, - 'cad_files': None + 'cad_files': None, + 'dump_history': False } + start.status = Status.RUNNING ctxt = HammerVLSILogging.context(start.action) ctxt.info(f"Running graph step {start.action}") - driver = cli_driver.CLIDriver() code = driver.run_main_parsed(arg_list) if code == 0: start.status = Status.COMPLETE else: start.status = Status.INCOMPLETE - raise RuntimeError(f"Step {start.action} failed") + ctxt.fatal(f"Step {start.action} failed") + return self for c in nx.neighbors(self.networkx, start): self.run(c) + return self + + def to_json(self) -> dict: + """Encodes a graph as a JSON string. + + Returns: + str: JSON dump of a flowgraph. + """ + return json_graph.node_link_data(self.networkx) + + def visualize(self) -> Any: + raise NotImplementedError() + + def convert_to_acyclic(g: Graph) -> Graph: """Eliminates cycles in a flowgraph for analysis. @@ -170,3 +275,12 @@ def convert_to_acyclic(g: Graph) -> Graph: new_edge_list[cut_start] = [] new_edge_list[cut_end_copy] = cut_start_children return Graph(new_edge_list) + + +# TODO: serialization format +# TODO: cycles are conditional on user input +# TODO: put x-to-y actions between connections +# TODO: hooks into nodes +# TODO: stopping/starting flows +# TODO: d2 stuff +# TODO: write tests for hooks/steps From 36553c40625fd4bf27b2fb64e71b865ccdcfa2b5 Mon Sep 17 00:00:00 2001 From: Bryan Ngo Date: Fri, 10 Mar 2023 02:17:08 -0800 Subject: [PATCH 15/36] small linting fix --- hammer/vlsi/cli_driver.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hammer/vlsi/cli_driver.py b/hammer/vlsi/cli_driver.py index cd91f7c9f..aaf89ca33 100644 --- a/hammer/vlsi/cli_driver.py +++ b/hammer/vlsi/cli_driver.py @@ -322,8 +322,8 @@ def info_action(driver: HammerDriver, append_error_func: Callable[[str], None]) if "_meta" not in k: print(k) while True: + key = input("Select from the current level of keys: ") try: - key = input("Select from the current level of keys: ") next_level = curr_level[key] break except KeyError: From 9465d20b8a817b87bcd65f640a56839cdde72622 Mon Sep 17 00:00:00 2001 From: Bryan Ngo Date: Fri, 10 Mar 2023 02:17:30 -0800 Subject: [PATCH 16/36] graph runner should not raise exception --- tests/test_node.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/test_node.py b/tests/test_node.py index 1d29600c1..a0e165650 100644 --- a/tests/test_node.py +++ b/tests/test_node.py @@ -385,8 +385,7 @@ def test_invalid_run(self) -> None: s2p_bad: [par], par: [] }) - with pytest.raises(Exception): - g.run(syn) + g.run(syn) self.assertEqual(syn.status, Status.COMPLETE) self.assertEqual(s2p_bad.status, Status.INCOMPLETE) From 74685bdb0b252eafc9ba29c3874e8f4def82616f Mon Sep 17 00:00:00 2001 From: Bryan Ngo Date: Fri, 10 Mar 2023 03:19:35 -0800 Subject: [PATCH 17/36] add mermaid support --- hammer/flowgraph/node.py | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/hammer/flowgraph/node.py b/hammer/flowgraph/node.py index c179f5cac..bb8f1fe9f 100644 --- a/hammer/flowgraph/node.py +++ b/hammer/flowgraph/node.py @@ -246,9 +246,22 @@ def to_json(self) -> dict: """ return json_graph.node_link_data(self.networkx) - def visualize(self) -> Any: + def to_d2(self) -> Any: raise NotImplementedError() + def to_mermaid(self, fname: str) -> None: + """Converts the flowgraph into Mermaid format for visualization. + + Args: + fname (str): Output file name. + """ + with open(fname, 'w', encoding="utf-8") as f: + f.write("stateDiagram-v2\n") + for start in self.networkx: + f.writelines( + f" {start.action} --> {child.action}\n" + for child in nx.neighbors(self.networkx, start) + ) def convert_to_acyclic(g: Graph) -> Graph: """Eliminates cycles in a flowgraph for analysis. @@ -280,7 +293,5 @@ def convert_to_acyclic(g: Graph) -> Graph: # TODO: serialization format # TODO: cycles are conditional on user input # TODO: put x-to-y actions between connections -# TODO: hooks into nodes -# TODO: stopping/starting flows # TODO: d2 stuff # TODO: write tests for hooks/steps From 13c9f006286c70b3c3e8d1914b6ad7ae1bdf3868 Mon Sep 17 00:00:00 2001 From: Bryan Ngo Date: Fri, 10 Mar 2023 03:19:41 -0800 Subject: [PATCH 18/36] add test for mermaid --- tests/test_node.py | 127 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 127 insertions(+) diff --git a/tests/test_node.py b/tests/test_node.py index a0e165650..803e8a023 100644 --- a/tests/test_node.py +++ b/tests/test_node.py @@ -391,6 +391,133 @@ def test_invalid_run(self) -> None: self.assertEqual(s2p_bad.status, Status.INCOMPLETE) self.assertEqual(par.status, Status.NOT_RUN) + def test_resume_graph(self) -> None: + """ + Test that a user can stop and start a flow if needed. + """ + HammerVLSILogging.clear_callbacks() + HammerVLSILogging.add_callback(HammerVLSILogging.callback_buffering) + + cfg = dedent(""" + synthesis.inputs: + input_files: ["LICENSE", "README.md"] + top_module: "z1top.xdc" + + par.inputs: + input_files: ["LICENSE", "README.md"] + top_module: "z1top.xdc" + + drc.inputs: + input_files: ["LICENSE", "README.md"] + top_module: "z1top.xdc" + + lvs.inputs: + input_files: ["LICENSE", "README.md"] + schematic_files: ["LICENSE", "README.md"] + top_module: "z1top.xdc" + hcells_list: [] + + pcb.inputs: + top_module: "z1top.xdc" + + formal.inputs: + input_files: ["LICENSE", "README.md"] + top_module: "z1top.xdc" + + sim.inputs: + input_files: ["LICENSE", "README.md"] + top_module: "z1top.xdc" + + vlsi: + core: + technology: "hammer.technology.nop" + + synthesis_tool: "hammer.synthesis.nop" + par_tool: "hammer.par.nop" + drc_tool: "hammer.drc.nop" + lvs_tool: "hammer.lvs.nop" + power_tool: "hammer.power.nop" + sim_tool: "mocksim" + """) + + with tempfile.TemporaryDirectory() as td: + os.mkdir(os.path.join(td, "syn_dir")) + os.mkdir(os.path.join(td, "par_dir")) + + with open(os.path.join(td, "syn_dir", "syn-in.yml"), 'w', encoding="utf-8") as tf1: + tf1.write(cfg) + + syn = Node( + "syn", "nop", + os.path.join(td, "syn_dir"), os.path.join(td, "s2p_dir"), + ["syn-in.yml"], + ["syn-out.json"], + ) + s2p_bad = Node( + "blah", "nop", + os.path.join(td, "s2p_dir"), os.path.join(td, "par_dir"), + ["syn-out.json"], + ["s2p-out.json"], + ) + par = Node( + "par", "nop", + os.path.join(td, "par_dir"), os.path.join(td, "out_dir"), + ["s2p-out.json"], + ["par-out.json"], + ) + g = Graph({ + syn: [s2p_bad], + s2p_bad: [par], + par: [] + }) + g_failed_run = g.run(syn) + + self.assertEqual(syn.status, Status.COMPLETE) + self.assertEqual(s2p_bad.status, Status.INCOMPLETE) + self.assertEqual(par.status, Status.NOT_RUN) + + s2p_bad.action = "syn-to-par" + g_good = g_failed_run.run(s2p_bad) + for n in g_good.networkx: + self.assertEqual(n.status, Status.COMPLETE) + + def test_mermaid(self) -> None: + """ + Test that Mermaid visualization works. + """ + with tempfile.TemporaryDirectory() as td: + os.mkdir(os.path.join(td, "syn_dir")) + os.mkdir(os.path.join(td, "par_dir")) + + syn = Node( + "syn", "nop", + os.path.join(td, "syn_dir"), os.path.join(td, "s2p_dir"), + ["syn-in.yml"], + ["syn-out.json"], + ) + s2p = Node( + "syn-to-par", "nop", + os.path.join(td, "s2p_dir"), os.path.join(td, "par_dir"), + ["syn-out.json"], + ["s2p-out.json"], + ) + par = Node( + "par", "nop", + os.path.join(td, "par_dir"), os.path.join(td, "out_dir"), + ["s2p-out.json"], + ["par-out.json"], + ) + g = Graph({ + syn: [s2p], + s2p: [par], + par: [] + }) + + g.to_mermaid(os.path.join(td, "mermaid.txt")) + with open(os.path.join(td, "mermaid.txt"), 'r', encoding="utf-8") as f: + s = f.readlines() + self.assertListEqual(s, ["stateDiagram-v2\n", " syn --> syn-to-par\n", " syn-to-par --> par\n"]) + def test_encode_decode(self) -> None: """ Test that a flowgraph can be encoded and decoded. From 51bf5ea86db0e70b7956d25a21043f5b2fea23a5 Mon Sep 17 00:00:00 2001 From: Bryan Ngo Date: Thu, 23 Mar 2023 16:48:18 -0700 Subject: [PATCH 19/36] implement and test auto-insertion of aux actions --- hammer/flowgraph/node.py | 74 +++++++++++++++-- tests/test_node.py | 174 ++++++++++++++++++++++----------------- 2 files changed, 166 insertions(+), 82 deletions(-) diff --git a/hammer/flowgraph/node.py b/hammer/flowgraph/node.py index bb8f1fe9f..9c03d6dad 100644 --- a/hammer/flowgraph/node.py +++ b/hammer/flowgraph/node.py @@ -139,11 +139,10 @@ class Graph: Graph: HAMMER flowgraph. """ edge_list: dict[Node, list[Node]] - driver: str = "" - # driver: cli_driver.CLIDriver = field(default_factory=cli_driver.CLIDriver) + auto_auxiliary: bool = True def __post_init__(self) -> None: - self.networkx = nx.DiGraph(self.edge_list) + self.networkx = nx.DiGraph(Graph.insert_auxiliary_actions(self.edge_list) if self.auto_auxiliary else self.edge_list) def verify(self) -> bool: """Checks if a graph is valid via its inputs and outputs. @@ -168,6 +167,69 @@ def __process(self, v: Node) -> bool: inputs = set(v.required_inputs) | set(v.optional_inputs) return self.networkx.in_degree(v) == 0 or parent_outs >= inputs + @staticmethod + def insert_auxiliary_actions(edge_list: dict[Node, list[Node]]) -> dict[Node, list[Node]]: + """Inserts x-to-y actions between two semantically related actions (e.g. if syn and par are connected, then we have to insert a syn-to-par node here). + + Args: + edge_list (dict[Node, list[Node]]): Edge list without auxiliary actions. + + Returns: + dict[Node, list[Node]]: Transformed edge list with auxiliary actions. + """ + valid_auxiliary_actions = [ + ("synthesis", "par"), + ("syn", "par"), + ("heir-par", "syn"), + ("heir_par", "syn"), + ("par", "drc"), + ("par", "lvs"), + ("synthesis", "sim"), + ("syn", "sim"), + ("par", "sim"), + ("syn", "power"), + ("par", "power"), + ("sim", "power"), + ("synthesis", "formal"), + ("syn", "formal"), + ("par", "formal"), + ("synthesis", "timing"), + ("syn", "timing"), + ("par", "timing"), + ] + + changes = [] + edge_list_copy = edge_list.copy() + for parent_idx, (parent, children) in enumerate(edge_list.items()): + for child_idx, child in enumerate(children): + if (parent.action, child.action) in valid_auxiliary_actions: + aux_action = f"{parent.action}-to-{child.action}" + aux_node = Node( + aux_action, + parent.tool, + os.path.join(os.path.dirname(parent.pull_dir), f"{aux_action}-dir"), + child.pull_dir, + parent.required_outputs, + [f"{aux_action}-out.json"], + ) + changes.append((parent_idx, child_idx, aux_node)) + + for parent_idx, child_idx, aux_node in changes: + parent, children = list(edge_list_copy.items())[parent_idx] + parent.push_dir = os.path.join( + os.path.dirname(parent.pull_dir), + f"{aux_node.action}-dir") + + child = children[child_idx] + child.required_inputs = aux_node.required_outputs + + children[child_idx] = aux_node + if aux_node not in edge_list_copy: + edge_list_copy[aux_node] = [] + edge_list_copy[aux_node].append(child) + return edge_list_copy + + def run(self, start: Node) -> Any: """Runs a flowgraph. @@ -186,7 +248,7 @@ def run(self, start: Node) -> Any: raise RuntimeError("Attempting to run non-privileged node in privileged flow. Please complete your stepped flow first.") if start.driver != "": - driver_pkg_path, driver_module = self.driver.rsplit('.', 1) + driver_pkg_path, driver_module = start.driver.rsplit('.', 1) driver_pkg = importlib.import_module(driver_pkg_path) driver = getattr(driver_pkg, driver_module)() if not isinstance(driver, cli_driver.CLIDriver): @@ -208,7 +270,6 @@ def run(self, start: Node) -> Any: 'power_rundir': '', 'formal_rundir': '', 'timing_rundir': '', - # TODO: sub-step determinations 'from_step': start.step_controls["from_step"], 'after_step': start.step_controls["after_step"], 'to_step': start.step_controls["to_step"], @@ -292,6 +353,5 @@ def convert_to_acyclic(g: Graph) -> Graph: # TODO: serialization format # TODO: cycles are conditional on user input -# TODO: put x-to-y actions between connections -# TODO: d2 stuff # TODO: write tests for hooks/steps +# TODO: make custom driver and tech for steps diff --git a/tests/test_node.py b/tests/test_node.py index 803e8a023..d8956e883 100644 --- a/tests/test_node.py +++ b/tests/test_node.py @@ -27,14 +27,14 @@ def test_initialize_node(self) -> None: def test_complex_graph(self) -> None: """Creating a more complex graph.""" root = Node( - "syn", "nop", "syn_dir", "", + "foo", "nop", "foo_dir", "", ["foo.yml"], - ["syn-out.json"], + ["foo-out.json"], ) child1 = Node( - "par", "nop", "syn_dir", "par_dir", - ["syn-out.json"], - ["par-out.json"], + "bar", "nop", "foo_dir", "bar_dir", + ["foo-out.json"], + ["bar-out.json"], ) graph = Graph({root: [child1]}) self.assertEqual(len(graph.networkx), 2) @@ -44,14 +44,14 @@ def test_complex_graph(self) -> None: def test_invalid_graph(self) -> None: """Test that invalid flowgraphs are detected.""" root = Node( - "syn", "nop", "syn_dir", "", + "foo", "nop", "foo_dir", "", ["foo.yml"], - ["syn-out.json"], + ["foo-out.json"], ) child1 = Node( - "par", "nop", "syn_dir", "par_dir", - ["syn-in.json"], - ["par-out.json"], + "bar", "nop", "foo_dir", "bar_dir", + ["foo-in.json"], + ["bar-out.json"], ) graph = Graph({root: [child1]}) self.assertFalse(graph.verify()) @@ -165,64 +165,6 @@ def test_multi_cycle_reduction(self) -> None: with self.assertRaises(nx.NetworkXNoCycle): nx.find_cycle(g_acyclic.networkx) - @pytest.mark.xfail(raises=ImportError, reason="Matplotlib currently not imported") - def test_visualization(self) -> None: - """Test visualization of flowgraph.""" - import matplotlib.pyplot as plt - v0 = Node( - "syn", "nop", "syn_dir", "par_dir", - ["syn-in.json"], - ["syn-out.json"], - ) - v1 = Node( - "par", "nop", "par_dir", "drc_dir", - ["syn-out.json", "par-in.json", "drc-out.json"], - ["par-out.json"], - ) - v2 = Node( - "drc", "nop", "drc_dir", "par_dir", - ["par-out.json", "drc-in.json"], - ["drc-out.json"], - ) - g = Graph({ - v0.action: [v1.action], - v1.action: [v2.action], - v2.action: [] - }).networkx - g.add_edge(v0.pull_dir, v0.action) - g.add_edge(v0.action, v0.push_dir) - g.add_edge(v1.pull_dir, v1.action) - g.add_edge(v1.action, v1.push_dir) - g.add_edge(v2.pull_dir, v2.action) - g.add_edge(v2.action, v2.push_dir) - pos = nx.planar_layout(g) - blue = "#003262" - yellow = "#fdb515" - nx.draw_networkx_nodes(g, pos=pos, - nodelist=[v0.action, v1.action, v2.action], node_size=1500, node_color=blue, label="Action") - nx.draw_networkx_nodes(g, pos=pos, - nodelist=[ - v0.pull_dir, v0.push_dir, - v1.pull_dir, v1.push_dir, - v2.pull_dir, v2.push_dir - ], node_size=1500, node_color=yellow, label="Push/Pull Directory") - nx.draw_networkx_labels(g, pos=pos, font_size=8, font_color="whitesmoke") - nx.draw_networkx_edges(g, pos=pos, - nodelist=[v0.action, v1.action, v2.action], - node_size=1500, arrowsize=15, connectionstyle="arc3, rad=0.2", edge_color=blue) - nx.draw_networkx_edges(g, pos=pos, - edgelist=[ - (v0.pull_dir, v0.action), - (v0.action, v0.push_dir), - (v1.pull_dir, v1.action), - (v1.action, v1.push_dir), - (v2.pull_dir, v2.action), - (v2.action, v2.push_dir), - ], node_size=1500, arrowsize=15, connectionstyle="arc3, rad=0.2", edge_color=yellow) - plt.axis("off") - plt.legend(loc="upper left", markerscale=0.2) - plt.savefig("/home/bngo/Research/hammer/graph.png", bbox_inches="tight", dpi=200) - def test_run_basic(self) -> None: """Test a basic syn -> par flow, all with nop tools.""" HammerVLSILogging.clear_callbacks() @@ -299,7 +241,7 @@ def test_run_basic(self) -> None: syn: [s2p], s2p: [par], par: [] - }) + }, auto_auxiliary=False) g.run(syn) for n in g.networkx: @@ -384,7 +326,7 @@ def test_invalid_run(self) -> None: syn: [s2p_bad], s2p_bad: [par], par: [] - }) + }, auto_auxiliary=False) g.run(syn) self.assertEqual(syn.status, Status.COMPLETE) @@ -469,7 +411,7 @@ def test_resume_graph(self) -> None: syn: [s2p_bad], s2p_bad: [par], par: [] - }) + }, auto_auxiliary=False) g_failed_run = g.run(syn) self.assertEqual(syn.status, Status.COMPLETE) @@ -511,12 +453,94 @@ def test_mermaid(self) -> None: syn: [s2p], s2p: [par], par: [] - }) + }, auto_auxiliary=False) - g.to_mermaid(os.path.join(td, "mermaid.txt")) - with open(os.path.join(td, "mermaid.txt"), 'r', encoding="utf-8") as f: + g.to_mermaid(os.path.join(td, "mermaid.md")) + with open(os.path.join(td, "mermaid.md"), 'r', encoding="utf-8") as f: s = f.readlines() - self.assertListEqual(s, ["stateDiagram-v2\n", " syn --> syn-to-par\n", " syn-to-par --> par\n"]) + self.assertListEqual(s, + ["stateDiagram-v2\n", + " syn --> syn-to-par\n", + " syn-to-par --> par\n"]) + + def test_auto_auxiliary(self) -> None: + """ + Test that auxiliary actions are automatically inserted. + """ + HammerVLSILogging.clear_callbacks() + HammerVLSILogging.add_callback(HammerVLSILogging.callback_buffering) + + cfg = dedent(""" + synthesis.inputs: + input_files: ["LICENSE", "README.md"] + top_module: "z1top.xdc" + + par.inputs: + input_files: ["LICENSE", "README.md"] + top_module: "z1top.xdc" + + drc.inputs: + input_files: ["LICENSE", "README.md"] + top_module: "z1top.xdc" + + lvs.inputs: + input_files: ["LICENSE", "README.md"] + schematic_files: ["LICENSE", "README.md"] + top_module: "z1top.xdc" + hcells_list: [] + + pcb.inputs: + top_module: "z1top.xdc" + + formal.inputs: + input_files: ["LICENSE", "README.md"] + top_module: "z1top.xdc" + + sim.inputs: + input_files: ["LICENSE", "README.md"] + top_module: "z1top.xdc" + + vlsi: + core: + technology: "hammer.technology.nop" + + synthesis_tool: "hammer.synthesis.nop" + par_tool: "hammer.par.nop" + drc_tool: "hammer.drc.nop" + lvs_tool: "hammer.lvs.nop" + power_tool: "hammer.power.nop" + sim_tool: "mocksim" + """) + + with tempfile.TemporaryDirectory() as td: + os.mkdir(os.path.join(td, "syn_dir")) + os.mkdir(os.path.join(td, "par_dir")) + + with open(os.path.join(td, "syn_dir", "syn-in.yml"), 'w', encoding="utf-8") as tf1: + tf1.write(cfg) + + syn = Node( + "syn", "nop", + os.path.join(td, "syn_dir"), os.path.join(td, "par_dir"), + ["syn-in.yml"], + ["syn-out.json"], + ) + par = Node( + "par", "nop", + os.path.join(td, "par_dir"), os.path.join(td, "out_dir"), + ["syn-out.json"], + ["par-out.json"], + ) + g = Graph({ + syn: [par], + par: [] + }) + self.assertEqual(len(g.networkx), 3) # check that there are three nodes + self.assertEqual(len(g.networkx.edges), 2) # check that there are two edge connections + g.run(syn) + + for n in g.networkx: + self.assertEqual(n.status, Status.COMPLETE) def test_encode_decode(self) -> None: """ From 3d1be77e3edfad784ec89d5f73316adfb2d145b0 Mon Sep 17 00:00:00 2001 From: Bryan Ngo Date: Thu, 23 Mar 2023 17:02:08 -0700 Subject: [PATCH 20/36] update poetry.lock --- poetry.lock | 700 ++++++++++++++++++++++++++-------------------------- 1 file changed, 354 insertions(+), 346 deletions(-) diff --git a/poetry.lock b/poetry.lock index 9ebff9f13..8cfb05fba 100644 --- a/poetry.lock +++ b/poetry.lock @@ -14,14 +14,14 @@ files = [ [[package]] name = "astroid" -version = "2.13.3" +version = "2.15.0" description = "An abstract syntax tree for Python with inference support." category = "dev" optional = false python-versions = ">=3.7.2" files = [ - {file = "astroid-2.13.3-py3-none-any.whl", hash = "sha256:14c1603c41cc61aae731cad1884a073c4645e26f126d13ac8346113c95577f3b"}, - {file = "astroid-2.13.3.tar.gz", hash = "sha256:6afc22718a48a689ca24a97981ad377ba7fb78c133f40335dfd16772f29bcfb1"}, + {file = "astroid-2.15.0-py3-none-any.whl", hash = "sha256:e3e4d0ffc2d15d954065579689c36aac57a339a4679a679579af6401db4d3fdb"}, + {file = "astroid-2.15.0.tar.gz", hash = "sha256:525f126d5dc1b8b0b6ee398b33159105615d92dc4a17f2cd064125d57f6186fa"}, ] [package.dependencies] @@ -53,19 +53,16 @@ tests-no-zope = ["cloudpickle", "cloudpickle", "hypothesis", "hypothesis", "mypy [[package]] name = "babel" -version = "2.11.0" +version = "2.12.1" description = "Internationalization utilities" category = "dev" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" files = [ - {file = "Babel-2.11.0-py3-none-any.whl", hash = "sha256:1ad3eca1c885218f6dce2ab67291178944f810a10a9b5f3cb8382a5a232b64fe"}, - {file = "Babel-2.11.0.tar.gz", hash = "sha256:5ef4b3226b0180dedded4229651c8b0e1a3a6a2837d45a073272f313e4cf97f6"}, + {file = "Babel-2.12.1-py3-none-any.whl", hash = "sha256:b4246fb7677d3b98f501a39d43396d3cafdc8eadb045f4a31be01863f655c610"}, + {file = "Babel-2.12.1.tar.gz", hash = "sha256:cc2d99999cd01d44420ae725a21c9e3711b3aadc7976d6147f622d8581963455"}, ] -[package.dependencies] -pytz = ">=2015.7" - [[package]] name = "certifi" version = "2022.12.7" @@ -80,100 +77,87 @@ files = [ [[package]] name = "charset-normalizer" -version = "3.0.1" +version = "3.1.0" description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." category = "dev" optional = false -python-versions = "*" +python-versions = ">=3.7.0" files = [ - {file = "charset-normalizer-3.0.1.tar.gz", hash = "sha256:ebea339af930f8ca5d7a699b921106c6e29c617fe9606fa7baa043c1cdae326f"}, - {file = "charset_normalizer-3.0.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:88600c72ef7587fe1708fd242b385b6ed4b8904976d5da0893e31df8b3480cb6"}, - {file = "charset_normalizer-3.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c75ffc45f25324e68ab238cb4b5c0a38cd1c3d7f1fb1f72b5541de469e2247db"}, - {file = "charset_normalizer-3.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:db72b07027db150f468fbada4d85b3b2729a3db39178abf5c543b784c1254539"}, - {file = "charset_normalizer-3.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:62595ab75873d50d57323a91dd03e6966eb79c41fa834b7a1661ed043b2d404d"}, - {file = "charset_normalizer-3.0.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ff6f3db31555657f3163b15a6b7c6938d08df7adbfc9dd13d9d19edad678f1e8"}, - {file = "charset_normalizer-3.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:772b87914ff1152b92a197ef4ea40efe27a378606c39446ded52c8f80f79702e"}, - {file = "charset_normalizer-3.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70990b9c51340e4044cfc394a81f614f3f90d41397104d226f21e66de668730d"}, - {file = "charset_normalizer-3.0.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:292d5e8ba896bbfd6334b096e34bffb56161c81408d6d036a7dfa6929cff8783"}, - {file = "charset_normalizer-3.0.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:2edb64ee7bf1ed524a1da60cdcd2e1f6e2b4f66ef7c077680739f1641f62f555"}, - {file = "charset_normalizer-3.0.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:31a9ddf4718d10ae04d9b18801bd776693487cbb57d74cc3458a7673f6f34639"}, - {file = "charset_normalizer-3.0.1-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:44ba614de5361b3e5278e1241fda3dc1838deed864b50a10d7ce92983797fa76"}, - {file = "charset_normalizer-3.0.1-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:12db3b2c533c23ab812c2b25934f60383361f8a376ae272665f8e48b88e8e1c6"}, - {file = "charset_normalizer-3.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c512accbd6ff0270939b9ac214b84fb5ada5f0409c44298361b2f5e13f9aed9e"}, - {file = "charset_normalizer-3.0.1-cp310-cp310-win32.whl", hash = "sha256:502218f52498a36d6bf5ea77081844017bf7982cdbe521ad85e64cabee1b608b"}, - {file = "charset_normalizer-3.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:601f36512f9e28f029d9481bdaf8e89e5148ac5d89cffd3b05cd533eeb423b59"}, - {file = "charset_normalizer-3.0.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:0298eafff88c99982a4cf66ba2efa1128e4ddaca0b05eec4c456bbc7db691d8d"}, - {file = "charset_normalizer-3.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a8d0fc946c784ff7f7c3742310cc8a57c5c6dc31631269876a88b809dbeff3d3"}, - {file = "charset_normalizer-3.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:87701167f2a5c930b403e9756fab1d31d4d4da52856143b609e30a1ce7160f3c"}, - {file = "charset_normalizer-3.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:14e76c0f23218b8f46c4d87018ca2e441535aed3632ca134b10239dfb6dadd6b"}, - {file = "charset_normalizer-3.0.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0c0a590235ccd933d9892c627dec5bc7511ce6ad6c1011fdf5b11363022746c1"}, - {file = "charset_normalizer-3.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8c7fe7afa480e3e82eed58e0ca89f751cd14d767638e2550c77a92a9e749c317"}, - {file = "charset_normalizer-3.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:79909e27e8e4fcc9db4addea88aa63f6423ebb171db091fb4373e3312cb6d603"}, - {file = "charset_normalizer-3.0.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8ac7b6a045b814cf0c47f3623d21ebd88b3e8cf216a14790b455ea7ff0135d18"}, - {file = "charset_normalizer-3.0.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:72966d1b297c741541ca8cf1223ff262a6febe52481af742036a0b296e35fa5a"}, - {file = "charset_normalizer-3.0.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:f9d0c5c045a3ca9bedfc35dca8526798eb91a07aa7a2c0fee134c6c6f321cbd7"}, - {file = "charset_normalizer-3.0.1-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:5995f0164fa7df59db4746112fec3f49c461dd6b31b841873443bdb077c13cfc"}, - {file = "charset_normalizer-3.0.1-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:4a8fcf28c05c1f6d7e177a9a46a1c52798bfe2ad80681d275b10dcf317deaf0b"}, - {file = "charset_normalizer-3.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:761e8904c07ad053d285670f36dd94e1b6ab7f16ce62b9805c475b7aa1cffde6"}, - {file = "charset_normalizer-3.0.1-cp311-cp311-win32.whl", hash = "sha256:71140351489970dfe5e60fc621ada3e0f41104a5eddaca47a7acb3c1b851d6d3"}, - {file = "charset_normalizer-3.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:9ab77acb98eba3fd2a85cd160851816bfce6871d944d885febf012713f06659c"}, - {file = "charset_normalizer-3.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:84c3990934bae40ea69a82034912ffe5a62c60bbf6ec5bc9691419641d7d5c9a"}, - {file = "charset_normalizer-3.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:74292fc76c905c0ef095fe11e188a32ebd03bc38f3f3e9bcb85e4e6db177b7ea"}, - {file = "charset_normalizer-3.0.1-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c95a03c79bbe30eec3ec2b7f076074f4281526724c8685a42872974ef4d36b72"}, - {file = "charset_normalizer-3.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f4c39b0e3eac288fedc2b43055cfc2ca7a60362d0e5e87a637beac5d801ef478"}, - {file = "charset_normalizer-3.0.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:df2c707231459e8a4028eabcd3cfc827befd635b3ef72eada84ab13b52e1574d"}, - {file = "charset_normalizer-3.0.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:93ad6d87ac18e2a90b0fe89df7c65263b9a99a0eb98f0a3d2e079f12a0735837"}, - {file = "charset_normalizer-3.0.1-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:59e5686dd847347e55dffcc191a96622f016bc0ad89105e24c14e0d6305acbc6"}, - {file = "charset_normalizer-3.0.1-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:cd6056167405314a4dc3c173943f11249fa0f1b204f8b51ed4bde1a9cd1834dc"}, - {file = "charset_normalizer-3.0.1-cp36-cp36m-musllinux_1_1_ppc64le.whl", hash = "sha256:083c8d17153ecb403e5e1eb76a7ef4babfc2c48d58899c98fcaa04833e7a2f9a"}, - {file = "charset_normalizer-3.0.1-cp36-cp36m-musllinux_1_1_s390x.whl", hash = "sha256:f5057856d21e7586765171eac8b9fc3f7d44ef39425f85dbcccb13b3ebea806c"}, - {file = "charset_normalizer-3.0.1-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:7eb33a30d75562222b64f569c642ff3dc6689e09adda43a082208397f016c39a"}, - {file = "charset_normalizer-3.0.1-cp36-cp36m-win32.whl", hash = "sha256:95dea361dd73757c6f1c0a1480ac499952c16ac83f7f5f4f84f0658a01b8ef41"}, - {file = "charset_normalizer-3.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:eaa379fcd227ca235d04152ca6704c7cb55564116f8bc52545ff357628e10602"}, - {file = "charset_normalizer-3.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:3e45867f1f2ab0711d60c6c71746ac53537f1684baa699f4f668d4c6f6ce8e14"}, - {file = "charset_normalizer-3.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cadaeaba78750d58d3cc6ac4d1fd867da6fc73c88156b7a3212a3cd4819d679d"}, - {file = "charset_normalizer-3.0.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:911d8a40b2bef5b8bbae2e36a0b103f142ac53557ab421dc16ac4aafee6f53dc"}, - {file = "charset_normalizer-3.0.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:503e65837c71b875ecdd733877d852adbc465bd82c768a067badd953bf1bc5a3"}, - {file = "charset_normalizer-3.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a60332922359f920193b1d4826953c507a877b523b2395ad7bc716ddd386d866"}, - {file = "charset_normalizer-3.0.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:16a8663d6e281208d78806dbe14ee9903715361cf81f6d4309944e4d1e59ac5b"}, - {file = "charset_normalizer-3.0.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:a16418ecf1329f71df119e8a65f3aa68004a3f9383821edcb20f0702934d8087"}, - {file = "charset_normalizer-3.0.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:9d9153257a3f70d5f69edf2325357251ed20f772b12e593f3b3377b5f78e7ef8"}, - {file = "charset_normalizer-3.0.1-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:02a51034802cbf38db3f89c66fb5d2ec57e6fe7ef2f4a44d070a593c3688667b"}, - {file = "charset_normalizer-3.0.1-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:2e396d70bc4ef5325b72b593a72c8979999aa52fb8bcf03f701c1b03e1166918"}, - {file = "charset_normalizer-3.0.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:11b53acf2411c3b09e6af37e4b9005cba376c872503c8f28218c7243582df45d"}, - {file = "charset_normalizer-3.0.1-cp37-cp37m-win32.whl", hash = "sha256:0bf2dae5291758b6f84cf923bfaa285632816007db0330002fa1de38bfcb7154"}, - {file = "charset_normalizer-3.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:2c03cc56021a4bd59be889c2b9257dae13bf55041a3372d3295416f86b295fb5"}, - {file = "charset_normalizer-3.0.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:024e606be3ed92216e2b6952ed859d86b4cfa52cd5bc5f050e7dc28f9b43ec42"}, - {file = "charset_normalizer-3.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:4b0d02d7102dd0f997580b51edc4cebcf2ab6397a7edf89f1c73b586c614272c"}, - {file = "charset_normalizer-3.0.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:358a7c4cb8ba9b46c453b1dd8d9e431452d5249072e4f56cfda3149f6ab1405e"}, - {file = "charset_normalizer-3.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:81d6741ab457d14fdedc215516665050f3822d3e56508921cc7239f8c8e66a58"}, - {file = "charset_normalizer-3.0.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8b8af03d2e37866d023ad0ddea594edefc31e827fee64f8de5611a1dbc373174"}, - {file = "charset_normalizer-3.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9cf4e8ad252f7c38dd1f676b46514f92dc0ebeb0db5552f5f403509705e24753"}, - {file = "charset_normalizer-3.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e696f0dd336161fca9adbb846875d40752e6eba585843c768935ba5c9960722b"}, - {file = "charset_normalizer-3.0.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c22d3fe05ce11d3671297dc8973267daa0f938b93ec716e12e0f6dee81591dc1"}, - {file = "charset_normalizer-3.0.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:109487860ef6a328f3eec66f2bf78b0b72400280d8f8ea05f69c51644ba6521a"}, - {file = "charset_normalizer-3.0.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:37f8febc8ec50c14f3ec9637505f28e58d4f66752207ea177c1d67df25da5aed"}, - {file = "charset_normalizer-3.0.1-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:f97e83fa6c25693c7a35de154681fcc257c1c41b38beb0304b9c4d2d9e164479"}, - {file = "charset_normalizer-3.0.1-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:a152f5f33d64a6be73f1d30c9cc82dfc73cec6477ec268e7c6e4c7d23c2d2291"}, - {file = "charset_normalizer-3.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:39049da0ffb96c8cbb65cbf5c5f3ca3168990adf3551bd1dee10c48fce8ae820"}, - {file = "charset_normalizer-3.0.1-cp38-cp38-win32.whl", hash = "sha256:4457ea6774b5611f4bed5eaa5df55f70abde42364d498c5134b7ef4c6958e20e"}, - {file = "charset_normalizer-3.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:e62164b50f84e20601c1ff8eb55620d2ad25fb81b59e3cd776a1902527a788af"}, - {file = "charset_normalizer-3.0.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:8eade758719add78ec36dc13201483f8e9b5d940329285edcd5f70c0a9edbd7f"}, - {file = "charset_normalizer-3.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8499ca8f4502af841f68135133d8258f7b32a53a1d594aa98cc52013fff55678"}, - {file = "charset_normalizer-3.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3fc1c4a2ffd64890aebdb3f97e1278b0cc72579a08ca4de8cd2c04799a3a22be"}, - {file = "charset_normalizer-3.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:00d3ffdaafe92a5dc603cb9bd5111aaa36dfa187c8285c543be562e61b755f6b"}, - {file = "charset_normalizer-3.0.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c2ac1b08635a8cd4e0cbeaf6f5e922085908d48eb05d44c5ae9eabab148512ca"}, - {file = "charset_normalizer-3.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f6f45710b4459401609ebebdbcfb34515da4fc2aa886f95107f556ac69a9147e"}, - {file = "charset_normalizer-3.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ae1de54a77dc0d6d5fcf623290af4266412a7c4be0b1ff7444394f03f5c54e3"}, - {file = "charset_normalizer-3.0.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3b590df687e3c5ee0deef9fc8c547d81986d9a1b56073d82de008744452d6541"}, - {file = "charset_normalizer-3.0.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ab5de034a886f616a5668aa5d098af2b5385ed70142090e2a31bcbd0af0fdb3d"}, - {file = "charset_normalizer-3.0.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9cb3032517f1627cc012dbc80a8ec976ae76d93ea2b5feaa9d2a5b8882597579"}, - {file = "charset_normalizer-3.0.1-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:608862a7bf6957f2333fc54ab4399e405baad0163dc9f8d99cb236816db169d4"}, - {file = "charset_normalizer-3.0.1-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:0f438ae3532723fb6ead77e7c604be7c8374094ef4ee2c5e03a3a17f1fca256c"}, - {file = "charset_normalizer-3.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:356541bf4381fa35856dafa6a965916e54bed415ad8a24ee6de6e37deccf2786"}, - {file = "charset_normalizer-3.0.1-cp39-cp39-win32.whl", hash = "sha256:39cf9ed17fe3b1bc81f33c9ceb6ce67683ee7526e65fde1447c772afc54a1bb8"}, - {file = "charset_normalizer-3.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:0a11e971ed097d24c534c037d298ad32c6ce81a45736d31e0ff0ad37ab437d59"}, - {file = "charset_normalizer-3.0.1-py3-none-any.whl", hash = "sha256:7e189e2e1d3ed2f4aebabd2d5b0f931e883676e51c7624826e0a4e5fe8a0bf24"}, + {file = "charset-normalizer-3.1.0.tar.gz", hash = "sha256:34e0a2f9c370eb95597aae63bf85eb5e96826d81e3dcf88b8886012906f509b5"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:e0ac8959c929593fee38da1c2b64ee9778733cdf03c482c9ff1d508b6b593b2b"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d7fc3fca01da18fbabe4625d64bb612b533533ed10045a2ac3dd194bfa656b60"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:04eefcee095f58eaabe6dc3cc2262f3bcd776d2c67005880894f447b3f2cb9c1"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:20064ead0717cf9a73a6d1e779b23d149b53daf971169289ed2ed43a71e8d3b0"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1435ae15108b1cb6fffbcea2af3d468683b7afed0169ad718451f8db5d1aff6f"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c84132a54c750fda57729d1e2599bb598f5fa0344085dbde5003ba429a4798c0"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75f2568b4189dda1c567339b48cba4ac7384accb9c2a7ed655cd86b04055c795"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:11d3bcb7be35e7b1bba2c23beedac81ee893ac9871d0ba79effc7fc01167db6c"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:891cf9b48776b5c61c700b55a598621fdb7b1e301a550365571e9624f270c203"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:5f008525e02908b20e04707a4f704cd286d94718f48bb33edddc7d7b584dddc1"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:b06f0d3bf045158d2fb8837c5785fe9ff9b8c93358be64461a1089f5da983137"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:49919f8400b5e49e961f320c735388ee686a62327e773fa5b3ce6721f7e785ce"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:22908891a380d50738e1f978667536f6c6b526a2064156203d418f4856d6e86a"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-win32.whl", hash = "sha256:12d1a39aa6b8c6f6248bb54550efcc1c38ce0d8096a146638fd4738e42284448"}, + {file = "charset_normalizer-3.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:65ed923f84a6844de5fd29726b888e58c62820e0769b76565480e1fdc3d062f8"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9a3267620866c9d17b959a84dd0bd2d45719b817245e49371ead79ed4f710d19"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6734e606355834f13445b6adc38b53c0fd45f1a56a9ba06c2058f86893ae8017"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f8303414c7b03f794347ad062c0516cee0e15f7a612abd0ce1e25caf6ceb47df"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aaf53a6cebad0eae578f062c7d462155eada9c172bd8c4d250b8c1d8eb7f916a"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3dc5b6a8ecfdc5748a7e429782598e4f17ef378e3e272eeb1340ea57c9109f41"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e1b25e3ad6c909f398df8921780d6a3d120d8c09466720226fc621605b6f92b1"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0ca564606d2caafb0abe6d1b5311c2649e8071eb241b2d64e75a0d0065107e62"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b82fab78e0b1329e183a65260581de4375f619167478dddab510c6c6fb04d9b6"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:bd7163182133c0c7701b25e604cf1611c0d87712e56e88e7ee5d72deab3e76b5"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:11d117e6c63e8f495412d37e7dc2e2fff09c34b2d09dbe2bee3c6229577818be"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:cf6511efa4801b9b38dc5546d7547d5b5c6ef4b081c60b23e4d941d0eba9cbeb"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:abc1185d79f47c0a7aaf7e2412a0eb2c03b724581139193d2d82b3ad8cbb00ac"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:cb7b2ab0188829593b9de646545175547a70d9a6e2b63bf2cd87a0a391599324"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-win32.whl", hash = "sha256:c36bcbc0d5174a80d6cccf43a0ecaca44e81d25be4b7f90f0ed7bcfbb5a00909"}, + {file = "charset_normalizer-3.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:cca4def576f47a09a943666b8f829606bcb17e2bc2d5911a46c8f8da45f56755"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0c95f12b74681e9ae127728f7e5409cbbef9cd914d5896ef238cc779b8152373"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fca62a8301b605b954ad2e9c3666f9d97f63872aa4efcae5492baca2056b74ab"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ac0aa6cd53ab9a31d397f8303f92c42f534693528fafbdb997c82bae6e477ad9"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c3af8e0f07399d3176b179f2e2634c3ce9c1301379a6b8c9c9aeecd481da494f"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a5fc78f9e3f501a1614a98f7c54d3969f3ad9bba8ba3d9b438c3bc5d047dd28"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:628c985afb2c7d27a4800bfb609e03985aaecb42f955049957814e0491d4006d"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:74db0052d985cf37fa111828d0dd230776ac99c740e1a758ad99094be4f1803d"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:1e8fcdd8f672a1c4fc8d0bd3a2b576b152d2a349782d1eb0f6b8e52e9954731d"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:04afa6387e2b282cf78ff3dbce20f0cc071c12dc8f685bd40960cc68644cfea6"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:dd5653e67b149503c68c4018bf07e42eeed6b4e956b24c00ccdf93ac79cdff84"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d2686f91611f9e17f4548dbf050e75b079bbc2a82be565832bc8ea9047b61c8c"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-win32.whl", hash = "sha256:4155b51ae05ed47199dc5b2a4e62abccb274cee6b01da5b895099b61b1982974"}, + {file = "charset_normalizer-3.1.0-cp37-cp37m-win_amd64.whl", hash = "sha256:322102cdf1ab682ecc7d9b1c5eed4ec59657a65e1c146a0da342b78f4112db23"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:e633940f28c1e913615fd624fcdd72fdba807bf53ea6925d6a588e84e1151531"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:3a06f32c9634a8705f4ca9946d667609f52cf130d5548881401f1eb2c39b1e2c"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7381c66e0561c5757ffe616af869b916c8b4e42b367ab29fedc98481d1e74e14"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3573d376454d956553c356df45bb824262c397c6e26ce43e8203c4c540ee0acb"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e89df2958e5159b811af9ff0f92614dabf4ff617c03a4c1c6ff53bf1c399e0e1"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:78cacd03e79d009d95635e7d6ff12c21eb89b894c354bd2b2ed0b4763373693b"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:de5695a6f1d8340b12a5d6d4484290ee74d61e467c39ff03b39e30df62cf83a0"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1c60b9c202d00052183c9be85e5eaf18a4ada0a47d188a83c8f5c5b23252f649"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:f645caaf0008bacf349875a974220f1f1da349c5dbe7c4ec93048cdc785a3326"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:ea9f9c6034ea2d93d9147818f17c2a0860d41b71c38b9ce4d55f21b6f9165a11"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:80d1543d58bd3d6c271b66abf454d437a438dff01c3e62fdbcd68f2a11310d4b"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:73dc03a6a7e30b7edc5b01b601e53e7fc924b04e1835e8e407c12c037e81adbd"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6f5c2e7bc8a4bf7c426599765b1bd33217ec84023033672c1e9a8b35eaeaaaf8"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-win32.whl", hash = "sha256:12a2b561af122e3d94cdb97fe6fb2bb2b82cef0cdca131646fdb940a1eda04f0"}, + {file = "charset_normalizer-3.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:3160a0fd9754aab7d47f95a6b63ab355388d890163eb03b2d2b87ab0a30cfa59"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:38e812a197bf8e71a59fe55b757a84c1f946d0ac114acafaafaf21667a7e169e"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6baf0baf0d5d265fa7944feb9f7451cc316bfe30e8df1a61b1bb08577c554f31"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8f25e17ab3039b05f762b0a55ae0b3632b2e073d9c8fc88e89aca31a6198e88f"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3747443b6a904001473370d7810aa19c3a180ccd52a7157aacc264a5ac79265e"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b116502087ce8a6b7a5f1814568ccbd0e9f6cfd99948aa59b0e241dc57cf739f"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d16fd5252f883eb074ca55cb622bc0bee49b979ae4e8639fff6ca3ff44f9f854"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21fa558996782fc226b529fdd2ed7866c2c6ec91cee82735c98a197fae39f706"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6f6c7a8a57e9405cad7485f4c9d3172ae486cfef1344b5ddd8e5239582d7355e"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ac3775e3311661d4adace3697a52ac0bab17edd166087d493b52d4f4f553f9f0"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:10c93628d7497c81686e8e5e557aafa78f230cd9e77dd0c40032ef90c18f2230"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:6f4f4668e1831850ebcc2fd0b1cd11721947b6dc7c00bf1c6bd3c929ae14f2c7"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:0be65ccf618c1e7ac9b849c315cc2e8a8751d9cfdaa43027d4f6624bd587ab7e"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:53d0a3fa5f8af98a1e261de6a3943ca631c526635eb5817a87a59d9a57ebf48f"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-win32.whl", hash = "sha256:a04f86f41a8916fe45ac5024ec477f41f886b3c435da2d4e3d2709b22ab02af1"}, + {file = "charset_normalizer-3.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:830d2948a5ec37c386d3170c483063798d7879037492540f10a475e3fd6f244b"}, + {file = "charset_normalizer-3.1.0-py3-none-any.whl", hash = "sha256:3d9098b479e78c85080c98e1e35ff40b4a31d8953102bb0fd7d1b6f8a2111a3d"}, ] [[package]] @@ -217,26 +201,26 @@ files = [ [[package]] name = "docutils" -version = "0.17.1" +version = "0.18.1" description = "Docutils -- Python Documentation Utilities" category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" files = [ - {file = "docutils-0.17.1-py2.py3-none-any.whl", hash = "sha256:cf316c8370a737a022b72b56874f6602acf974a37a9fba42ec2876387549fc61"}, - {file = "docutils-0.17.1.tar.gz", hash = "sha256:686577d2e4c32380bb50cbb22f575ed742d58168cee37e99117a854bcd88f125"}, + {file = "docutils-0.18.1-py2.py3-none-any.whl", hash = "sha256:23010f129180089fbcd3bc08cfefccb3b890b0050e1ca00c867036e9d161b98c"}, + {file = "docutils-0.18.1.tar.gz", hash = "sha256:679987caf361a7539d76e584cbeddc311e3aee937877c87346f31debc63e9d06"}, ] [[package]] name = "exceptiongroup" -version = "1.1.0" +version = "1.1.1" description = "Backport of PEP 654 (exception groups)" category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "exceptiongroup-1.1.0-py3-none-any.whl", hash = "sha256:327cbda3da756e2de031a3107b81ab7b3770a602c4d16ca618298c526f4bec1e"}, - {file = "exceptiongroup-1.1.0.tar.gz", hash = "sha256:bcb67d800a4497e1b404c2dd44fca47d3b7a5e5433dbab67f96c1a685cdfdf23"}, + {file = "exceptiongroup-1.1.1-py3-none-any.whl", hash = "sha256:232c37c63e4f682982c8b6459f33a8981039e5fb8756b2074364e5055c498c9e"}, + {file = "exceptiongroup-1.1.1.tar.gz", hash = "sha256:d484c3090ba2889ae2928419117447a14daf3c1231d5e30d0aae34f354f01785"}, ] [package.extras] @@ -244,19 +228,19 @@ test = ["pytest (>=6)"] [[package]] name = "filelock" -version = "3.9.0" +version = "3.10.3" description = "A platform independent file lock." category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "filelock-3.9.0-py3-none-any.whl", hash = "sha256:f58d535af89bb9ad5cd4df046f741f8553a418c01a7856bf0d173bbc9f6bd16d"}, - {file = "filelock-3.9.0.tar.gz", hash = "sha256:7b319f24340b51f55a2bf7a12ac0755a9b03e718311dac567a0f4f7fabd2f5de"}, + {file = "filelock-3.10.3-py3-none-any.whl", hash = "sha256:99d6282f732410d44242ca02aa49835cf5473e2dd4d6734a2a785c8889dc191e"}, + {file = "filelock-3.10.3.tar.gz", hash = "sha256:a26bfa34d26293e04886dff13fa8dd0c8c6e1a786b723c689755fe8939297410"}, ] [package.extras] -docs = ["furo (>=2022.12.7)", "sphinx (>=5.3)", "sphinx-autodoc-typehints (>=1.19.5)"] -testing = ["covdefaults (>=2.2.2)", "coverage (>=7.0.1)", "pytest (>=7.2)", "pytest-cov (>=4)", "pytest-timeout (>=2.1)"] +docs = ["furo (>=2022.12.7)", "sphinx (>=6.1.3)", "sphinx-autodoc-typehints (>=1.22,!=1.23.4)"] +testing = ["covdefaults (>=2.3)", "coverage (>=7.2.2)", "pytest (>=7.2.2)", "pytest-cov (>=4)", "pytest-timeout (>=2.1)"] [[package]] name = "gdspy" @@ -274,36 +258,45 @@ numpy = "*" [[package]] name = "gdstk" -version = "0.9.35" +version = "0.9.37" description = "Python module for creation and manipulation of GDSII files." category = "main" optional = true python-versions = "*" files = [ - {file = "gdstk-0.9.35-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:997a77833ca00027eabf6cc6ac47e1f669d774f1d1bb2a55f0c4168583c3d575"}, - {file = "gdstk-0.9.35-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7f8ad42f494fe7e8fa20d01268400455772d8bd22acb6165f6de736b271801ff"}, - {file = "gdstk-0.9.35-cp310-cp310-win_amd64.whl", hash = "sha256:ae36032632f3032544aa80195cb4b5cb49d8fb5ef8791059121873fb04e40c8f"}, - {file = "gdstk-0.9.35-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a0609082e1fdd0fc9bc8c66efba083086b645d2e9fb19d0631389a0fd6293ce6"}, - {file = "gdstk-0.9.35-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ce0435aece4c781794bf2aaa9c2e1ee0074043a3fa6e5fc20b97ee5c4ac52e4c"}, - {file = "gdstk-0.9.35-cp311-cp311-win_amd64.whl", hash = "sha256:ce8526ef2f7ec514ad4f72535eb045a925fa9fede9ed35b4f1a72eea1831cfce"}, - {file = "gdstk-0.9.35-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:0e16cb99826633a480150fd978acea00b87bfaf037d684fac6ed17a4a1934b87"}, - {file = "gdstk-0.9.35-cp36-cp36m-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e66406fb246faf043a42f24dd04c64b57a4d1d4ea64ca8d3723924a3ff751f97"}, - {file = "gdstk-0.9.35-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:edffe8a1a96a78639d82ebda493623fad20b5dc152d12d531ed8bf750601f6dc"}, - {file = "gdstk-0.9.35-cp37-cp37m-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9ab1f229e1e7d770c6879464db717acf654aae253641f43eb0c1af746013acf8"}, - {file = "gdstk-0.9.35-cp37-cp37m-win_amd64.whl", hash = "sha256:848a12da526b7d7a9ac49fe266f4f4637e563753702256c67794c6d65994c77b"}, - {file = "gdstk-0.9.35-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:e37c7cfd89f135e2da4570a9f3aaa2d4fa04ad5a448fa02c9bc74e3846024a42"}, - {file = "gdstk-0.9.35-cp38-cp38-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7c2f7c2249c735b62356e5821f806591327a03fc234a35882c26bce4ec8cb03e"}, - {file = "gdstk-0.9.35-cp38-cp38-win_amd64.whl", hash = "sha256:2813837d200634e6a176b72e36fa22911de77c74409a9e5747b31d2c926e736d"}, - {file = "gdstk-0.9.35-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6ef6a04b27c6488ef1feef59203b49c33403ef01d9bb1a819c42855dd6191e39"}, - {file = "gdstk-0.9.35-cp39-cp39-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4fd385a081ecbfb1fc8f9ce0a5a2a9fd60f98fc407b605870d7468ff4a964c0e"}, - {file = "gdstk-0.9.35-cp39-cp39-win_amd64.whl", hash = "sha256:6b823c8c8ba72d62cf3f80b3958657f64b70d372d830257e7d4a353eef703c4f"}, - {file = "gdstk-0.9.35-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:de7d12603b637672c6e6dcb15666ce71b07cddca333d34220f845bfdc771aad3"}, - {file = "gdstk-0.9.35-pp37-pypy37_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f1d211ded903bfcec2fd98de31acbb2dce8a6adae0571c1f634191d66e565045"}, - {file = "gdstk-0.9.35-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:b4ce11d489e694a43cc6ffa8f3590c82f498e8e2e157c42f058a9387e7b3a8c8"}, - {file = "gdstk-0.9.35-pp38-pypy38_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d7aa21915d0a542d29c9edc6de8d7509be11c748d2a73f73b060d3932f254456"}, - {file = "gdstk-0.9.35-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:9b52ee46d1e28998765b070b4d82a6a1c1909689f23405d620cb78b4cba0d3b2"}, - {file = "gdstk-0.9.35-pp39-pypy39_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:11292bf8e767def6b6c6ec2efc22bcfb01547efbe3b7b3720bfeaaac05e14e02"}, - {file = "gdstk-0.9.35.tar.gz", hash = "sha256:8568b9d5cd81530e5325547aa32211154ed144c2ae1a83fe86f6f48d3b5f97e5"}, + {file = "gdstk-0.9.37-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ae2424113a1434d195196340ab28a691de88c59c2f14e280dba744542eb90143"}, + {file = "gdstk-0.9.37-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b51b24966a128b3b72698e6a21a76dc2ad33fcb10034dec303964567578b25db"}, + {file = "gdstk-0.9.37-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8022295a9ee7480d3e2bae5827f979990dc35c62f1442d1e88ed5830ba90ce47"}, + {file = "gdstk-0.9.37-cp310-cp310-win_amd64.whl", hash = "sha256:52405ad6eea1b9f0dd0580d21055e953dc5b2a2303be62787ec0649a27e9d83c"}, + {file = "gdstk-0.9.37-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:7b8c4a8fb4e992d05a7178a1ab50f9ef6329c8e1e76c4f507b61c263b31baaf0"}, + {file = "gdstk-0.9.37-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6069ada42f44a78ef3d13ff33a586ad1fb013e98f92730a7b6c15d731d399570"}, + {file = "gdstk-0.9.37-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:23aec774897483667a21dfb6310ac417b0ec5baa49591a45a15df651ab2ceb9e"}, + {file = "gdstk-0.9.37-cp311-cp311-win_amd64.whl", hash = "sha256:e29b0f9368f8942421c08cde63ea379e738e2d1c0dd06ea45286efbc9bd92cda"}, + {file = "gdstk-0.9.37-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:481aa05b407cf8f60735d58c40a2df43da0bfee8093e9897a9552f7e5ce411d2"}, + {file = "gdstk-0.9.37-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:36db562eb25db40776948f27a7018967bb666e7517aebf2c9ddf60625f59fbec"}, + {file = "gdstk-0.9.37-cp36-cp36m-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ef9e2f72c5175e573a7b83fb3f45e47c8451caf784a14d7b414cdcdef10d9a0d"}, + {file = "gdstk-0.9.37-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:400d16d6d2339885d59710510f9736999fcc35031a23027a4b923d81f74cc7ff"}, + {file = "gdstk-0.9.37-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3fd5fe8ba75cbf902e2f4fe896bb275c31c32a377356dd58f14082448a2507c7"}, + {file = "gdstk-0.9.37-cp37-cp37m-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4f5d702611ff507da0993d856f0c010758462e83fb2c366e0bd3ae1eadb87a76"}, + {file = "gdstk-0.9.37-cp37-cp37m-win_amd64.whl", hash = "sha256:156312cddb137fcd0dfdba7f321d6478df0a413a093878588eb53471344f290c"}, + {file = "gdstk-0.9.37-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:9786351c58c34111af973eb10a87296fec7f3928b8f7eefa1140c62fbc338480"}, + {file = "gdstk-0.9.37-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9a116c2e8806eed0e21068af5e84b4cee251635382f87180014c28fd2d818c72"}, + {file = "gdstk-0.9.37-cp38-cp38-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:907c626acf9d4e349ebab775784f916c48345a8c87921dd964b419d0d491cc5b"}, + {file = "gdstk-0.9.37-cp38-cp38-win_amd64.whl", hash = "sha256:d88748d357197fcb400a6006ae82b9456659e3106eb5c039a8111a7690f04c0a"}, + {file = "gdstk-0.9.37-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:83d76fc350bb4d2ddeffd343344751944d54ecfe2c081072bdbf7439a3e18f53"}, + {file = "gdstk-0.9.37-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:78974a21a268f6797beee658b4b754c0a82008a7674458aa59165b4ab3065f86"}, + {file = "gdstk-0.9.37-cp39-cp39-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ca85ffda0636a0c5a16c65f6f41776861e7a987b14dbdb9b1e53fddd16252dfd"}, + {file = "gdstk-0.9.37-cp39-cp39-win_amd64.whl", hash = "sha256:c6968054978d2c1a17198f842edf8aaeb0baad796addcfa463be19217086061b"}, + {file = "gdstk-0.9.37-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:3cb6ee2132e7617c2c335e19dae1fc275ca628514576b3fcb0cb61d50ef93edf"}, + {file = "gdstk-0.9.37-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fdcc6992952a327bcd4cda52a3596dc9a88417bad3942e174438572e5bac0ec6"}, + {file = "gdstk-0.9.37-pp37-pypy37_pp73-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:cc5ffabc2aec6ad6706a260196b58eeaefeba0ac614c4eca39f9abfcecc569d2"}, + {file = "gdstk-0.9.37-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:7d54e2271b2b02467428cc26a43307380d3dd20196033f2b8f3a1eb96425e24a"}, + {file = "gdstk-0.9.37-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d4baa34e1d4cb6f4fa4a639cbc1133879ba4eb903ee659a2040dd0596dee5f8e"}, + {file = "gdstk-0.9.37-pp38-pypy38_pp73-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d1fddde2159bc6f5844be7e200ddf776fd4510ee7f1767f189bbed5d7533da0f"}, + {file = "gdstk-0.9.37-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:4f3fc607f64598d4a3eba978b06a8a9c11971978dbc2189ba0bea9510d8566f7"}, + {file = "gdstk-0.9.37-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6063fbcbba1e1d5060f5b766efc94e75526e0a57419fc7fc1d616cb6437877df"}, + {file = "gdstk-0.9.37-pp39-pypy39_pp73-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1985caae9cf6cb49d1686fe921514e445d736a95376af8534c207703fda465e4"}, + {file = "gdstk-0.9.37.tar.gz", hash = "sha256:1a4a7cb364a8d4f4d11521d275d38cea75fd86354e8cade16d5f0d3c797c69b6"}, ] [package.dependencies] @@ -335,14 +328,14 @@ files = [ [[package]] name = "importlib-metadata" -version = "6.0.0" +version = "6.1.0" description = "Read metadata from Python packages" category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "importlib_metadata-6.0.0-py3-none-any.whl", hash = "sha256:7efb448ec9a5e313a57655d35aa54cd3e01b7e1fbcf72dce1bf06119420f5bad"}, - {file = "importlib_metadata-6.0.0.tar.gz", hash = "sha256:e354bedeb60efa6affdcc8ae121b73544a7aa74156d047311948f6d711cd378d"}, + {file = "importlib_metadata-6.1.0-py3-none-any.whl", hash = "sha256:ff80f3b5394912eb1b108fcfd444dc78b7f1f3e16b16188054bd01cb9cb86f09"}, + {file = "importlib_metadata-6.1.0.tar.gz", hash = "sha256:43ce9281e097583d758c2c708c4376371261a02c34682491a8e98352365aad20"}, ] [package.dependencies] @@ -367,19 +360,19 @@ files = [ [[package]] name = "isort" -version = "5.11.4" +version = "5.12.0" description = "A Python utility / library to sort Python imports." category = "dev" optional = false -python-versions = ">=3.7.0" +python-versions = ">=3.8.0" files = [ - {file = "isort-5.11.4-py3-none-any.whl", hash = "sha256:c033fd0edb91000a7f09527fe5c75321878f98322a77ddcc81adbd83724afb7b"}, - {file = "isort-5.11.4.tar.gz", hash = "sha256:6db30c5ded9815d813932c04c2f85a360bcdd35fed496f4d8f35495ef0a261b6"}, + {file = "isort-5.12.0-py3-none-any.whl", hash = "sha256:f84c2818376e66cf843d497486ea8fed8700b340f308f076c6fb1229dff318b6"}, + {file = "isort-5.12.0.tar.gz", hash = "sha256:8bef7dde241278824a6d83f44a544709b065191b95b6e50894bdc722fcba0504"}, ] [package.extras] -colors = ["colorama (>=0.4.3,<0.5.0)"] -pipfile-deprecated-finder = ["pipreqs", "requirementslib"] +colors = ["colorama (>=0.4.3)"] +pipfile-deprecated-finder = ["pip-shims (>=0.5.2)", "pipreqs", "requirementslib"] plugins = ["setuptools"] requirements-deprecated-finder = ["pip-api", "pipreqs"] @@ -449,24 +442,24 @@ files = [ [[package]] name = "markdown-it-py" -version = "2.1.0" +version = "2.2.0" description = "Python port of markdown-it. Markdown parsing, done right!" category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "markdown-it-py-2.1.0.tar.gz", hash = "sha256:cf7e59fed14b5ae17c0006eff14a2d9a00ed5f3a846148153899a0224e2c07da"}, - {file = "markdown_it_py-2.1.0-py3-none-any.whl", hash = "sha256:93de681e5c021a432c63147656fe21790bc01231e0cd2da73626f1aa3ac0fe27"}, + {file = "markdown-it-py-2.2.0.tar.gz", hash = "sha256:7c9a5e412688bc771c67432cbfebcdd686c93ce6484913dccf06cb5a0bea35a1"}, + {file = "markdown_it_py-2.2.0-py3-none-any.whl", hash = "sha256:5a35f8d1870171d9acc47b99612dc146129b631baf04970128b568f190d0cc30"}, ] [package.dependencies] mdurl = ">=0.1,<1.0" [package.extras] -benchmarking = ["psutil", "pytest", "pytest-benchmark (>=3.2,<4.0)"] -code-style = ["pre-commit (==2.6)"] -compare = ["commonmark (>=0.9.1,<0.10.0)", "markdown (>=3.3.6,<3.4.0)", "mistletoe (>=0.8.1,<0.9.0)", "mistune (>=2.0.2,<2.1.0)", "panflute (>=2.1.3,<2.2.0)"] -linkify = ["linkify-it-py (>=1.0,<2.0)"] +benchmarking = ["psutil", "pytest", "pytest-benchmark"] +code-style = ["pre-commit (>=3.0,<4.0)"] +compare = ["commonmark (>=0.9,<1.0)", "markdown (>=3.4,<4.0)", "mistletoe (>=1.0,<2.0)", "mistune (>=2.0,<3.0)", "panflute (>=2.3,<3.0)"] +linkify = ["linkify-it-py (>=1,<3)"] plugins = ["mdit-py-plugins"] profiling = ["gprof2dot"] rtd = ["attrs", "myst-parser", "pyyaml", "sphinx", "sphinx-copybutton", "sphinx-design", "sphinx_book_theme"] @@ -546,14 +539,14 @@ files = [ [[package]] name = "mdit-py-plugins" -version = "0.3.3" +version = "0.3.5" description = "Collection of plugins for markdown-it-py" category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "mdit-py-plugins-0.3.3.tar.gz", hash = "sha256:5cfd7e7ac582a594e23ba6546a2f406e94e42eb33ae596d0734781261c251260"}, - {file = "mdit_py_plugins-0.3.3-py3-none-any.whl", hash = "sha256:36d08a29def19ec43acdcd8ba471d3ebab132e7879d442760d963f19913e04b9"}, + {file = "mdit-py-plugins-0.3.5.tar.gz", hash = "sha256:eee0adc7195e5827e17e02d2a258a2ba159944a0748f59c5099a4a27f78fcf6a"}, + {file = "mdit_py_plugins-0.3.5-py3-none-any.whl", hash = "sha256:ca9a0714ea59a24b2b044a1831f48d817dd0c817e84339f20e7889f392d77c4e"}, ] [package.dependencies] @@ -629,14 +622,14 @@ reports = ["lxml"] [[package]] name = "mypy-extensions" -version = "0.4.3" -description = "Experimental type system extensions for programs checked with the mypy typechecker." +version = "1.0.0" +description = "Type system extensions for programs checked with the mypy type checker." category = "dev" optional = false -python-versions = "*" +python-versions = ">=3.5" files = [ - {file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"}, - {file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"}, + {file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"}, + {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"}, ] [[package]] @@ -687,40 +680,40 @@ test = ["codecov (>=2.1)", "pytest (>=7.2)", "pytest-cov (>=4.0)"] [[package]] name = "numpy" -version = "1.24.1" +version = "1.24.2" description = "Fundamental package for array computing in Python" category = "main" optional = false python-versions = ">=3.8" files = [ - {file = "numpy-1.24.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:179a7ef0889ab769cc03573b6217f54c8bd8e16cef80aad369e1e8185f994cd7"}, - {file = "numpy-1.24.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:b09804ff570b907da323b3d762e74432fb07955701b17b08ff1b5ebaa8cfe6a9"}, - {file = "numpy-1.24.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f1b739841821968798947d3afcefd386fa56da0caf97722a5de53e07c4ccedc7"}, - {file = "numpy-1.24.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0e3463e6ac25313462e04aea3fb8a0a30fb906d5d300f58b3bc2c23da6a15398"}, - {file = "numpy-1.24.1-cp310-cp310-win32.whl", hash = "sha256:b31da69ed0c18be8b77bfce48d234e55d040793cebb25398e2a7d84199fbc7e2"}, - {file = "numpy-1.24.1-cp310-cp310-win_amd64.whl", hash = "sha256:b07b40f5fb4fa034120a5796288f24c1fe0e0580bbfff99897ba6267af42def2"}, - {file = "numpy-1.24.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:7094891dcf79ccc6bc2a1f30428fa5edb1e6fb955411ffff3401fb4ea93780a8"}, - {file = "numpy-1.24.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:28e418681372520c992805bb723e29d69d6b7aa411065f48216d8329d02ba032"}, - {file = "numpy-1.24.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e274f0f6c7efd0d577744f52032fdd24344f11c5ae668fe8d01aac0422611df1"}, - {file = "numpy-1.24.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0044f7d944ee882400890f9ae955220d29b33d809a038923d88e4e01d652acd9"}, - {file = "numpy-1.24.1-cp311-cp311-win32.whl", hash = "sha256:442feb5e5bada8408e8fcd43f3360b78683ff12a4444670a7d9e9824c1817d36"}, - {file = "numpy-1.24.1-cp311-cp311-win_amd64.whl", hash = "sha256:de92efa737875329b052982e37bd4371d52cabf469f83e7b8be9bb7752d67e51"}, - {file = "numpy-1.24.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b162ac10ca38850510caf8ea33f89edcb7b0bb0dfa5592d59909419986b72407"}, - {file = "numpy-1.24.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:26089487086f2648944f17adaa1a97ca6aee57f513ba5f1c0b7ebdabbe2b9954"}, - {file = "numpy-1.24.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:caf65a396c0d1f9809596be2e444e3bd4190d86d5c1ce21f5fc4be60a3bc5b36"}, - {file = "numpy-1.24.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b0677a52f5d896e84414761531947c7a330d1adc07c3a4372262f25d84af7bf7"}, - {file = "numpy-1.24.1-cp38-cp38-win32.whl", hash = "sha256:dae46bed2cb79a58d6496ff6d8da1e3b95ba09afeca2e277628171ca99b99db1"}, - {file = "numpy-1.24.1-cp38-cp38-win_amd64.whl", hash = "sha256:6ec0c021cd9fe732e5bab6401adea5a409214ca5592cd92a114f7067febcba0c"}, - {file = "numpy-1.24.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:28bc9750ae1f75264ee0f10561709b1462d450a4808cd97c013046073ae64ab6"}, - {file = "numpy-1.24.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:84e789a085aabef2f36c0515f45e459f02f570c4b4c4c108ac1179c34d475ed7"}, - {file = "numpy-1.24.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8e669fbdcdd1e945691079c2cae335f3e3a56554e06bbd45d7609a6cf568c700"}, - {file = "numpy-1.24.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ef85cf1f693c88c1fd229ccd1055570cb41cdf4875873b7728b6301f12cd05bf"}, - {file = "numpy-1.24.1-cp39-cp39-win32.whl", hash = "sha256:87a118968fba001b248aac90e502c0b13606721b1343cdaddbc6e552e8dfb56f"}, - {file = "numpy-1.24.1-cp39-cp39-win_amd64.whl", hash = "sha256:ddc7ab52b322eb1e40521eb422c4e0a20716c271a306860979d450decbb51b8e"}, - {file = "numpy-1.24.1-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:ed5fb71d79e771ec930566fae9c02626b939e37271ec285e9efaf1b5d4370e7d"}, - {file = "numpy-1.24.1-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ad2925567f43643f51255220424c23d204024ed428afc5aad0f86f3ffc080086"}, - {file = "numpy-1.24.1-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:cfa1161c6ac8f92dea03d625c2d0c05e084668f4a06568b77a25a89111621566"}, - {file = "numpy-1.24.1.tar.gz", hash = "sha256:2386da9a471cc00a1f47845e27d916d5ec5346ae9696e01a8a34760858fe9dd2"}, + {file = "numpy-1.24.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:eef70b4fc1e872ebddc38cddacc87c19a3709c0e3e5d20bf3954c147b1dd941d"}, + {file = "numpy-1.24.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e8d2859428712785e8a8b7d2b3ef0a1d1565892367b32f915c4a4df44d0e64f5"}, + {file = "numpy-1.24.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6524630f71631be2dabe0c541e7675db82651eb998496bbe16bc4f77f0772253"}, + {file = "numpy-1.24.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a51725a815a6188c662fb66fb32077709a9ca38053f0274640293a14fdd22978"}, + {file = "numpy-1.24.2-cp310-cp310-win32.whl", hash = "sha256:2620e8592136e073bd12ee4536149380695fbe9ebeae845b81237f986479ffc9"}, + {file = "numpy-1.24.2-cp310-cp310-win_amd64.whl", hash = "sha256:97cf27e51fa078078c649a51d7ade3c92d9e709ba2bfb97493007103c741f1d0"}, + {file = "numpy-1.24.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:7de8fdde0003f4294655aa5d5f0a89c26b9f22c0a58790c38fae1ed392d44a5a"}, + {file = "numpy-1.24.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4173bde9fa2a005c2c6e2ea8ac1618e2ed2c1c6ec8a7657237854d42094123a0"}, + {file = "numpy-1.24.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4cecaed30dc14123020f77b03601559fff3e6cd0c048f8b5289f4eeabb0eb281"}, + {file = "numpy-1.24.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9a23f8440561a633204a67fb44617ce2a299beecf3295f0d13c495518908e910"}, + {file = "numpy-1.24.2-cp311-cp311-win32.whl", hash = "sha256:e428c4fbfa085f947b536706a2fc349245d7baa8334f0c5723c56a10595f9b95"}, + {file = "numpy-1.24.2-cp311-cp311-win_amd64.whl", hash = "sha256:557d42778a6869c2162deb40ad82612645e21d79e11c1dc62c6e82a2220ffb04"}, + {file = "numpy-1.24.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d0a2db9d20117bf523dde15858398e7c0858aadca7c0f088ac0d6edd360e9ad2"}, + {file = "numpy-1.24.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:c72a6b2f4af1adfe193f7beb91ddf708ff867a3f977ef2ec53c0ffb8283ab9f5"}, + {file = "numpy-1.24.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c29e6bd0ec49a44d7690ecb623a8eac5ab8a923bce0bea6293953992edf3a76a"}, + {file = "numpy-1.24.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2eabd64ddb96a1239791da78fa5f4e1693ae2dadc82a76bc76a14cbb2b966e96"}, + {file = "numpy-1.24.2-cp38-cp38-win32.whl", hash = "sha256:e3ab5d32784e843fc0dd3ab6dcafc67ef806e6b6828dc6af2f689be0eb4d781d"}, + {file = "numpy-1.24.2-cp38-cp38-win_amd64.whl", hash = "sha256:76807b4063f0002c8532cfeac47a3068a69561e9c8715efdad3c642eb27c0756"}, + {file = "numpy-1.24.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:4199e7cfc307a778f72d293372736223e39ec9ac096ff0a2e64853b866a8e18a"}, + {file = "numpy-1.24.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:adbdce121896fd3a17a77ab0b0b5eedf05a9834a18699db6829a64e1dfccca7f"}, + {file = "numpy-1.24.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:889b2cc88b837d86eda1b17008ebeb679d82875022200c6e8e4ce6cf549b7acb"}, + {file = "numpy-1.24.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f64bb98ac59b3ea3bf74b02f13836eb2e24e48e0ab0145bbda646295769bd780"}, + {file = "numpy-1.24.2-cp39-cp39-win32.whl", hash = "sha256:63e45511ee4d9d976637d11e6c9864eae50e12dc9598f531c035265991910468"}, + {file = "numpy-1.24.2-cp39-cp39-win_amd64.whl", hash = "sha256:a77d3e1163a7770164404607b7ba3967fb49b24782a6ef85d9b5f54126cc39e5"}, + {file = "numpy-1.24.2-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:92011118955724465fb6853def593cf397b4a1367495e0b59a7e69d40c4eb71d"}, + {file = "numpy-1.24.2-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f9006288bcf4895917d02583cf3411f98631275bc67cce355a7f39f8c14338fa"}, + {file = "numpy-1.24.2-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:150947adbdfeceec4e5926d956a06865c1c690f2fd902efede4ca6fe2e657c3f"}, + {file = "numpy-1.24.2.tar.gz", hash = "sha256:003a9f530e880cb2cd177cba1af7220b9aa42def9c4afc2a2fc3ee6be7eb2b22"}, ] [[package]] @@ -737,19 +730,19 @@ files = [ [[package]] name = "platformdirs" -version = "2.6.2" +version = "3.1.1" description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "platformdirs-2.6.2-py3-none-any.whl", hash = "sha256:83c8f6d04389165de7c9b6f0c682439697887bca0aa2f1c87ef1826be3584490"}, - {file = "platformdirs-2.6.2.tar.gz", hash = "sha256:e1fea1fe471b9ff8332e229df3cb7de4f53eeea4998d3b6bfff542115e998bd2"}, + {file = "platformdirs-3.1.1-py3-none-any.whl", hash = "sha256:e5986afb596e4bb5bde29a79ac9061aa955b94fca2399b7aaac4090860920dd8"}, + {file = "platformdirs-3.1.1.tar.gz", hash = "sha256:024996549ee88ec1a9aa99ff7f8fc819bb59e2c3477b410d90a16d32d6e707aa"}, ] [package.extras] -docs = ["furo (>=2022.12.7)", "proselint (>=0.13)", "sphinx (>=5.3)", "sphinx-autodoc-typehints (>=1.19.5)"] -test = ["appdirs (==1.4.4)", "covdefaults (>=2.2.2)", "pytest (>=7.2)", "pytest-cov (>=4)", "pytest-mock (>=3.10)"] +docs = ["furo (>=2022.12.7)", "proselint (>=0.13)", "sphinx (>=6.1.3)", "sphinx-autodoc-typehints (>=1.22,!=1.23.4)"] +test = ["appdirs (==1.4.4)", "covdefaults (>=2.2.2)", "pytest (>=7.2.1)", "pytest-cov (>=4)", "pytest-mock (>=3.10)"] [[package]] name = "pluggy" @@ -781,48 +774,48 @@ files = [ [[package]] name = "pydantic" -version = "1.10.4" +version = "1.10.7" description = "Data validation and settings management using python type hints" category = "main" optional = false python-versions = ">=3.7" files = [ - {file = "pydantic-1.10.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b5635de53e6686fe7a44b5cf25fcc419a0d5e5c1a1efe73d49d48fe7586db854"}, - {file = "pydantic-1.10.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6dc1cc241440ed7ca9ab59d9929075445da6b7c94ced281b3dd4cfe6c8cff817"}, - {file = "pydantic-1.10.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:51bdeb10d2db0f288e71d49c9cefa609bca271720ecd0c58009bd7504a0c464c"}, - {file = "pydantic-1.10.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:78cec42b95dbb500a1f7120bdf95c401f6abb616bbe8785ef09887306792e66e"}, - {file = "pydantic-1.10.4-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:8775d4ef5e7299a2f4699501077a0defdaac5b6c4321173bcb0f3c496fbadf85"}, - {file = "pydantic-1.10.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:572066051eeac73d23f95ba9a71349c42a3e05999d0ee1572b7860235b850cc6"}, - {file = "pydantic-1.10.4-cp310-cp310-win_amd64.whl", hash = "sha256:7feb6a2d401f4d6863050f58325b8d99c1e56f4512d98b11ac64ad1751dc647d"}, - {file = "pydantic-1.10.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:39f4a73e5342b25c2959529f07f026ef58147249f9b7431e1ba8414a36761f53"}, - {file = "pydantic-1.10.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:983e720704431a6573d626b00662eb78a07148c9115129f9b4351091ec95ecc3"}, - {file = "pydantic-1.10.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75d52162fe6b2b55964fbb0af2ee58e99791a3138588c482572bb6087953113a"}, - {file = "pydantic-1.10.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fdf8d759ef326962b4678d89e275ffc55b7ce59d917d9f72233762061fd04a2d"}, - {file = "pydantic-1.10.4-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:05a81b006be15655b2a1bae5faa4280cf7c81d0e09fcb49b342ebf826abe5a72"}, - {file = "pydantic-1.10.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d88c4c0e5c5dfd05092a4b271282ef0588e5f4aaf345778056fc5259ba098857"}, - {file = "pydantic-1.10.4-cp311-cp311-win_amd64.whl", hash = "sha256:6a05a9db1ef5be0fe63e988f9617ca2551013f55000289c671f71ec16f4985e3"}, - {file = "pydantic-1.10.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:887ca463c3bc47103c123bc06919c86720e80e1214aab79e9b779cda0ff92a00"}, - {file = "pydantic-1.10.4-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fdf88ab63c3ee282c76d652fc86518aacb737ff35796023fae56a65ced1a5978"}, - {file = "pydantic-1.10.4-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a48f1953c4a1d9bd0b5167ac50da9a79f6072c63c4cef4cf2a3736994903583e"}, - {file = "pydantic-1.10.4-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:a9f2de23bec87ff306aef658384b02aa7c32389766af3c5dee9ce33e80222dfa"}, - {file = "pydantic-1.10.4-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:cd8702c5142afda03dc2b1ee6bc358b62b3735b2cce53fc77b31ca9f728e4bc8"}, - {file = "pydantic-1.10.4-cp37-cp37m-win_amd64.whl", hash = "sha256:6e7124d6855b2780611d9f5e1e145e86667eaa3bd9459192c8dc1a097f5e9903"}, - {file = "pydantic-1.10.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0b53e1d41e97063d51a02821b80538053ee4608b9a181c1005441f1673c55423"}, - {file = "pydantic-1.10.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:55b1625899acd33229c4352ce0ae54038529b412bd51c4915349b49ca575258f"}, - {file = "pydantic-1.10.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:301d626a59edbe5dfb48fcae245896379a450d04baeed50ef40d8199f2733b06"}, - {file = "pydantic-1.10.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b6f9d649892a6f54a39ed56b8dfd5e08b5f3be5f893da430bed76975f3735d15"}, - {file = "pydantic-1.10.4-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:d7b5a3821225f5c43496c324b0d6875fde910a1c2933d726a743ce328fbb2a8c"}, - {file = "pydantic-1.10.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:f2f7eb6273dd12472d7f218e1fef6f7c7c2f00ac2e1ecde4db8824c457300416"}, - {file = "pydantic-1.10.4-cp38-cp38-win_amd64.whl", hash = "sha256:4b05697738e7d2040696b0a66d9f0a10bec0efa1883ca75ee9e55baf511909d6"}, - {file = "pydantic-1.10.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a9a6747cac06c2beb466064dda999a13176b23535e4c496c9d48e6406f92d42d"}, - {file = "pydantic-1.10.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:eb992a1ef739cc7b543576337bebfc62c0e6567434e522e97291b251a41dad7f"}, - {file = "pydantic-1.10.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:990406d226dea0e8f25f643b370224771878142155b879784ce89f633541a024"}, - {file = "pydantic-1.10.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2e82a6d37a95e0b1b42b82ab340ada3963aea1317fd7f888bb6b9dfbf4fff57c"}, - {file = "pydantic-1.10.4-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9193d4f4ee8feca58bc56c8306bcb820f5c7905fd919e0750acdeeeef0615b28"}, - {file = "pydantic-1.10.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:2b3ce5f16deb45c472dde1a0ee05619298c864a20cded09c4edd820e1454129f"}, - {file = "pydantic-1.10.4-cp39-cp39-win_amd64.whl", hash = "sha256:9cbdc268a62d9a98c56e2452d6c41c0263d64a2009aac69246486f01b4f594c4"}, - {file = "pydantic-1.10.4-py3-none-any.whl", hash = "sha256:4948f264678c703f3877d1c8877c4e3b2e12e549c57795107f08cf70c6ec7774"}, - {file = "pydantic-1.10.4.tar.gz", hash = "sha256:b9a3859f24eb4e097502a3be1fb4b2abb79b6103dd9e2e0edb70613a4459a648"}, + {file = "pydantic-1.10.7-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e79e999e539872e903767c417c897e729e015872040e56b96e67968c3b918b2d"}, + {file = "pydantic-1.10.7-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:01aea3a42c13f2602b7ecbbea484a98169fb568ebd9e247593ea05f01b884b2e"}, + {file = "pydantic-1.10.7-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:516f1ed9bc2406a0467dd777afc636c7091d71f214d5e413d64fef45174cfc7a"}, + {file = "pydantic-1.10.7-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ae150a63564929c675d7f2303008d88426a0add46efd76c3fc797cd71cb1b46f"}, + {file = "pydantic-1.10.7-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:ecbbc51391248116c0a055899e6c3e7ffbb11fb5e2a4cd6f2d0b93272118a209"}, + {file = "pydantic-1.10.7-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:f4a2b50e2b03d5776e7f21af73e2070e1b5c0d0df255a827e7c632962f8315af"}, + {file = "pydantic-1.10.7-cp310-cp310-win_amd64.whl", hash = "sha256:a7cd2251439988b413cb0a985c4ed82b6c6aac382dbaff53ae03c4b23a70e80a"}, + {file = "pydantic-1.10.7-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:68792151e174a4aa9e9fc1b4e653e65a354a2fa0fed169f7b3d09902ad2cb6f1"}, + {file = "pydantic-1.10.7-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:dfe2507b8ef209da71b6fb5f4e597b50c5a34b78d7e857c4f8f3115effaef5fe"}, + {file = "pydantic-1.10.7-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10a86d8c8db68086f1e30a530f7d5f83eb0685e632e411dbbcf2d5c0150e8dcd"}, + {file = "pydantic-1.10.7-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d75ae19d2a3dbb146b6f324031c24f8a3f52ff5d6a9f22f0683694b3afcb16fb"}, + {file = "pydantic-1.10.7-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:464855a7ff7f2cc2cf537ecc421291b9132aa9c79aef44e917ad711b4a93163b"}, + {file = "pydantic-1.10.7-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:193924c563fae6ddcb71d3f06fa153866423ac1b793a47936656e806b64e24ca"}, + {file = "pydantic-1.10.7-cp311-cp311-win_amd64.whl", hash = "sha256:b4a849d10f211389502059c33332e91327bc154acc1845f375a99eca3afa802d"}, + {file = "pydantic-1.10.7-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:cc1dde4e50a5fc1336ee0581c1612215bc64ed6d28d2c7c6f25d2fe3e7c3e918"}, + {file = "pydantic-1.10.7-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e0cfe895a504c060e5d36b287ee696e2fdad02d89e0d895f83037245218a87fe"}, + {file = "pydantic-1.10.7-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:670bb4683ad1e48b0ecb06f0cfe2178dcf74ff27921cdf1606e527d2617a81ee"}, + {file = "pydantic-1.10.7-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:950ce33857841f9a337ce07ddf46bc84e1c4946d2a3bba18f8280297157a3fd1"}, + {file = "pydantic-1.10.7-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:c15582f9055fbc1bfe50266a19771bbbef33dd28c45e78afbe1996fd70966c2a"}, + {file = "pydantic-1.10.7-cp37-cp37m-win_amd64.whl", hash = "sha256:82dffb306dd20bd5268fd6379bc4bfe75242a9c2b79fec58e1041fbbdb1f7914"}, + {file = "pydantic-1.10.7-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8c7f51861d73e8b9ddcb9916ae7ac39fb52761d9ea0df41128e81e2ba42886cd"}, + {file = "pydantic-1.10.7-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:6434b49c0b03a51021ade5c4daa7d70c98f7a79e95b551201fff682fc1661245"}, + {file = "pydantic-1.10.7-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:64d34ab766fa056df49013bb6e79921a0265204c071984e75a09cbceacbbdd5d"}, + {file = "pydantic-1.10.7-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:701daea9ffe9d26f97b52f1d157e0d4121644f0fcf80b443248434958fd03dc3"}, + {file = "pydantic-1.10.7-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:cf135c46099ff3f919d2150a948ce94b9ce545598ef2c6c7bf55dca98a304b52"}, + {file = "pydantic-1.10.7-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:b0f85904f73161817b80781cc150f8b906d521fa11e3cdabae19a581c3606209"}, + {file = "pydantic-1.10.7-cp38-cp38-win_amd64.whl", hash = "sha256:9f6f0fd68d73257ad6685419478c5aece46432f4bdd8d32c7345f1986496171e"}, + {file = "pydantic-1.10.7-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c230c0d8a322276d6e7b88c3f7ce885f9ed16e0910354510e0bae84d54991143"}, + {file = "pydantic-1.10.7-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:976cae77ba6a49d80f461fd8bba183ff7ba79f44aa5cfa82f1346b5626542f8e"}, + {file = "pydantic-1.10.7-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7d45fc99d64af9aaf7e308054a0067fdcd87ffe974f2442312372dfa66e1001d"}, + {file = "pydantic-1.10.7-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d2a5ebb48958754d386195fe9e9c5106f11275867051bf017a8059410e9abf1f"}, + {file = "pydantic-1.10.7-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:abfb7d4a7cd5cc4e1d1887c43503a7c5dd608eadf8bc615413fc498d3e4645cd"}, + {file = "pydantic-1.10.7-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:80b1fab4deb08a8292d15e43a6edccdffa5377a36a4597bb545b93e79c5ff0a5"}, + {file = "pydantic-1.10.7-cp39-cp39-win_amd64.whl", hash = "sha256:d71e69699498b020ea198468e2480a2f1e7433e32a3a99760058c6520e2bea7e"}, + {file = "pydantic-1.10.7-py3-none-any.whl", hash = "sha256:0cd181f1d0b1d00e2b705f1bf1ac7799a2d938cce3376b8007df62b29be3c2c6"}, + {file = "pydantic-1.10.7.tar.gz", hash = "sha256:cfc83c0678b6ba51b0532bea66860617c4cd4251ecf76e9846fa5a9f3454e97e"}, ] [package.dependencies] @@ -849,18 +842,18 @@ plugins = ["importlib-metadata"] [[package]] name = "pylint" -version = "2.15.10" +version = "2.17.1" description = "python code static checker" category = "dev" optional = false python-versions = ">=3.7.2" files = [ - {file = "pylint-2.15.10-py3-none-any.whl", hash = "sha256:9df0d07e8948a1c3ffa3b6e2d7e6e63d9fb457c5da5b961ed63106594780cc7e"}, - {file = "pylint-2.15.10.tar.gz", hash = "sha256:b3dc5ef7d33858f297ac0d06cc73862f01e4f2e74025ec3eff347ce0bc60baf5"}, + {file = "pylint-2.17.1-py3-none-any.whl", hash = "sha256:8660a54e3f696243d644fca98f79013a959c03f979992c1ab59c24d3f4ec2700"}, + {file = "pylint-2.17.1.tar.gz", hash = "sha256:d4d009b0116e16845533bc2163493d6681846ac725eab8ca8014afb520178ddd"}, ] [package.dependencies] -astroid = ">=2.12.13,<=2.14.0-dev0" +astroid = ">=2.15.0,<=2.17.0-dev0" colorama = {version = ">=0.4.5", markers = "sys_platform == \"win32\""} dill = [ {version = ">=0.2", markers = "python_version < \"3.11\""}, @@ -879,14 +872,14 @@ testutils = ["gitpython (>3)"] [[package]] name = "pytest" -version = "7.2.1" +version = "7.2.2" description = "pytest: simple powerful testing with Python" category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "pytest-7.2.1-py3-none-any.whl", hash = "sha256:c7c6ca206e93355074ae32f7403e8ea12163b1163c976fee7d4d84027c162be5"}, - {file = "pytest-7.2.1.tar.gz", hash = "sha256:d45e0952f3727241918b8fd0f376f5ff6b301cc0777c6f9a556935c92d8a7d42"}, + {file = "pytest-7.2.2-py3-none-any.whl", hash = "sha256:130328f552dcfac0b1cec75c12e3f005619dc5f874f0a06e8ff7263f0ee6225e"}, + {file = "pytest-7.2.2.tar.gz", hash = "sha256:c99ab0c73aceb050f68929bc93af19ab6db0558791c6a0715723abe9d0ade9d4"}, ] [package.dependencies] @@ -901,18 +894,6 @@ tomli = {version = ">=1.0.0", markers = "python_version < \"3.11\""} [package.extras] testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "xmlschema"] -[[package]] -name = "pytz" -version = "2022.7.1" -description = "World timezone definitions, modern and historical" -category = "dev" -optional = false -python-versions = "*" -files = [ - {file = "pytz-2022.7.1-py2.py3-none-any.whl", hash = "sha256:78f4f37d8198e0627c5f1143240bb0206b8691d8d7ac6d78fee88b78733f8c4a"}, - {file = "pytz-2022.7.1.tar.gz", hash = "sha256:01a0681c4b9684a28304615eba55d1ab31ae00bf68ec157ec3708a8182dbbcd0"}, -] - [[package]] name = "pyyaml" version = "6.0" @@ -1110,19 +1091,20 @@ test = ["cython", "html5lib", "pytest (>=4.6)", "typed_ast"] [[package]] name = "sphinx-rtd-theme" -version = "1.1.1" +version = "1.2.0" description = "Read the Docs theme for Sphinx" category = "dev" optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7" +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7" files = [ - {file = "sphinx_rtd_theme-1.1.1-py2.py3-none-any.whl", hash = "sha256:31faa07d3e97c8955637fc3f1423a5ab2c44b74b8cc558a51498c202ce5cbda7"}, - {file = "sphinx_rtd_theme-1.1.1.tar.gz", hash = "sha256:6146c845f1e1947b3c3dd4432c28998a1693ccc742b4f9ad7c63129f0757c103"}, + {file = "sphinx_rtd_theme-1.2.0-py2.py3-none-any.whl", hash = "sha256:f823f7e71890abe0ac6aaa6013361ea2696fc8d3e1fa798f463e82bdb77eeff2"}, + {file = "sphinx_rtd_theme-1.2.0.tar.gz", hash = "sha256:a0d8bd1a2ed52e0b338cbe19c4b2eef3c5e7a048769753dac6a9f059c7b641b8"}, ] [package.dependencies] -docutils = "<0.18" -sphinx = ">=1.6,<6" +docutils = "<0.19" +sphinx = ">=1.6,<7" +sphinxcontrib-jquery = {version = ">=2.0.0,<3.0.0 || >3.0.0", markers = "python_version > \"3\""} [package.extras] dev = ["bump2version", "sphinxcontrib-httpdomain", "transifex-client", "wheel"] @@ -1161,20 +1143,35 @@ test = ["pytest"] [[package]] name = "sphinxcontrib-htmlhelp" -version = "2.0.0" +version = "2.0.1" description = "sphinxcontrib-htmlhelp is a sphinx extension which renders HTML help files" category = "dev" optional = false -python-versions = ">=3.6" +python-versions = ">=3.8" files = [ - {file = "sphinxcontrib-htmlhelp-2.0.0.tar.gz", hash = "sha256:f5f8bb2d0d629f398bf47d0d69c07bc13b65f75a81ad9e2f71a63d4b7a2f6db2"}, - {file = "sphinxcontrib_htmlhelp-2.0.0-py2.py3-none-any.whl", hash = "sha256:d412243dfb797ae3ec2b59eca0e52dac12e75a241bf0e4eb861e450d06c6ed07"}, + {file = "sphinxcontrib-htmlhelp-2.0.1.tar.gz", hash = "sha256:0cbdd302815330058422b98a113195c9249825d681e18f11e8b1f78a2f11efff"}, + {file = "sphinxcontrib_htmlhelp-2.0.1-py3-none-any.whl", hash = "sha256:c38cb46dccf316c79de6e5515e1770414b797162b23cd3d06e67020e1d2a6903"}, ] [package.extras] lint = ["docutils-stubs", "flake8", "mypy"] test = ["html5lib", "pytest"] +[[package]] +name = "sphinxcontrib-jquery" +version = "4.1" +description = "Extension to include jQuery on newer Sphinx releases" +category = "dev" +optional = false +python-versions = ">=2.7" +files = [ + {file = "sphinxcontrib-jquery-4.1.tar.gz", hash = "sha256:1620739f04e36a2c779f1a131a2dfd49b2fd07351bf1968ced074365933abc7a"}, + {file = "sphinxcontrib_jquery-4.1-py2.py3-none-any.whl", hash = "sha256:f936030d7d0147dd026a4f2b5a57343d233f1fc7b363f68b3d4f1cb0993878ae"}, +] + +[package.dependencies] +Sphinx = ">=1.8" + [[package]] name = "sphinxcontrib-jsmath" version = "1.0.1" @@ -1274,38 +1271,38 @@ testing = ["flaky (>=3.4.0)", "freezegun (>=0.3.11)", "pathlib2 (>=2.3.3)", "psu [[package]] name = "types-pyyaml" -version = "6.0.12.3" +version = "6.0.12.8" description = "Typing stubs for PyYAML" category = "dev" optional = false python-versions = "*" files = [ - {file = "types-PyYAML-6.0.12.3.tar.gz", hash = "sha256:17ce17b3ead8f06e416a3b1d5b8ddc6cb82a422bb200254dd8b469434b045ffc"}, - {file = "types_PyYAML-6.0.12.3-py3-none-any.whl", hash = "sha256:879700e9f215afb20ab5f849590418ab500989f83a57e635689e1d50ccc63f0c"}, + {file = "types-PyYAML-6.0.12.8.tar.gz", hash = "sha256:19304869a89d49af00be681e7b267414df213f4eb89634c4495fa62e8f942b9f"}, + {file = "types_PyYAML-6.0.12.8-py3-none-any.whl", hash = "sha256:5314a4b2580999b2ea06b2e5f9a7763d860d6e09cdf21c0e9561daa9cbd60178"}, ] [[package]] name = "typing-extensions" -version = "4.4.0" +version = "4.5.0" description = "Backported and Experimental Type Hints for Python 3.7+" category = "main" optional = false python-versions = ">=3.7" files = [ - {file = "typing_extensions-4.4.0-py3-none-any.whl", hash = "sha256:16fa4864408f655d35ec496218b85f79b3437c829e93320c7c9215ccfd92489e"}, - {file = "typing_extensions-4.4.0.tar.gz", hash = "sha256:1511434bb92bf8dd198c12b1cc812e800d4181cfcb867674e0f8279cc93087aa"}, + {file = "typing_extensions-4.5.0-py3-none-any.whl", hash = "sha256:fb33085c39dd998ac16d1431ebc293a8b3eedd00fd4a32de0ff79002c19511b4"}, + {file = "typing_extensions-4.5.0.tar.gz", hash = "sha256:5cb5f4a79139d699607b3ef622a1dedafa84e115ab0024e0d9c044a9479ca7cb"}, ] [[package]] name = "urllib3" -version = "1.26.14" +version = "1.26.15" description = "HTTP library with thread-safe connection pooling, file post, and more." category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" files = [ - {file = "urllib3-1.26.14-py2.py3-none-any.whl", hash = "sha256:75edcdc2f7d85b137124a6c3c9fc3933cdeaa12ecb9a6a959f22797a0feca7e1"}, - {file = "urllib3-1.26.14.tar.gz", hash = "sha256:076907bf8fd355cde77728471316625a4d2f7e713c125f51953bb5b3eecf4f72"}, + {file = "urllib3-1.26.15-py2.py3-none-any.whl", hash = "sha256:aa751d169e23c7479ce47a0cb0da579e3ede798f994f5816a74e4f4500dcea42"}, + {file = "urllib3-1.26.15.tar.gz", hash = "sha256:8a388717b9476f934a21484e8c8e61875ab60644d29b9b39e11e4b9dc1c6b305"}, ] [package.extras] @@ -1315,114 +1312,125 @@ socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] [[package]] name = "virtualenv" -version = "20.17.1" +version = "20.21.0" description = "Virtual Python Environment builder" category = "dev" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" files = [ - {file = "virtualenv-20.17.1-py3-none-any.whl", hash = "sha256:ce3b1684d6e1a20a3e5ed36795a97dfc6af29bc3970ca8dab93e11ac6094b3c4"}, - {file = "virtualenv-20.17.1.tar.gz", hash = "sha256:f8b927684efc6f1cc206c9db297a570ab9ad0e51c16fa9e45487d36d1905c058"}, + {file = "virtualenv-20.21.0-py3-none-any.whl", hash = "sha256:31712f8f2a17bd06234fa97fdf19609e789dd4e3e4bf108c3da71d710651adbc"}, + {file = "virtualenv-20.21.0.tar.gz", hash = "sha256:f50e3e60f990a0757c9b68333c9fdaa72d7188caa417f96af9e52407831a3b68"}, ] [package.dependencies] distlib = ">=0.3.6,<1" filelock = ">=3.4.1,<4" -platformdirs = ">=2.4,<3" +platformdirs = ">=2.4,<4" [package.extras] -docs = ["proselint (>=0.13)", "sphinx (>=5.3)", "sphinx-argparse (>=0.3.2)", "sphinx-rtd-theme (>=1)", "towncrier (>=22.8)"] -testing = ["coverage (>=6.2)", "coverage-enable-subprocess (>=1)", "flaky (>=3.7)", "packaging (>=21.3)", "pytest (>=7.0.1)", "pytest-env (>=0.6.2)", "pytest-freezegun (>=0.4.2)", "pytest-mock (>=3.6.1)", "pytest-randomly (>=3.10.3)", "pytest-timeout (>=2.1)"] +docs = ["furo (>=2022.12.7)", "proselint (>=0.13)", "sphinx (>=6.1.3)", "sphinx-argparse (>=0.4)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=22.12)"] +test = ["covdefaults (>=2.2.2)", "coverage (>=7.1)", "coverage-enable-subprocess (>=1)", "flaky (>=3.7)", "packaging (>=23)", "pytest (>=7.2.1)", "pytest-env (>=0.8.1)", "pytest-freezegun (>=0.4.2)", "pytest-mock (>=3.10)", "pytest-randomly (>=3.12)", "pytest-timeout (>=2.1)"] [[package]] name = "wrapt" -version = "1.14.1" +version = "1.15.0" description = "Module for decorators, wrappers and monkey patching." category = "dev" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" files = [ - {file = "wrapt-1.14.1-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:1b376b3f4896e7930f1f772ac4b064ac12598d1c38d04907e696cc4d794b43d3"}, - {file = "wrapt-1.14.1-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:903500616422a40a98a5a3c4ff4ed9d0066f3b4c951fa286018ecdf0750194ef"}, - {file = "wrapt-1.14.1-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:5a9a0d155deafd9448baff28c08e150d9b24ff010e899311ddd63c45c2445e28"}, - {file = "wrapt-1.14.1-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:ddaea91abf8b0d13443f6dac52e89051a5063c7d014710dcb4d4abb2ff811a59"}, - {file = "wrapt-1.14.1-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:36f582d0c6bc99d5f39cd3ac2a9062e57f3cf606ade29a0a0d6b323462f4dd87"}, - {file = "wrapt-1.14.1-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:7ef58fb89674095bfc57c4069e95d7a31cfdc0939e2a579882ac7d55aadfd2a1"}, - {file = "wrapt-1.14.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:e2f83e18fe2f4c9e7db597e988f72712c0c3676d337d8b101f6758107c42425b"}, - {file = "wrapt-1.14.1-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:ee2b1b1769f6707a8a445162ea16dddf74285c3964f605877a20e38545c3c462"}, - {file = "wrapt-1.14.1-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:833b58d5d0b7e5b9832869f039203389ac7cbf01765639c7309fd50ef619e0b1"}, - {file = "wrapt-1.14.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:80bb5c256f1415f747011dc3604b59bc1f91c6e7150bd7db03b19170ee06b320"}, - {file = "wrapt-1.14.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:07f7a7d0f388028b2df1d916e94bbb40624c59b48ecc6cbc232546706fac74c2"}, - {file = "wrapt-1.14.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:02b41b633c6261feff8ddd8d11c711df6842aba629fdd3da10249a53211a72c4"}, - {file = "wrapt-1.14.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2fe803deacd09a233e4762a1adcea5db5d31e6be577a43352936179d14d90069"}, - {file = "wrapt-1.14.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:257fd78c513e0fb5cdbe058c27a0624c9884e735bbd131935fd49e9fe719d310"}, - {file = "wrapt-1.14.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:4fcc4649dc762cddacd193e6b55bc02edca674067f5f98166d7713b193932b7f"}, - {file = "wrapt-1.14.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:11871514607b15cfeb87c547a49bca19fde402f32e2b1c24a632506c0a756656"}, - {file = "wrapt-1.14.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:8ad85f7f4e20964db4daadcab70b47ab05c7c1cf2a7c1e51087bfaa83831854c"}, - {file = "wrapt-1.14.1-cp310-cp310-win32.whl", hash = "sha256:a9a52172be0b5aae932bef82a79ec0a0ce87288c7d132946d645eba03f0ad8a8"}, - {file = "wrapt-1.14.1-cp310-cp310-win_amd64.whl", hash = "sha256:6d323e1554b3d22cfc03cd3243b5bb815a51f5249fdcbb86fda4bf62bab9e164"}, - {file = "wrapt-1.14.1-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:43ca3bbbe97af00f49efb06e352eae40434ca9d915906f77def219b88e85d907"}, - {file = "wrapt-1.14.1-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:6b1a564e6cb69922c7fe3a678b9f9a3c54e72b469875aa8018f18b4d1dd1adf3"}, - {file = "wrapt-1.14.1-cp35-cp35m-manylinux2010_i686.whl", hash = "sha256:00b6d4ea20a906c0ca56d84f93065b398ab74b927a7a3dbd470f6fc503f95dc3"}, - {file = "wrapt-1.14.1-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:a85d2b46be66a71bedde836d9e41859879cc54a2a04fad1191eb50c2066f6e9d"}, - {file = "wrapt-1.14.1-cp35-cp35m-win32.whl", hash = "sha256:dbcda74c67263139358f4d188ae5faae95c30929281bc6866d00573783c422b7"}, - {file = "wrapt-1.14.1-cp35-cp35m-win_amd64.whl", hash = "sha256:b21bb4c09ffabfa0e85e3a6b623e19b80e7acd709b9f91452b8297ace2a8ab00"}, - {file = "wrapt-1.14.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:9e0fd32e0148dd5dea6af5fee42beb949098564cc23211a88d799e434255a1f4"}, - {file = "wrapt-1.14.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9736af4641846491aedb3c3f56b9bc5568d92b0692303b5a305301a95dfd38b1"}, - {file = "wrapt-1.14.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5b02d65b9ccf0ef6c34cba6cf5bf2aab1bb2f49c6090bafeecc9cd81ad4ea1c1"}, - {file = "wrapt-1.14.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21ac0156c4b089b330b7666db40feee30a5d52634cc4560e1905d6529a3897ff"}, - {file = "wrapt-1.14.1-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:9f3e6f9e05148ff90002b884fbc2a86bd303ae847e472f44ecc06c2cd2fcdb2d"}, - {file = "wrapt-1.14.1-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:6e743de5e9c3d1b7185870f480587b75b1cb604832e380d64f9504a0535912d1"}, - {file = "wrapt-1.14.1-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:d79d7d5dc8a32b7093e81e97dad755127ff77bcc899e845f41bf71747af0c569"}, - {file = "wrapt-1.14.1-cp36-cp36m-win32.whl", hash = "sha256:81b19725065dcb43df02b37e03278c011a09e49757287dca60c5aecdd5a0b8ed"}, - {file = "wrapt-1.14.1-cp36-cp36m-win_amd64.whl", hash = "sha256:b014c23646a467558be7da3d6b9fa409b2c567d2110599b7cf9a0c5992b3b471"}, - {file = "wrapt-1.14.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:88bd7b6bd70a5b6803c1abf6bca012f7ed963e58c68d76ee20b9d751c74a3248"}, - {file = "wrapt-1.14.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b5901a312f4d14c59918c221323068fad0540e34324925c8475263841dbdfe68"}, - {file = "wrapt-1.14.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d77c85fedff92cf788face9bfa3ebaa364448ebb1d765302e9af11bf449ca36d"}, - {file = "wrapt-1.14.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8d649d616e5c6a678b26d15ece345354f7c2286acd6db868e65fcc5ff7c24a77"}, - {file = "wrapt-1.14.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:7d2872609603cb35ca513d7404a94d6d608fc13211563571117046c9d2bcc3d7"}, - {file = "wrapt-1.14.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:ee6acae74a2b91865910eef5e7de37dc6895ad96fa23603d1d27ea69df545015"}, - {file = "wrapt-1.14.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:2b39d38039a1fdad98c87279b48bc5dce2c0ca0d73483b12cb72aa9609278e8a"}, - {file = "wrapt-1.14.1-cp37-cp37m-win32.whl", hash = "sha256:60db23fa423575eeb65ea430cee741acb7c26a1365d103f7b0f6ec412b893853"}, - {file = "wrapt-1.14.1-cp37-cp37m-win_amd64.whl", hash = "sha256:709fe01086a55cf79d20f741f39325018f4df051ef39fe921b1ebe780a66184c"}, - {file = "wrapt-1.14.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8c0ce1e99116d5ab21355d8ebe53d9460366704ea38ae4d9f6933188f327b456"}, - {file = "wrapt-1.14.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:e3fb1677c720409d5f671e39bac6c9e0e422584e5f518bfd50aa4cbbea02433f"}, - {file = "wrapt-1.14.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:642c2e7a804fcf18c222e1060df25fc210b9c58db7c91416fb055897fc27e8cc"}, - {file = "wrapt-1.14.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7b7c050ae976e286906dd3f26009e117eb000fb2cf3533398c5ad9ccc86867b1"}, - {file = "wrapt-1.14.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ef3f72c9666bba2bab70d2a8b79f2c6d2c1a42a7f7e2b0ec83bb2f9e383950af"}, - {file = "wrapt-1.14.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:01c205616a89d09827986bc4e859bcabd64f5a0662a7fe95e0d359424e0e071b"}, - {file = "wrapt-1.14.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:5a0f54ce2c092aaf439813735584b9537cad479575a09892b8352fea5e988dc0"}, - {file = "wrapt-1.14.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:2cf71233a0ed05ccdabe209c606fe0bac7379fdcf687f39b944420d2a09fdb57"}, - {file = "wrapt-1.14.1-cp38-cp38-win32.whl", hash = "sha256:aa31fdcc33fef9eb2552cbcbfee7773d5a6792c137b359e82879c101e98584c5"}, - {file = "wrapt-1.14.1-cp38-cp38-win_amd64.whl", hash = "sha256:d1967f46ea8f2db647c786e78d8cc7e4313dbd1b0aca360592d8027b8508e24d"}, - {file = "wrapt-1.14.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3232822c7d98d23895ccc443bbdf57c7412c5a65996c30442ebe6ed3df335383"}, - {file = "wrapt-1.14.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:988635d122aaf2bdcef9e795435662bcd65b02f4f4c1ae37fbee7401c440b3a7"}, - {file = "wrapt-1.14.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9cca3c2cdadb362116235fdbd411735de4328c61425b0aa9f872fd76d02c4e86"}, - {file = "wrapt-1.14.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d52a25136894c63de15a35bc0bdc5adb4b0e173b9c0d07a2be9d3ca64a332735"}, - {file = "wrapt-1.14.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:40e7bc81c9e2b2734ea4bc1aceb8a8f0ceaac7c5299bc5d69e37c44d9081d43b"}, - {file = "wrapt-1.14.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:b9b7a708dd92306328117d8c4b62e2194d00c365f18eff11a9b53c6f923b01e3"}, - {file = "wrapt-1.14.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:6a9a25751acb379b466ff6be78a315e2b439d4c94c1e99cb7266d40a537995d3"}, - {file = "wrapt-1.14.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:34aa51c45f28ba7f12accd624225e2b1e5a3a45206aa191f6f9aac931d9d56fe"}, - {file = "wrapt-1.14.1-cp39-cp39-win32.whl", hash = "sha256:dee0ce50c6a2dd9056c20db781e9c1cfd33e77d2d569f5d1d9321c641bb903d5"}, - {file = "wrapt-1.14.1-cp39-cp39-win_amd64.whl", hash = "sha256:dee60e1de1898bde3b238f18340eec6148986da0455d8ba7848d50470a7a32fb"}, - {file = "wrapt-1.14.1.tar.gz", hash = "sha256:380a85cf89e0e69b7cfbe2ea9f765f004ff419f34194018a6827ac0e3edfed4d"}, + {file = "wrapt-1.15.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:ca1cccf838cd28d5a0883b342474c630ac48cac5df0ee6eacc9c7290f76b11c1"}, + {file = "wrapt-1.15.0-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:e826aadda3cae59295b95343db8f3d965fb31059da7de01ee8d1c40a60398b29"}, + {file = "wrapt-1.15.0-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:5fc8e02f5984a55d2c653f5fea93531e9836abbd84342c1d1e17abc4a15084c2"}, + {file = "wrapt-1.15.0-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:96e25c8603a155559231c19c0349245eeb4ac0096fe3c1d0be5c47e075bd4f46"}, + {file = "wrapt-1.15.0-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:40737a081d7497efea35ab9304b829b857f21558acfc7b3272f908d33b0d9d4c"}, + {file = "wrapt-1.15.0-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:f87ec75864c37c4c6cb908d282e1969e79763e0d9becdfe9fe5473b7bb1e5f09"}, + {file = "wrapt-1.15.0-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:1286eb30261894e4c70d124d44b7fd07825340869945c79d05bda53a40caa079"}, + {file = "wrapt-1.15.0-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:493d389a2b63c88ad56cdc35d0fa5752daac56ca755805b1b0c530f785767d5e"}, + {file = "wrapt-1.15.0-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:58d7a75d731e8c63614222bcb21dd992b4ab01a399f1f09dd82af17bbfc2368a"}, + {file = "wrapt-1.15.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:21f6d9a0d5b3a207cdf7acf8e58d7d13d463e639f0c7e01d82cdb671e6cb7923"}, + {file = "wrapt-1.15.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ce42618f67741d4697684e501ef02f29e758a123aa2d669e2d964ff734ee00ee"}, + {file = "wrapt-1.15.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:41d07d029dd4157ae27beab04d22b8e261eddfc6ecd64ff7000b10dc8b3a5727"}, + {file = "wrapt-1.15.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:54accd4b8bc202966bafafd16e69da9d5640ff92389d33d28555c5fd4f25ccb7"}, + {file = "wrapt-1.15.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2fbfbca668dd15b744418265a9607baa970c347eefd0db6a518aaf0cfbd153c0"}, + {file = "wrapt-1.15.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:76e9c727a874b4856d11a32fb0b389afc61ce8aaf281ada613713ddeadd1cfec"}, + {file = "wrapt-1.15.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e20076a211cd6f9b44a6be58f7eeafa7ab5720eb796975d0c03f05b47d89eb90"}, + {file = "wrapt-1.15.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a74d56552ddbde46c246b5b89199cb3fd182f9c346c784e1a93e4dc3f5ec9975"}, + {file = "wrapt-1.15.0-cp310-cp310-win32.whl", hash = "sha256:26458da5653aa5b3d8dc8b24192f574a58984c749401f98fff994d41d3f08da1"}, + {file = "wrapt-1.15.0-cp310-cp310-win_amd64.whl", hash = "sha256:75760a47c06b5974aa5e01949bf7e66d2af4d08cb8c1d6516af5e39595397f5e"}, + {file = "wrapt-1.15.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ba1711cda2d30634a7e452fc79eabcadaffedf241ff206db2ee93dd2c89a60e7"}, + {file = "wrapt-1.15.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:56374914b132c702aa9aa9959c550004b8847148f95e1b824772d453ac204a72"}, + {file = "wrapt-1.15.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a89ce3fd220ff144bd9d54da333ec0de0399b52c9ac3d2ce34b569cf1a5748fb"}, + {file = "wrapt-1.15.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3bbe623731d03b186b3d6b0d6f51865bf598587c38d6f7b0be2e27414f7f214e"}, + {file = "wrapt-1.15.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3abbe948c3cbde2689370a262a8d04e32ec2dd4f27103669a45c6929bcdbfe7c"}, + {file = "wrapt-1.15.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:b67b819628e3b748fd3c2192c15fb951f549d0f47c0449af0764d7647302fda3"}, + {file = "wrapt-1.15.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:7eebcdbe3677e58dd4c0e03b4f2cfa346ed4049687d839adad68cc38bb559c92"}, + {file = "wrapt-1.15.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:74934ebd71950e3db69960a7da29204f89624dde411afbfb3b4858c1409b1e98"}, + {file = "wrapt-1.15.0-cp311-cp311-win32.whl", hash = "sha256:bd84395aab8e4d36263cd1b9308cd504f6cf713b7d6d3ce25ea55670baec5416"}, + {file = "wrapt-1.15.0-cp311-cp311-win_amd64.whl", hash = "sha256:a487f72a25904e2b4bbc0817ce7a8de94363bd7e79890510174da9d901c38705"}, + {file = "wrapt-1.15.0-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:4ff0d20f2e670800d3ed2b220d40984162089a6e2c9646fdb09b85e6f9a8fc29"}, + {file = "wrapt-1.15.0-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:9ed6aa0726b9b60911f4aed8ec5b8dd7bf3491476015819f56473ffaef8959bd"}, + {file = "wrapt-1.15.0-cp35-cp35m-manylinux2010_i686.whl", hash = "sha256:896689fddba4f23ef7c718279e42f8834041a21342d95e56922e1c10c0cc7afb"}, + {file = "wrapt-1.15.0-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:75669d77bb2c071333417617a235324a1618dba66f82a750362eccbe5b61d248"}, + {file = "wrapt-1.15.0-cp35-cp35m-win32.whl", hash = "sha256:fbec11614dba0424ca72f4e8ba3c420dba07b4a7c206c8c8e4e73f2e98f4c559"}, + {file = "wrapt-1.15.0-cp35-cp35m-win_amd64.whl", hash = "sha256:fd69666217b62fa5d7c6aa88e507493a34dec4fa20c5bd925e4bc12fce586639"}, + {file = "wrapt-1.15.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:b0724f05c396b0a4c36a3226c31648385deb6a65d8992644c12a4963c70326ba"}, + {file = "wrapt-1.15.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bbeccb1aa40ab88cd29e6c7d8585582c99548f55f9b2581dfc5ba68c59a85752"}, + {file = "wrapt-1.15.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:38adf7198f8f154502883242f9fe7333ab05a5b02de7d83aa2d88ea621f13364"}, + {file = "wrapt-1.15.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:578383d740457fa790fdf85e6d346fda1416a40549fe8db08e5e9bd281c6a475"}, + {file = "wrapt-1.15.0-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:a4cbb9ff5795cd66f0066bdf5947f170f5d63a9274f99bdbca02fd973adcf2a8"}, + {file = "wrapt-1.15.0-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:af5bd9ccb188f6a5fdda9f1f09d9f4c86cc8a539bd48a0bfdc97723970348418"}, + {file = "wrapt-1.15.0-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:b56d5519e470d3f2fe4aa7585f0632b060d532d0696c5bdfb5e8319e1d0f69a2"}, + {file = "wrapt-1.15.0-cp36-cp36m-win32.whl", hash = "sha256:77d4c1b881076c3ba173484dfa53d3582c1c8ff1f914c6461ab70c8428b796c1"}, + {file = "wrapt-1.15.0-cp36-cp36m-win_amd64.whl", hash = "sha256:077ff0d1f9d9e4ce6476c1a924a3332452c1406e59d90a2cf24aeb29eeac9420"}, + {file = "wrapt-1.15.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:5c5aa28df055697d7c37d2099a7bc09f559d5053c3349b1ad0c39000e611d317"}, + {file = "wrapt-1.15.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3a8564f283394634a7a7054b7983e47dbf39c07712d7b177b37e03f2467a024e"}, + {file = "wrapt-1.15.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:780c82a41dc493b62fc5884fb1d3a3b81106642c5c5c78d6a0d4cbe96d62ba7e"}, + {file = "wrapt-1.15.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e169e957c33576f47e21864cf3fc9ff47c223a4ebca8960079b8bd36cb014fd0"}, + {file = "wrapt-1.15.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:b02f21c1e2074943312d03d243ac4388319f2456576b2c6023041c4d57cd7019"}, + {file = "wrapt-1.15.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:f2e69b3ed24544b0d3dbe2c5c0ba5153ce50dcebb576fdc4696d52aa22db6034"}, + {file = "wrapt-1.15.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d787272ed958a05b2c86311d3a4135d3c2aeea4fc655705f074130aa57d71653"}, + {file = "wrapt-1.15.0-cp37-cp37m-win32.whl", hash = "sha256:02fce1852f755f44f95af51f69d22e45080102e9d00258053b79367d07af39c0"}, + {file = "wrapt-1.15.0-cp37-cp37m-win_amd64.whl", hash = "sha256:abd52a09d03adf9c763d706df707c343293d5d106aea53483e0ec8d9e310ad5e"}, + {file = "wrapt-1.15.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:cdb4f085756c96a3af04e6eca7f08b1345e94b53af8921b25c72f096e704e145"}, + {file = "wrapt-1.15.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:230ae493696a371f1dbffaad3dafbb742a4d27a0afd2b1aecebe52b740167e7f"}, + {file = "wrapt-1.15.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:63424c681923b9f3bfbc5e3205aafe790904053d42ddcc08542181a30a7a51bd"}, + {file = "wrapt-1.15.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d6bcbfc99f55655c3d93feb7ef3800bd5bbe963a755687cbf1f490a71fb7794b"}, + {file = "wrapt-1.15.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c99f4309f5145b93eca6e35ac1a988f0dc0a7ccf9ccdcd78d3c0adf57224e62f"}, + {file = "wrapt-1.15.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:b130fe77361d6771ecf5a219d8e0817d61b236b7d8b37cc045172e574ed219e6"}, + {file = "wrapt-1.15.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:96177eb5645b1c6985f5c11d03fc2dbda9ad24ec0f3a46dcce91445747e15094"}, + {file = "wrapt-1.15.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:d5fe3e099cf07d0fb5a1e23d399e5d4d1ca3e6dfcbe5c8570ccff3e9208274f7"}, + {file = "wrapt-1.15.0-cp38-cp38-win32.whl", hash = "sha256:abd8f36c99512755b8456047b7be10372fca271bf1467a1caa88db991e7c421b"}, + {file = "wrapt-1.15.0-cp38-cp38-win_amd64.whl", hash = "sha256:b06fa97478a5f478fb05e1980980a7cdf2712015493b44d0c87606c1513ed5b1"}, + {file = "wrapt-1.15.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:2e51de54d4fb8fb50d6ee8327f9828306a959ae394d3e01a1ba8b2f937747d86"}, + {file = "wrapt-1.15.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0970ddb69bba00670e58955f8019bec4a42d1785db3faa043c33d81de2bf843c"}, + {file = "wrapt-1.15.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76407ab327158c510f44ded207e2f76b657303e17cb7a572ffe2f5a8a48aa04d"}, + {file = "wrapt-1.15.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cd525e0e52a5ff16653a3fc9e3dd827981917d34996600bbc34c05d048ca35cc"}, + {file = "wrapt-1.15.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9d37ac69edc5614b90516807de32d08cb8e7b12260a285ee330955604ed9dd29"}, + {file = "wrapt-1.15.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:078e2a1a86544e644a68422f881c48b84fef6d18f8c7a957ffd3f2e0a74a0d4a"}, + {file = "wrapt-1.15.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:2cf56d0e237280baed46f0b5316661da892565ff58309d4d2ed7dba763d984b8"}, + {file = "wrapt-1.15.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:7dc0713bf81287a00516ef43137273b23ee414fe41a3c14be10dd95ed98a2df9"}, + {file = "wrapt-1.15.0-cp39-cp39-win32.whl", hash = "sha256:46ed616d5fb42f98630ed70c3529541408166c22cdfd4540b88d5f21006b0eff"}, + {file = "wrapt-1.15.0-cp39-cp39-win_amd64.whl", hash = "sha256:eef4d64c650f33347c1f9266fa5ae001440b232ad9b98f1f43dfe7a79435c0a6"}, + {file = "wrapt-1.15.0-py3-none-any.whl", hash = "sha256:64b1df0f83706b4ef4cfb4fb0e4c2669100fd7ecacfb59e091fad300d4e04640"}, + {file = "wrapt-1.15.0.tar.gz", hash = "sha256:d06730c6aed78cee4126234cf2d071e01b44b915e725a6cb439a879ec9754a3a"}, ] [[package]] name = "zipp" -version = "3.11.0" +version = "3.15.0" description = "Backport of pathlib-compatible object wrapper for zip files" category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "zipp-3.11.0-py3-none-any.whl", hash = "sha256:83a28fcb75844b5c0cdaf5aa4003c2d728c77e05f5aeabe8e95e56727005fbaa"}, - {file = "zipp-3.11.0.tar.gz", hash = "sha256:a7a22e05929290a67401440b39690ae6563279bced5f314609d9d03798f56766"}, + {file = "zipp-3.15.0-py3-none-any.whl", hash = "sha256:48904fc76a60e542af151aded95726c1a5c34ed43ab4134b597665c86d7ad556"}, + {file = "zipp-3.15.0.tar.gz", hash = "sha256:112929ad649da941c23de50f356a2b5570c954b65150642bccdd66bf194d224b"}, ] [package.extras] -docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)"] -testing = ["flake8 (<5)", "func-timeout", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)"] +docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] +testing = ["big-O", "flake8 (<5)", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)"] [extras] asap7 = ["gdspy"] From 02d0cf2bbce064669bc2caf8a0ac393266622369 Mon Sep 17 00:00:00 2001 From: Bryan Ngo Date: Thu, 23 Mar 2023 17:21:11 -0700 Subject: [PATCH 21/36] mermaid generator automatically writes to file --- hammer/flowgraph/node.py | 11 +++++++++-- tests/test_node.py | 16 +++++++++------- 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/hammer/flowgraph/node.py b/hammer/flowgraph/node.py index 9c03d6dad..c5b936cfb 100644 --- a/hammer/flowgraph/node.py +++ b/hammer/flowgraph/node.py @@ -310,19 +310,26 @@ def to_json(self) -> dict: def to_d2(self) -> Any: raise NotImplementedError() - def to_mermaid(self, fname: str) -> None: + def to_mermaid(self) -> str: """Converts the flowgraph into Mermaid format for visualization. Args: fname (str): Output file name. + + Returns: + str: Path to Mermaid Markdown file. """ + folder = os.path.dirname(list(self.networkx.nodes)[0].pull_dir) + fname = os.path.join(folder, "graph_viz.md") with open(fname, 'w', encoding="utf-8") as f: - f.write("stateDiagram-v2\n") + f.write("```mermaid\nstateDiagram-v2\n") for start in self.networkx: f.writelines( f" {start.action} --> {child.action}\n" for child in nx.neighbors(self.networkx, start) ) + f.write("```\n") + return fname def convert_to_acyclic(g: Graph) -> Graph: """Eliminates cycles in a flowgraph for analysis. diff --git a/tests/test_node.py b/tests/test_node.py index d8956e883..ca53569cd 100644 --- a/tests/test_node.py +++ b/tests/test_node.py @@ -455,13 +455,15 @@ def test_mermaid(self) -> None: par: [] }, auto_auxiliary=False) - g.to_mermaid(os.path.join(td, "mermaid.md")) - with open(os.path.join(td, "mermaid.md"), 'r', encoding="utf-8") as f: + fname = g.to_mermaid() + with open(fname, 'r', encoding="utf-8") as f: s = f.readlines() self.assertListEqual(s, - ["stateDiagram-v2\n", + ["```mermaid\n", + "stateDiagram-v2\n", " syn --> syn-to-par\n", - " syn-to-par --> par\n"]) + " syn-to-par --> par\n", + "```\n"]) def test_auto_auxiliary(self) -> None: """ @@ -535,8 +537,8 @@ def test_auto_auxiliary(self) -> None: syn: [par], par: [] }) - self.assertEqual(len(g.networkx), 3) # check that there are three nodes - self.assertEqual(len(g.networkx.edges), 2) # check that there are two edge connections + self.assertEqual(g.networkx.number_of_nodes(), 3) # check that there are three nodes + self.assertEqual(g.networkx.number_of_edges(), 2) # check that there are two edge connections g.run(syn) for n in g.networkx: @@ -624,7 +626,7 @@ def test_encode_decode(self) -> None: out = json.dumps(g.to_json(), cls=node.NodeEncoder) g_dec = json.loads(out, object_hook=node.as_node) # print(g.to_json()) - print(json_graph.node_link_graph(g_dec).nodes) + # print(json_graph.node_link_graph(g_dec).nodes) if __name__ == "__main__": unittest.main() From f8ae7e2f6dd8c257c8f4f1b483a6e1abec8c6e40 Mon Sep 17 00:00:00 2001 From: Bryan Ngo Date: Fri, 24 Mar 2023 12:13:48 -0700 Subject: [PATCH 22/36] implement hook test and direct imports --- hammer/flowgraph/node.py | 25 ++-- tests/test_node.py | 315 +++++++++++++-------------------------- 2 files changed, 117 insertions(+), 223 deletions(-) diff --git a/hammer/flowgraph/node.py b/hammer/flowgraph/node.py index c5b936cfb..cc196252a 100644 --- a/hammer/flowgraph/node.py +++ b/hammer/flowgraph/node.py @@ -20,7 +20,7 @@ from networkx.readwrite import json_graph from hammer.logging import HammerVLSILogging -from hammer.vlsi import cli_driver +from hammer.vlsi.cli_driver import CLIDriver class Status(Enum): @@ -52,7 +52,7 @@ class Node: required_outputs: list[str] status: Status = Status.NOT_RUN # __uuid: uuid.UUID = field(default_factory=uuid.uuid4) - driver: str = "" + driver: CLIDriver = field(default_factory=CLIDriver) optional_inputs: list[str] = field(default_factory=list) optional_outputs: list[str] = field(default_factory=list) step_controls: dict[str, str] = field(default_factory=lambda: { @@ -247,14 +247,16 @@ def run(self, start: Node) -> Any: if not start.privileged and any(i.privileged for i in self.networkx): raise RuntimeError("Attempting to run non-privileged node in privileged flow. Please complete your stepped flow first.") - if start.driver != "": - driver_pkg_path, driver_module = start.driver.rsplit('.', 1) - driver_pkg = importlib.import_module(driver_pkg_path) - driver = getattr(driver_pkg, driver_module)() - if not isinstance(driver, cli_driver.CLIDriver): - raise TypeError(f"Driver {driver} does not extend CLIDriver, cannot run a flow.") - else: - driver = cli_driver.CLIDriver() + # if start.driver != "": + # driver_pkg_path, driver_module = start.driver.rsplit('.', 1) + # driver_pkg = importlib.import_module(driver_pkg_path) + # driver = getattr(driver_pkg, driver_module)() + # if not isinstance(driver, cli_driver.CLIDriver): + # raise TypeError(f"Driver {driver} does not extend CLIDriver, cannot run a flow.") + # else: + # driver = cli_driver.CLIDriver() + + driver = start.driver arg_list = { "action": start.action, @@ -307,9 +309,6 @@ def to_json(self) -> dict: """ return json_graph.node_link_data(self.networkx) - def to_d2(self) -> Any: - raise NotImplementedError() - def to_mermaid(self) -> str: """Converts the flowgraph into Mermaid format for visualization. diff --git a/tests/test_node.py b/tests/test_node.py index ca53569cd..9e8807048 100644 --- a/tests/test_node.py +++ b/tests/test_node.py @@ -8,11 +8,59 @@ import pytest from networkx.readwrite import json_graph +from hammer.vlsi.cli_driver import ( + CLIDriver, + HammerTool, + HammerToolHookAction +) from hammer.flowgraph import node from hammer.flowgraph.node import Graph, Node, Status from hammer.logging import HammerVLSILogging +from hammer.vlsi import HammerTool +MOCK_CFG = dedent(""" +synthesis.inputs: + input_files: ["LICENSE", "README.md"] + top_module: "z1top.xdc" + +par.inputs: + input_files: ["LICENSE", "README.md"] + top_module: "z1top.xdc" + +drc.inputs: + input_files: ["LICENSE", "README.md"] + top_module: "z1top.xdc" + +lvs.inputs: + input_files: ["LICENSE", "README.md"] + schematic_files: ["LICENSE", "README.md"] + top_module: "z1top.xdc" + hcells_list: [] + +pcb.inputs: + top_module: "z1top.xdc" + +formal.inputs: + input_files: ["LICENSE", "README.md"] + top_module: "z1top.xdc" + +sim.inputs: + input_files: ["LICENSE", "README.md"] + top_module: "z1top.xdc" + +vlsi: + core: + technology: "hammer.technology.nop" + + synthesis_tool: "hammer.synthesis.nop" + par_tool: "hammer.par.nop" + drc_tool: "hammer.drc.nop" + lvs_tool: "hammer.lvs.nop" + power_tool: "hammer.power.nop" + sim_tool: "mocksim" +""") + class TestNode(unittest.TestCase): def test_initialize_node(self) -> None: @@ -170,54 +218,12 @@ def test_run_basic(self) -> None: HammerVLSILogging.clear_callbacks() HammerVLSILogging.add_callback(HammerVLSILogging.callback_buffering) - cfg = dedent(""" - synthesis.inputs: - input_files: ["LICENSE", "README.md"] - top_module: "z1top.xdc" - - par.inputs: - input_files: ["LICENSE", "README.md"] - top_module: "z1top.xdc" - - drc.inputs: - input_files: ["LICENSE", "README.md"] - top_module: "z1top.xdc" - - lvs.inputs: - input_files: ["LICENSE", "README.md"] - schematic_files: ["LICENSE", "README.md"] - top_module: "z1top.xdc" - hcells_list: [] - - pcb.inputs: - top_module: "z1top.xdc" - - formal.inputs: - input_files: ["LICENSE", "README.md"] - top_module: "z1top.xdc" - - sim.inputs: - input_files: ["LICENSE", "README.md"] - top_module: "z1top.xdc" - - vlsi: - core: - technology: "hammer.technology.nop" - - synthesis_tool: "hammer.synthesis.nop" - par_tool: "hammer.par.nop" - drc_tool: "hammer.drc.nop" - lvs_tool: "hammer.lvs.nop" - power_tool: "hammer.power.nop" - sim_tool: "mocksim" - """) - with tempfile.TemporaryDirectory() as td: os.mkdir(os.path.join(td, "syn_dir")) os.mkdir(os.path.join(td, "par_dir")) with open(os.path.join(td, "syn_dir", "syn-in.yml"), 'w', encoding="utf-8") as tf1: - tf1.write(cfg) + tf1.write(MOCK_CFG) syn = Node( "syn", "nop", @@ -255,54 +261,12 @@ def test_invalid_run(self) -> None: HammerVLSILogging.clear_callbacks() HammerVLSILogging.add_callback(HammerVLSILogging.callback_buffering) - cfg = dedent(""" - synthesis.inputs: - input_files: ["LICENSE", "README.md"] - top_module: "z1top.xdc" - - par.inputs: - input_files: ["LICENSE", "README.md"] - top_module: "z1top.xdc" - - drc.inputs: - input_files: ["LICENSE", "README.md"] - top_module: "z1top.xdc" - - lvs.inputs: - input_files: ["LICENSE", "README.md"] - schematic_files: ["LICENSE", "README.md"] - top_module: "z1top.xdc" - hcells_list: [] - - pcb.inputs: - top_module: "z1top.xdc" - - formal.inputs: - input_files: ["LICENSE", "README.md"] - top_module: "z1top.xdc" - - sim.inputs: - input_files: ["LICENSE", "README.md"] - top_module: "z1top.xdc" - - vlsi: - core: - technology: "hammer.technology.nop" - - synthesis_tool: "hammer.synthesis.nop" - par_tool: "hammer.par.nop" - drc_tool: "hammer.drc.nop" - lvs_tool: "hammer.lvs.nop" - power_tool: "hammer.power.nop" - sim_tool: "mocksim" - """) - with tempfile.TemporaryDirectory() as td: os.mkdir(os.path.join(td, "syn_dir")) os.mkdir(os.path.join(td, "par_dir")) with open(os.path.join(td, "syn_dir", "syn-in.yml"), 'w', encoding="utf-8") as tf1: - tf1.write(cfg) + tf1.write(MOCK_CFG) syn = Node( "syn", "nop", @@ -340,54 +304,12 @@ def test_resume_graph(self) -> None: HammerVLSILogging.clear_callbacks() HammerVLSILogging.add_callback(HammerVLSILogging.callback_buffering) - cfg = dedent(""" - synthesis.inputs: - input_files: ["LICENSE", "README.md"] - top_module: "z1top.xdc" - - par.inputs: - input_files: ["LICENSE", "README.md"] - top_module: "z1top.xdc" - - drc.inputs: - input_files: ["LICENSE", "README.md"] - top_module: "z1top.xdc" - - lvs.inputs: - input_files: ["LICENSE", "README.md"] - schematic_files: ["LICENSE", "README.md"] - top_module: "z1top.xdc" - hcells_list: [] - - pcb.inputs: - top_module: "z1top.xdc" - - formal.inputs: - input_files: ["LICENSE", "README.md"] - top_module: "z1top.xdc" - - sim.inputs: - input_files: ["LICENSE", "README.md"] - top_module: "z1top.xdc" - - vlsi: - core: - technology: "hammer.technology.nop" - - synthesis_tool: "hammer.synthesis.nop" - par_tool: "hammer.par.nop" - drc_tool: "hammer.drc.nop" - lvs_tool: "hammer.lvs.nop" - power_tool: "hammer.power.nop" - sim_tool: "mocksim" - """) - with tempfile.TemporaryDirectory() as td: os.mkdir(os.path.join(td, "syn_dir")) os.mkdir(os.path.join(td, "par_dir")) with open(os.path.join(td, "syn_dir", "syn-in.yml"), 'w', encoding="utf-8") as tf1: - tf1.write(cfg) + tf1.write(MOCK_CFG) syn = Node( "syn", "nop", @@ -472,54 +394,13 @@ def test_auto_auxiliary(self) -> None: HammerVLSILogging.clear_callbacks() HammerVLSILogging.add_callback(HammerVLSILogging.callback_buffering) - cfg = dedent(""" - synthesis.inputs: - input_files: ["LICENSE", "README.md"] - top_module: "z1top.xdc" - - par.inputs: - input_files: ["LICENSE", "README.md"] - top_module: "z1top.xdc" - - drc.inputs: - input_files: ["LICENSE", "README.md"] - top_module: "z1top.xdc" - - lvs.inputs: - input_files: ["LICENSE", "README.md"] - schematic_files: ["LICENSE", "README.md"] - top_module: "z1top.xdc" - hcells_list: [] - - pcb.inputs: - top_module: "z1top.xdc" - - formal.inputs: - input_files: ["LICENSE", "README.md"] - top_module: "z1top.xdc" - - sim.inputs: - input_files: ["LICENSE", "README.md"] - top_module: "z1top.xdc" - - vlsi: - core: - technology: "hammer.technology.nop" - - synthesis_tool: "hammer.synthesis.nop" - par_tool: "hammer.par.nop" - drc_tool: "hammer.drc.nop" - lvs_tool: "hammer.lvs.nop" - power_tool: "hammer.power.nop" - sim_tool: "mocksim" - """) with tempfile.TemporaryDirectory() as td: os.mkdir(os.path.join(td, "syn_dir")) os.mkdir(os.path.join(td, "par_dir")) with open(os.path.join(td, "syn_dir", "syn-in.yml"), 'w', encoding="utf-8") as tf1: - tf1.write(cfg) + tf1.write(MOCK_CFG) syn = Node( "syn", "nop", @@ -544,61 +425,66 @@ def test_auto_auxiliary(self) -> None: for n in g.networkx: self.assertEqual(n.status, Status.COMPLETE) - def test_encode_decode(self) -> None: + def test_flowgraph_hooks(self) -> None: """ - Test that a flowgraph can be encoded and decoded. + Test that hooks can be used in flowgraphs. """ - HammerVLSILogging.clear_callbacks() - HammerVLSILogging.add_callback(HammerVLSILogging.callback_buffering) - - cfg = dedent(""" - synthesis.inputs: - input_files: ["LICENSE", "README.md"] - top_module: "z1top.xdc" + with tempfile.TemporaryDirectory() as td: + syn_dir = os.path.join(td, "syn_dir") + out_dir = os.path.join(td, "out_dir") + os.mkdir(syn_dir) + os.mkdir(out_dir) - par.inputs: - input_files: ["LICENSE", "README.md"] - top_module: "z1top.xdc" + cfg = dedent(f""" + vlsi.core: + synthesis_tool: hammer.synthesis.mocksynth + technology: hammer.technology.nop - drc.inputs: - input_files: ["LICENSE", "README.md"] - top_module: "z1top.xdc" + synthesis.inputs: + top_module: dummy + input_files: ["/dev/null"] - lvs.inputs: - input_files: ["LICENSE", "README.md"] - schematic_files: ["LICENSE", "README.md"] - top_module: "z1top.xdc" - hcells_list: [] + synthesis.mocksynth.temp_folder: {out_dir} + """) - pcb.inputs: - top_module: "z1top.xdc" + with open(os.path.join(syn_dir, "syn-in.yml"), 'w', encoding="utf-8") as tf1: + tf1.write(cfg) - formal.inputs: - input_files: ["LICENSE", "README.md"] - top_module: "z1top.xdc" + syn = Node( + "syn", "mocksynth", + syn_dir, out_dir, + ["syn-in.yml"], + ["syn-out.json"], + driver=NodeDummyDriver() + ) - sim.inputs: - input_files: ["LICENSE", "README.md"] - top_module: "z1top.xdc" + g = Graph({ + syn: [] + }) + g.run(syn) - vlsi: - core: - technology: "hammer.technology.nop" + for i in range(1, 5): + file = os.path.join(out_dir, f"step{i}.txt") + if i in (2, 4): + self.assertFalse(os.path.exists(file)) + else: + self.assertTrue(os.path.exists(file)) - synthesis_tool: "hammer.synthesis.nop" - par_tool: "hammer.par.nop" - drc_tool: "hammer.drc.nop" - lvs_tool: "hammer.lvs.nop" - power_tool: "hammer.power.nop" - sim_tool: "mocksim" - """) + @pytest.mark.skip + def test_encode_decode(self) -> None: + """ + Test that a flowgraph can be encoded and decoded. + """ + HammerVLSILogging.clear_callbacks() + HammerVLSILogging.add_callback(HammerVLSILogging.callback_buffering) with tempfile.TemporaryDirectory() as td: os.mkdir(os.path.join(td, "syn_dir")) os.mkdir(os.path.join(td, "par_dir")) with open(os.path.join(td, "syn_dir", "syn-in.yml"), 'w', encoding="utf-8") as tf1: - tf1.write(cfg) + tf1.write(MOCK_CFG) + syn = Node( "syn", "nop", os.path.join(td, "syn_dir"), os.path.join(td, "s2p_dir"), @@ -628,5 +514,14 @@ def test_encode_decode(self) -> None: # print(g.to_json()) # print(json_graph.node_link_graph(g_dec).nodes) +class NodeDummyDriver(CLIDriver): + def get_extra_synthesis_hooks(self) -> list[HammerToolHookAction]: + extra_hooks = [ + HammerTool.make_removal_hook("step2"), + HammerTool.make_removal_hook("step4"), + ] + return extra_hooks + + if __name__ == "__main__": unittest.main() From 117516348bc66aa4e636b8ba1717d78190e53cc1 Mon Sep 17 00:00:00 2001 From: Bryan Ngo Date: Mon, 27 Mar 2023 21:14:05 -0700 Subject: [PATCH 23/36] change runner to iteratively run nodes via BFS --- hammer/flowgraph/node.py | 67 +++++++++++++++++++++------------------- 1 file changed, 36 insertions(+), 31 deletions(-) diff --git a/hammer/flowgraph/node.py b/hammer/flowgraph/node.py index cc196252a..1854c4d29 100644 --- a/hammer/flowgraph/node.py +++ b/hammer/flowgraph/node.py @@ -8,7 +8,6 @@ # pylint: disable=invalid-name -import importlib import json import os import uuid @@ -247,23 +246,34 @@ def run(self, start: Node) -> Any: if not start.privileged and any(i.privileged for i in self.networkx): raise RuntimeError("Attempting to run non-privileged node in privileged flow. Please complete your stepped flow first.") - # if start.driver != "": - # driver_pkg_path, driver_module = start.driver.rsplit('.', 1) - # driver_pkg = importlib.import_module(driver_pkg_path) - # driver = getattr(driver_pkg, driver_module)() - # if not isinstance(driver, cli_driver.CLIDriver): - # raise TypeError(f"Driver {driver} does not extend CLIDriver, cannot run a flow.") - # else: - # driver = cli_driver.CLIDriver() + start_code = Graph.__run_single(start) + if start_code != 0: + return self + else: + for _, c in nx.bfs_edges(self.networkx, start): + code = Graph.__run_single(c) + if code != 0: + break + return self - driver = start.driver + @staticmethod + def __run_single(node: Node) -> int: + """Helper function to run a HAMMER node. + + Args: + node (Node): Node to run action on. + + Returns: + int: Status code. + """ + driver = node.driver arg_list = { - "action": start.action, + "action": node.action, 'environment_config': None, - 'configs': [os.path.join(start.pull_dir, i) for i in start.required_inputs], + 'configs': [os.path.join(node.pull_dir, i) for i in node.required_inputs], 'log': None, - 'obj_dir': start.push_dir, + 'obj_dir': node.push_dir, 'syn_rundir': '', 'par_rundir': '', 'drc_rundir': '', @@ -272,12 +282,12 @@ def run(self, start: Node) -> Any: 'power_rundir': '', 'formal_rundir': '', 'timing_rundir': '', - 'from_step': start.step_controls["from_step"], - 'after_step': start.step_controls["after_step"], - 'to_step': start.step_controls["to_step"], - 'until_step': start.step_controls["until_step"], - 'only_step': start.step_controls["only_step"], - 'output': os.path.join(start.push_dir, start.required_outputs[0]), # TODO: fix this + 'from_step': node.step_controls["from_step"], + 'after_step': node.step_controls["after_step"], + 'to_step': node.step_controls["to_step"], + 'until_step': node.step_controls["until_step"], + 'only_step': node.step_controls["only_step"], + 'output': os.path.join(node.push_dir, node.required_outputs[0]), # TODO: fix this 'verilog': None, 'firrtl': None, 'top': None, @@ -285,21 +295,16 @@ def run(self, start: Node) -> Any: 'dump_history': False } - start.status = Status.RUNNING - ctxt = HammerVLSILogging.context(start.action) - ctxt.info(f"Running graph step {start.action}") + node.status = Status.RUNNING + ctxt = HammerVLSILogging.context(node.action) + ctxt.info(f"Running graph step {node.action}") code = driver.run_main_parsed(arg_list) if code == 0: - start.status = Status.COMPLETE + node.status = Status.COMPLETE else: - start.status = Status.INCOMPLETE - ctxt.fatal(f"Step {start.action} failed") - return self - - for c in nx.neighbors(self.networkx, start): - self.run(c) - - return self + node.status = Status.INCOMPLETE + ctxt.fatal(f"Step {node.action} failed") + return code def to_json(self) -> dict: """Encodes a graph as a JSON string. From 812b763950f71ef88a2af5f5c3aac6a55f26b8b5 Mon Sep 17 00:00:00 2001 From: Bryan Ngo Date: Mon, 27 Mar 2023 21:33:32 -0700 Subject: [PATCH 24/36] add mermaid support to docs --- doc/conf.py | 3 ++- poetry.lock | 50 +++++++++++++++++++++++++++++++------------------- pyproject.toml | 1 + 3 files changed, 34 insertions(+), 20 deletions(-) diff --git a/doc/conf.py b/doc/conf.py index 443fa8815..afbd1f5aa 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -31,7 +31,8 @@ # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. extensions = [ - "myst_parser" + "myst_parser", + "sphinxcontrib.mermaid" ] # Add any paths that contain templates here, relative to this directory. diff --git a/poetry.lock b/poetry.lock index 8cfb05fba..3f0e7997b 100644 --- a/poetry.lock +++ b/poetry.lock @@ -14,14 +14,14 @@ files = [ [[package]] name = "astroid" -version = "2.15.0" +version = "2.15.1" description = "An abstract syntax tree for Python with inference support." category = "dev" optional = false python-versions = ">=3.7.2" files = [ - {file = "astroid-2.15.0-py3-none-any.whl", hash = "sha256:e3e4d0ffc2d15d954065579689c36aac57a339a4679a679579af6401db4d3fdb"}, - {file = "astroid-2.15.0.tar.gz", hash = "sha256:525f126d5dc1b8b0b6ee398b33159105615d92dc4a17f2cd064125d57f6186fa"}, + {file = "astroid-2.15.1-py3-none-any.whl", hash = "sha256:89860bda98fe2bbd1f5d262229be7629d778ce280de68d95d4a73d1f592ad268"}, + {file = "astroid-2.15.1.tar.gz", hash = "sha256:af4e0aff46e2868218502789898269ed95b663fba49e65d91c1e09c966266c34"}, ] [package.dependencies] @@ -228,19 +228,19 @@ test = ["pytest (>=6)"] [[package]] name = "filelock" -version = "3.10.3" +version = "3.10.7" description = "A platform independent file lock." category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "filelock-3.10.3-py3-none-any.whl", hash = "sha256:99d6282f732410d44242ca02aa49835cf5473e2dd4d6734a2a785c8889dc191e"}, - {file = "filelock-3.10.3.tar.gz", hash = "sha256:a26bfa34d26293e04886dff13fa8dd0c8c6e1a786b723c689755fe8939297410"}, + {file = "filelock-3.10.7-py3-none-any.whl", hash = "sha256:bde48477b15fde2c7e5a0713cbe72721cb5a5ad32ee0b8f419907960b9d75536"}, + {file = "filelock-3.10.7.tar.gz", hash = "sha256:892be14aa8efc01673b5ed6589dbccb95f9a8596f0507e232626155495c18105"}, ] [package.extras] docs = ["furo (>=2022.12.7)", "sphinx (>=6.1.3)", "sphinx-autodoc-typehints (>=1.22,!=1.23.4)"] -testing = ["covdefaults (>=2.3)", "coverage (>=7.2.2)", "pytest (>=7.2.2)", "pytest-cov (>=4)", "pytest-timeout (>=2.1)"] +testing = ["covdefaults (>=2.3)", "coverage (>=7.2.2)", "diff-cover (>=7.5)", "pytest (>=7.2.2)", "pytest-cov (>=4)", "pytest-mock (>=3.10)", "pytest-timeout (>=2.1)"] [[package]] name = "gdspy" @@ -730,19 +730,19 @@ files = [ [[package]] name = "platformdirs" -version = "3.1.1" +version = "3.2.0" description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "platformdirs-3.1.1-py3-none-any.whl", hash = "sha256:e5986afb596e4bb5bde29a79ac9061aa955b94fca2399b7aaac4090860920dd8"}, - {file = "platformdirs-3.1.1.tar.gz", hash = "sha256:024996549ee88ec1a9aa99ff7f8fc819bb59e2c3477b410d90a16d32d6e707aa"}, + {file = "platformdirs-3.2.0-py3-none-any.whl", hash = "sha256:ebe11c0d7a805086e99506aa331612429a72ca7cd52a1f0d277dc4adc20cb10e"}, + {file = "platformdirs-3.2.0.tar.gz", hash = "sha256:d5b638ca397f25f979350ff789db335903d7ea010ab28903f57b27e1b16c2b08"}, ] [package.extras] docs = ["furo (>=2022.12.7)", "proselint (>=0.13)", "sphinx (>=6.1.3)", "sphinx-autodoc-typehints (>=1.22,!=1.23.4)"] -test = ["appdirs (==1.4.4)", "covdefaults (>=2.2.2)", "pytest (>=7.2.1)", "pytest-cov (>=4)", "pytest-mock (>=3.10)"] +test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.2.2)", "pytest-cov (>=4)", "pytest-mock (>=3.10)"] [[package]] name = "pluggy" @@ -1187,6 +1187,18 @@ files = [ [package.extras] test = ["flake8", "mypy", "pytest"] +[[package]] +name = "sphinxcontrib-mermaid" +version = "0.8.1" +description = "Mermaid diagrams in yours Sphinx powered docs" +category = "main" +optional = false +python-versions = ">=3.7" +files = [ + {file = "sphinxcontrib-mermaid-0.8.1.tar.gz", hash = "sha256:fa3e5325d4ba395336e6137d113f55026b1a03ccd115dc54113d1d871a580466"}, + {file = "sphinxcontrib_mermaid-0.8.1-py3-none-any.whl", hash = "sha256:15491c24ec78cf1626b1e79e797a9ce87cb7959cf38f955eb72dd5512aeb6ce9"}, +] + [[package]] name = "sphinxcontrib-qthelp" version = "1.0.3" @@ -1233,14 +1245,14 @@ files = [ [[package]] name = "tomlkit" -version = "0.11.6" +version = "0.11.7" description = "Style preserving TOML library" category = "dev" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" files = [ - {file = "tomlkit-0.11.6-py3-none-any.whl", hash = "sha256:07de26b0d8cfc18f871aec595fda24d95b08fef89d147caa861939f37230bf4b"}, - {file = "tomlkit-0.11.6.tar.gz", hash = "sha256:71b952e5721688937fb02cf9d354dbcf0785066149d2855e44531ebdd2b65d73"}, + {file = "tomlkit-0.11.7-py3-none-any.whl", hash = "sha256:5325463a7da2ef0c6bbfefb62a3dc883aebe679984709aee32a317907d0a8d3c"}, + {file = "tomlkit-0.11.7.tar.gz", hash = "sha256:f392ef70ad87a672f02519f99967d28a4d3047133e2d1df936511465fbb3791d"}, ] [[package]] @@ -1271,14 +1283,14 @@ testing = ["flaky (>=3.4.0)", "freezegun (>=0.3.11)", "pathlib2 (>=2.3.3)", "psu [[package]] name = "types-pyyaml" -version = "6.0.12.8" +version = "6.0.12.9" description = "Typing stubs for PyYAML" category = "dev" optional = false python-versions = "*" files = [ - {file = "types-PyYAML-6.0.12.8.tar.gz", hash = "sha256:19304869a89d49af00be681e7b267414df213f4eb89634c4495fa62e8f942b9f"}, - {file = "types_PyYAML-6.0.12.8-py3-none-any.whl", hash = "sha256:5314a4b2580999b2ea06b2e5f9a7763d860d6e09cdf21c0e9561daa9cbd60178"}, + {file = "types-PyYAML-6.0.12.9.tar.gz", hash = "sha256:c51b1bd6d99ddf0aa2884a7a328810ebf70a4262c292195d3f4f9a0005f9eeb6"}, + {file = "types_PyYAML-6.0.12.9-py3-none-any.whl", hash = "sha256:5aed5aa66bd2d2e158f75dda22b059570ede988559f030cf294871d3b647e3e8"}, ] [[package]] @@ -1439,4 +1451,4 @@ asap7-gdstk = ["gdstk"] [metadata] lock-version = "2.0" python-versions = "^3.9" -content-hash = "67c4116b3ad38c850c787570708e14362df542402503fa53b6414f7aaa598644" +content-hash = "905376dcbe86ee41ff3fc09b22e3cf3cd05e40e2cf66a327f5412816e01c3c24" diff --git a/pyproject.toml b/pyproject.toml index b630cebed..9f5d8a08c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -26,6 +26,7 @@ PyYAML = "^6.0" "ruamel.yaml" = "^0.17.21" networkx = "^3.0" numpy = "^1.23.0" +sphinxcontrib-mermaid = "^0.8.1" gdstk = { version = "^0.9.0", optional = true } gdspy = { version = "1.4", optional = true } From 673adfaf04ca7ec60da6d25321f23349fb25e2a2 Mon Sep 17 00:00:00 2001 From: Bryan Ngo Date: Mon, 27 Mar 2023 21:46:52 -0700 Subject: [PATCH 25/36] simplify module imports --- hammer/flowgraph/__init__.py | 5 +++++ hammer/flowgraph/{node.py => flowgraph.py} | 5 ----- tests/test_node.py | 17 ++++++++--------- 3 files changed, 13 insertions(+), 14 deletions(-) create mode 100644 hammer/flowgraph/__init__.py rename hammer/flowgraph/{node.py => flowgraph.py} (98%) diff --git a/hammer/flowgraph/__init__.py b/hammer/flowgraph/__init__.py new file mode 100644 index 000000000..38b16ffff --- /dev/null +++ b/hammer/flowgraph/__init__.py @@ -0,0 +1,5 @@ +# Hammer logging code. +# +# See LICENSE for licence details. + +from .flowgraph import * diff --git a/hammer/flowgraph/node.py b/hammer/flowgraph/flowgraph.py similarity index 98% rename from hammer/flowgraph/node.py rename to hammer/flowgraph/flowgraph.py index 1854c4d29..6a49401c9 100644 --- a/hammer/flowgraph/node.py +++ b/hammer/flowgraph/flowgraph.py @@ -33,9 +33,6 @@ class Status(Enum): COMPLETE = "COMPLETE" -# separate required validity checking and optional validity checking -# meta dict for tech compatibilty - @dataclass class Node: """Defines a node for an action in a flowgraph. @@ -364,5 +361,3 @@ def convert_to_acyclic(g: Graph) -> Graph: # TODO: serialization format # TODO: cycles are conditional on user input -# TODO: write tests for hooks/steps -# TODO: make custom driver and tech for steps diff --git a/tests/test_node.py b/tests/test_node.py index 9e8807048..2faff83ad 100644 --- a/tests/test_node.py +++ b/tests/test_node.py @@ -6,17 +6,16 @@ import networkx as nx import pytest -from networkx.readwrite import json_graph from hammer.vlsi.cli_driver import ( CLIDriver, HammerTool, HammerToolHookAction ) -from hammer.flowgraph import node -from hammer.flowgraph.node import Graph, Node, Status + +from hammer import flowgraph +from hammer.flowgraph import convert_to_acyclic, Graph, Node, Status from hammer.logging import HammerVLSILogging -from hammer.vlsi import HammerTool MOCK_CFG = dedent(""" @@ -127,7 +126,7 @@ def test_cycle_reduction(self) -> None: v2: [v0], }) self.assertTrue(len(nx.find_cycle(g.networkx)) > 0) - g_acyclic = node.convert_to_acyclic(g) + g_acyclic = convert_to_acyclic(g) with self.assertRaises(nx.NetworkXNoCycle): nx.find_cycle(g_acyclic.networkx) self.assertEqual(len(g_acyclic.networkx), 4) @@ -162,7 +161,7 @@ def test_big_cycle_reduction(self) -> None: v3: [v0] }) self.assertTrue(len(nx.find_cycle(g.networkx)) > 0) - g_acyclic = node.convert_to_acyclic(g) + g_acyclic = convert_to_acyclic(g) with self.assertRaises(nx.NetworkXNoCycle): nx.find_cycle(g_acyclic.networkx) self.assertEqual(len(g_acyclic.networkx), 5) @@ -209,7 +208,7 @@ def test_multi_cycle_reduction(self) -> None: v5: [v3] }) self.assertTrue(len(nx.find_cycle(g.networkx)) > 0) - g_acyclic = node.convert_to_acyclic(g) + g_acyclic = convert_to_acyclic(g) with self.assertRaises(nx.NetworkXNoCycle): nx.find_cycle(g_acyclic.networkx) @@ -509,8 +508,8 @@ def test_encode_decode(self) -> None: par: [] }) - out = json.dumps(g.to_json(), cls=node.NodeEncoder) - g_dec = json.loads(out, object_hook=node.as_node) + out = json.dumps(g.to_json(), cls=flowgraph.NodeEncoder) + g_dec = json.loads(out, object_hook=flowgraph.as_node) # print(g.to_json()) # print(json_graph.node_link_graph(g_dec).nodes) From 4fcb13d4d5d7bfb6f123037488e2a4702e3f97bf Mon Sep 17 00:00:00 2001 From: Bryan Ngo Date: Mon, 27 Mar 2023 22:24:16 -0700 Subject: [PATCH 26/36] rename test --- tests/{test_node.py => test_flowgraph.py} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename tests/{test_node.py => test_flowgraph.py} (99%) diff --git a/tests/test_node.py b/tests/test_flowgraph.py similarity index 99% rename from tests/test_node.py rename to tests/test_flowgraph.py index 2faff83ad..ce9f50fdb 100644 --- a/tests/test_node.py +++ b/tests/test_flowgraph.py @@ -60,7 +60,7 @@ sim_tool: "mocksim" """) -class TestNode(unittest.TestCase): +class TestFlowgraph(unittest.TestCase): def test_initialize_node(self) -> None: """Test that we can instantiate a node.""" From 1cbdcddef590107a6aa80fc6040e765d26e524d7 Mon Sep 17 00:00:00 2001 From: Bryan Ngo Date: Tue, 28 Mar 2023 15:05:29 -0700 Subject: [PATCH 27/36] start documentation --- doc/Hammer-Use/Flowgraphs.rst | 156 ++++++++++++++++++++++++++++++++++ doc/Hammer-Use/index.rst | 1 + hammer/flowgraph/flowgraph.py | 7 +- tests/test_flowgraph.py | 4 +- 4 files changed, 162 insertions(+), 6 deletions(-) create mode 100644 doc/Hammer-Use/Flowgraphs.rst diff --git a/doc/Hammer-Use/Flowgraphs.rst b/doc/Hammer-Use/Flowgraphs.rst new file mode 100644 index 000000000..b394a579d --- /dev/null +++ b/doc/Hammer-Use/Flowgraphs.rst @@ -0,0 +1,156 @@ +.. _flowgraphs: + +Flowgraphs +========== + +Hammer has **experimental** support for flowgraph constructions, similar to tools like `mflowgen `_. +Their intention is to simplify the way flows are constructed and ran in Hammer. +They can be imported via the ``hammer.flowgraph`` module. + +Construction +------------ + +Flowgraphs are nothing more than a collection of ``Node`` instances linked together via a ``Graph`` instance. +Each ``Node`` "pulls" from a directory to feed in inputs and "pushes" output files to another directory to be used by other nodes. +``Node`` instances are roughly equivalent to a single call to the ``hammer-vlsi`` CLI, so they take in similar attributes: + +* The action being called +* The tool used to perform the action +* The pull and push directories +* Any *required* input/output files +* Any *optional* input/output files +* A driver to run the node with; this enables backwards compatibility with :ref:`hooks `. +* Options to specify steps within an action; this enables backwards compatibility with :ref:`flow control `. + + * ``from_step`` + * ``after_step`` + * ``to_step`` + * ``until_step`` + * ``only_step`` + +A minimal example of a ``Node``: + +.. code-block:: python + + from hammer.flowgraph import Node + + test = Node( + action="foo", + tool="nop", + pull_dir="foo_dir", + push_dir="/dev/null", + required_inputs=["foo.yml"], + required_outputs=["foo-out.json"], + ) + +Each ``Node`` has the ability to be "privileged", meaning that a flow *must* start with this node. +This only occurs when a flow is being controlled using any of the steps. + +Running a Flowgraph +------------------- + +``Node`` instances are linked together using an `adjacency list `_. +This list can be used to instantiate a ``Graph``: + +.. code-block:: python + + from hammer.flowgraph import Graph, Node + + root = Node( + "foo", "nop", "foo_dir", "", + ["foo.yml"], + ["foo-out.json"], + ) + child1 = Node( + "bar", "nop", "foo_dir", "bar_dir", + ["foo-out.json"], + ["bar-out.json"], + ) + graph = Graph({root: [child1]}) + +``Graph`` instances by default *automatically* insert auxiliary actions. +This means that actions such as ``syn-to-par`` or ``par-to-drc`` no longer need to be specified in a flow; the nodes are inserted by the flowgraph tool. +This feature can be disabled by setting ``auto_auxiliary=False``. + +A ``Graph`` can be run by calling the ``run`` method and passing in a starting node. +When running a flow, each ``Node`` keeps an internal status based on the status of the action being run: + +* ``NOT_RUN``: The action has yet to be run. +* ``RUNNING``: The action is currently running. +* ``COMPLETE``: The action has finished. +* ``INCOMPLETE``: The action ran into an error while being run. +* ``INVALID``: The action's outputs have been invalidated (e.g. inputs or attributes have changed). + +The interactions between the statuses are described in the diagram: + +.. mermaid:: + + stateDiagram-v2 + [*] --> NOT_RUN + NOT_RUN --> RUNNING + RUNNING --> INCOMPLETE + RUNNING --> COMPLETE + INCOMPLETE --> NOT_RUN + COMPLETE --> INVALID + INVALID --> NOT_RUN + +Regardless of whether a flow completes with or without errors, the graph at the time of completion or error is returned, allowing for a graph to be "resumed" once any errors have been fixed. + +Visualization +------------- + +A flowgraph can be visualized in Markdown files via the `Mermaid `_ tool. +Calling a ``Graph`` instance's ``to_mermaid`` method outputs a file named ``graph-viz.md``. +The file can be viewed in a site like `Mermaid's live editor `_ or using Github's native support. + +The flowgraph below would appear like this: + +.. code-block:: python + + from hammer.flowgraph import Graph, Node + + syn = Node( + "syn", "nop", + os.path.join(td, "syn_dir"), os.path.join(td, "s2p_dir"), + ["syn-in.yml"], + ["syn-out.json"], + ) + s2p = Node( + "syn-to-par", "nop", + os.path.join(td, "s2p_dir"), os.path.join(td, "par_dir"), + ["syn-out.json"], + ["s2p-out.json"], + ) + par = Node( + "par", "nop", + os.path.join(td, "par_dir"), os.path.join(td, "out_dir"), + ["s2p-out.json"], + ["par-out.json"], + ) + g = Graph({ + syn: [s2p], + s2p: [par], + par: [] + }) + + +Here are the contents of ``graph-viz.md`` after calling ``g.to_mermaid()``: + +.. code-block:: markdown + + ```mermaid + + stateDiagram-v2 + syn --> syn_to_par + syn_to_par --> par + ``` + +Which would render like this: + +.. mermaid:: + + stateDiagram-v2 + syn --> syn_to_par + syn_to_par --> par + +Note that the separators have been changed to comply with Mermaid syntax. diff --git a/doc/Hammer-Use/index.rst b/doc/Hammer-Use/index.rst index 2e29006e4..b608c0969 100644 --- a/doc/Hammer-Use/index.rst +++ b/doc/Hammer-Use/index.rst @@ -13,3 +13,4 @@ This documentation will walk through more advanced features of the Hammer infras Hooks Buildfile Hierarchical + Flowgraphs diff --git a/hammer/flowgraph/flowgraph.py b/hammer/flowgraph/flowgraph.py index 6a49401c9..415d495d7 100644 --- a/hammer/flowgraph/flowgraph.py +++ b/hammer/flowgraph/flowgraph.py @@ -24,7 +24,6 @@ class Status(Enum): """Represents the status of a node in the flowgraph. - https://tinyurl.com/2bstth7y """ NOT_RUN = "NOT_RUN" RUNNING = "RUNNING" @@ -195,7 +194,6 @@ def insert_auxiliary_actions(edge_list: dict[Node, list[Node]]) -> dict[Node, li ] changes = [] - edge_list_copy = edge_list.copy() for parent_idx, (parent, children) in enumerate(edge_list.items()): for child_idx, child in enumerate(children): if (parent.action, child.action) in valid_auxiliary_actions: @@ -210,6 +208,7 @@ def insert_auxiliary_actions(edge_list: dict[Node, list[Node]]) -> dict[Node, li ) changes.append((parent_idx, child_idx, aux_node)) + edge_list_copy = edge_list.copy() for parent_idx, child_idx, aux_node in changes: parent, children = list(edge_list_copy.items())[parent_idx] parent.push_dir = os.path.join( @@ -321,12 +320,12 @@ def to_mermaid(self) -> str: str: Path to Mermaid Markdown file. """ folder = os.path.dirname(list(self.networkx.nodes)[0].pull_dir) - fname = os.path.join(folder, "graph_viz.md") + fname = os.path.join(folder, "graph-viz.md") with open(fname, 'w', encoding="utf-8") as f: f.write("```mermaid\nstateDiagram-v2\n") for start in self.networkx: f.writelines( - f" {start.action} --> {child.action}\n" + f" {start.action.replace('-', '_')} --> {child.action.replace('-', '_')}\n" for child in nx.neighbors(self.networkx, start) ) f.write("```\n") diff --git a/tests/test_flowgraph.py b/tests/test_flowgraph.py index ce9f50fdb..a39f0361f 100644 --- a/tests/test_flowgraph.py +++ b/tests/test_flowgraph.py @@ -382,8 +382,8 @@ def test_mermaid(self) -> None: self.assertListEqual(s, ["```mermaid\n", "stateDiagram-v2\n", - " syn --> syn-to-par\n", - " syn-to-par --> par\n", + " syn --> syn_to_par\n", + " syn_to_par --> par\n", "```\n"]) def test_auto_auxiliary(self) -> None: From 689a88a8ee9e61e0dd8b303f1d9c0483dc539207 Mon Sep 17 00:00:00 2001 From: Bryan Ngo Date: Fri, 7 Apr 2023 15:37:42 -0700 Subject: [PATCH 28/36] fix wording --- doc/Hammer-Use/Flowgraphs.rst | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/doc/Hammer-Use/Flowgraphs.rst b/doc/Hammer-Use/Flowgraphs.rst index b394a579d..d798ed932 100644 --- a/doc/Hammer-Use/Flowgraphs.rst +++ b/doc/Hammer-Use/Flowgraphs.rst @@ -68,8 +68,9 @@ This list can be used to instantiate a ``Graph``: ) graph = Graph({root: [child1]}) -``Graph`` instances by default *automatically* insert auxiliary actions. -This means that actions such as ``syn-to-par`` or ``par-to-drc`` no longer need to be specified in a flow; the nodes are inserted by the flowgraph tool. +Using the Hammer CLI tool, separate actions are manually linked via an *auxiliary* action, such as ``syn-to-par``. +By using a flowgraph, ``Graph`` instances by default *automatically* insert auxiliary actions. +This means that actions no longer need to be specified in a flow; the necessary nodes are inserted by the flowgraph tool. This feature can be disabled by setting ``auto_auxiliary=False``. A ``Graph`` can be run by calling the ``run`` method and passing in a starting node. From 2159e636f37715e6a8dd8cab031403aee822923e Mon Sep 17 00:00:00 2001 From: Bryan Ngo Date: Thu, 11 May 2023 11:01:31 -0700 Subject: [PATCH 29/36] bump packages --- doc/conf.py | 24 +++-- poetry.lock | 282 +++++++++++++++++++++++++--------------------------- 2 files changed, 146 insertions(+), 160 deletions(-) diff --git a/doc/conf.py b/doc/conf.py index afbd1f5aa..8d154b6ce 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -17,12 +17,12 @@ # -- Project information ----------------------------------------------------- -project = 'Hammer' -copyright = '2023, Berkeley Architecture Research' -author = 'Berkeley Architecture Research' +project = "Hammer" +copyright = "2023, Berkeley Architecture Research" +author = "Berkeley Architecture Research" # The full version, including alpha/beta/rc tags -release = '1.0.0' +release = "1.0.0" # -- General configuration --------------------------------------------------- @@ -32,30 +32,32 @@ # ones. extensions = [ "myst_parser", - "sphinxcontrib.mermaid" + "sphinx-jsonschema", + "sphinx_rtd_size", + "sphinxcontrib.mermaid", ] # Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] +templates_path = ["_templates"] # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. # This pattern also affects html_static_path and html_extra_path. -exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] +exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"] -source_suffix = '.rst' +source_suffix = ".rst" -master_doc = 'index' +master_doc = "index" # -- Options for HTML output ------------------------------------------------- # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. # -html_theme = 'sphinx_rtd_theme' +html_theme = "sphinx_rtd_theme" html_theme_options = { - 'collapse_navigation': False, + "collapse_navigation": False, } # Add any paths that contain custom static files (such as style sheets) here, diff --git a/poetry.lock b/poetry.lock index 3f0e7997b..c19b1dc5d 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry and should not be changed by hand. +# This file is automatically @generated by Poetry 1.4.2 and should not be changed by hand. [[package]] name = "alabaster" @@ -14,14 +14,14 @@ files = [ [[package]] name = "astroid" -version = "2.15.1" +version = "2.15.4" description = "An abstract syntax tree for Python with inference support." category = "dev" optional = false python-versions = ">=3.7.2" files = [ - {file = "astroid-2.15.1-py3-none-any.whl", hash = "sha256:89860bda98fe2bbd1f5d262229be7629d778ce280de68d95d4a73d1f592ad268"}, - {file = "astroid-2.15.1.tar.gz", hash = "sha256:af4e0aff46e2868218502789898269ed95b663fba49e65d91c1e09c966266c34"}, + {file = "astroid-2.15.4-py3-none-any.whl", hash = "sha256:a1b8543ef9d36ea777194bc9b17f5f8678d2c56ee6a45b2c2f17eec96f242347"}, + {file = "astroid-2.15.4.tar.gz", hash = "sha256:c81e1c7fbac615037744d067a9bb5f9aeb655edf59b63ee8b59585475d6f80d8"}, ] [package.dependencies] @@ -32,25 +32,6 @@ wrapt = [ {version = ">=1.14,<2", markers = "python_version >= \"3.11\""}, ] -[[package]] -name = "attrs" -version = "22.2.0" -description = "Classes Without Boilerplate" -category = "dev" -optional = false -python-versions = ">=3.6" -files = [ - {file = "attrs-22.2.0-py3-none-any.whl", hash = "sha256:29e95c7f6778868dbd49170f98f8818f78f3dc5e0e37c0b1f474e3561b240836"}, - {file = "attrs-22.2.0.tar.gz", hash = "sha256:c9227bfc2f01993c03f68db37d1d15c9690188323c067c641f1a35ca58185f99"}, -] - -[package.extras] -cov = ["attrs[tests]", "coverage-enable-subprocess", "coverage[toml] (>=5.3)"] -dev = ["attrs[docs,tests]"] -docs = ["furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier", "zope.interface"] -tests = ["attrs[tests-no-zope]", "zope.interface"] -tests-no-zope = ["cloudpickle", "cloudpickle", "hypothesis", "hypothesis", "mypy (>=0.971,<0.990)", "mypy (>=0.971,<0.990)", "pympler", "pympler", "pytest (>=4.3.0)", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-mypy-plugins", "pytest-xdist[psutil]", "pytest-xdist[psutil]"] - [[package]] name = "babel" version = "2.12.1" @@ -65,14 +46,14 @@ files = [ [[package]] name = "certifi" -version = "2022.12.7" +version = "2023.5.7" description = "Python package for providing Mozilla's CA Bundle." category = "dev" optional = false python-versions = ">=3.6" files = [ - {file = "certifi-2022.12.7-py3-none-any.whl", hash = "sha256:4ad3232f5e926d6718ec31cfc1fcadfde020920e278684144551c91769c7bc18"}, - {file = "certifi-2022.12.7.tar.gz", hash = "sha256:35824b4c3a97115964b408844d64aa14db1cc518f6562e8d7261699d1350a9e3"}, + {file = "certifi-2023.5.7-py3-none-any.whl", hash = "sha256:c6c2e98f5c7869efca1f8916fed228dd91539f9f1b444c314c06eef02980c716"}, + {file = "certifi-2023.5.7.tar.gz", hash = "sha256:0f0d56dc5a6ad56fd4ba36484d6cc34451e1c6548c61daad8c320169f91eddc7"}, ] [[package]] @@ -228,19 +209,19 @@ test = ["pytest (>=6)"] [[package]] name = "filelock" -version = "3.10.7" +version = "3.12.0" description = "A platform independent file lock." category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "filelock-3.10.7-py3-none-any.whl", hash = "sha256:bde48477b15fde2c7e5a0713cbe72721cb5a5ad32ee0b8f419907960b9d75536"}, - {file = "filelock-3.10.7.tar.gz", hash = "sha256:892be14aa8efc01673b5ed6589dbccb95f9a8596f0507e232626155495c18105"}, + {file = "filelock-3.12.0-py3-none-any.whl", hash = "sha256:ad98852315c2ab702aeb628412cbf7e95b7ce8c3bf9565670b4eaecf1db370a9"}, + {file = "filelock-3.12.0.tar.gz", hash = "sha256:fc03ae43288c013d2ea83c8597001b1129db351aad9c57fe2409327916b8e718"}, ] [package.extras] -docs = ["furo (>=2022.12.7)", "sphinx (>=6.1.3)", "sphinx-autodoc-typehints (>=1.22,!=1.23.4)"] -testing = ["covdefaults (>=2.3)", "coverage (>=7.2.2)", "diff-cover (>=7.5)", "pytest (>=7.2.2)", "pytest-cov (>=4)", "pytest-mock (>=3.10)", "pytest-timeout (>=2.1)"] +docs = ["furo (>=2023.3.27)", "sphinx (>=6.1.3)", "sphinx-autodoc-typehints (>=1.23,!=1.23.4)"] +testing = ["covdefaults (>=2.3)", "coverage (>=7.2.3)", "diff-cover (>=7.5)", "pytest (>=7.3.1)", "pytest-cov (>=4)", "pytest-mock (>=3.10)", "pytest-timeout (>=2.1)"] [[package]] name = "gdspy" @@ -258,45 +239,46 @@ numpy = "*" [[package]] name = "gdstk" -version = "0.9.37" +version = "0.9.40" description = "Python module for creation and manipulation of GDSII files." category = "main" optional = true python-versions = "*" files = [ - {file = "gdstk-0.9.37-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ae2424113a1434d195196340ab28a691de88c59c2f14e280dba744542eb90143"}, - {file = "gdstk-0.9.37-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b51b24966a128b3b72698e6a21a76dc2ad33fcb10034dec303964567578b25db"}, - {file = "gdstk-0.9.37-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8022295a9ee7480d3e2bae5827f979990dc35c62f1442d1e88ed5830ba90ce47"}, - {file = "gdstk-0.9.37-cp310-cp310-win_amd64.whl", hash = "sha256:52405ad6eea1b9f0dd0580d21055e953dc5b2a2303be62787ec0649a27e9d83c"}, - {file = "gdstk-0.9.37-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:7b8c4a8fb4e992d05a7178a1ab50f9ef6329c8e1e76c4f507b61c263b31baaf0"}, - {file = "gdstk-0.9.37-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6069ada42f44a78ef3d13ff33a586ad1fb013e98f92730a7b6c15d731d399570"}, - {file = "gdstk-0.9.37-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:23aec774897483667a21dfb6310ac417b0ec5baa49591a45a15df651ab2ceb9e"}, - {file = "gdstk-0.9.37-cp311-cp311-win_amd64.whl", hash = "sha256:e29b0f9368f8942421c08cde63ea379e738e2d1c0dd06ea45286efbc9bd92cda"}, - {file = "gdstk-0.9.37-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:481aa05b407cf8f60735d58c40a2df43da0bfee8093e9897a9552f7e5ce411d2"}, - {file = "gdstk-0.9.37-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:36db562eb25db40776948f27a7018967bb666e7517aebf2c9ddf60625f59fbec"}, - {file = "gdstk-0.9.37-cp36-cp36m-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ef9e2f72c5175e573a7b83fb3f45e47c8451caf784a14d7b414cdcdef10d9a0d"}, - {file = "gdstk-0.9.37-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:400d16d6d2339885d59710510f9736999fcc35031a23027a4b923d81f74cc7ff"}, - {file = "gdstk-0.9.37-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3fd5fe8ba75cbf902e2f4fe896bb275c31c32a377356dd58f14082448a2507c7"}, - {file = "gdstk-0.9.37-cp37-cp37m-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4f5d702611ff507da0993d856f0c010758462e83fb2c366e0bd3ae1eadb87a76"}, - {file = "gdstk-0.9.37-cp37-cp37m-win_amd64.whl", hash = "sha256:156312cddb137fcd0dfdba7f321d6478df0a413a093878588eb53471344f290c"}, - {file = "gdstk-0.9.37-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:9786351c58c34111af973eb10a87296fec7f3928b8f7eefa1140c62fbc338480"}, - {file = "gdstk-0.9.37-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9a116c2e8806eed0e21068af5e84b4cee251635382f87180014c28fd2d818c72"}, - {file = "gdstk-0.9.37-cp38-cp38-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:907c626acf9d4e349ebab775784f916c48345a8c87921dd964b419d0d491cc5b"}, - {file = "gdstk-0.9.37-cp38-cp38-win_amd64.whl", hash = "sha256:d88748d357197fcb400a6006ae82b9456659e3106eb5c039a8111a7690f04c0a"}, - {file = "gdstk-0.9.37-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:83d76fc350bb4d2ddeffd343344751944d54ecfe2c081072bdbf7439a3e18f53"}, - {file = "gdstk-0.9.37-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:78974a21a268f6797beee658b4b754c0a82008a7674458aa59165b4ab3065f86"}, - {file = "gdstk-0.9.37-cp39-cp39-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ca85ffda0636a0c5a16c65f6f41776861e7a987b14dbdb9b1e53fddd16252dfd"}, - {file = "gdstk-0.9.37-cp39-cp39-win_amd64.whl", hash = "sha256:c6968054978d2c1a17198f842edf8aaeb0baad796addcfa463be19217086061b"}, - {file = "gdstk-0.9.37-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:3cb6ee2132e7617c2c335e19dae1fc275ca628514576b3fcb0cb61d50ef93edf"}, - {file = "gdstk-0.9.37-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fdcc6992952a327bcd4cda52a3596dc9a88417bad3942e174438572e5bac0ec6"}, - {file = "gdstk-0.9.37-pp37-pypy37_pp73-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:cc5ffabc2aec6ad6706a260196b58eeaefeba0ac614c4eca39f9abfcecc569d2"}, - {file = "gdstk-0.9.37-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:7d54e2271b2b02467428cc26a43307380d3dd20196033f2b8f3a1eb96425e24a"}, - {file = "gdstk-0.9.37-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d4baa34e1d4cb6f4fa4a639cbc1133879ba4eb903ee659a2040dd0596dee5f8e"}, - {file = "gdstk-0.9.37-pp38-pypy38_pp73-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d1fddde2159bc6f5844be7e200ddf776fd4510ee7f1767f189bbed5d7533da0f"}, - {file = "gdstk-0.9.37-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:4f3fc607f64598d4a3eba978b06a8a9c11971978dbc2189ba0bea9510d8566f7"}, - {file = "gdstk-0.9.37-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6063fbcbba1e1d5060f5b766efc94e75526e0a57419fc7fc1d616cb6437877df"}, - {file = "gdstk-0.9.37-pp39-pypy39_pp73-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1985caae9cf6cb49d1686fe921514e445d736a95376af8534c207703fda465e4"}, - {file = "gdstk-0.9.37.tar.gz", hash = "sha256:1a4a7cb364a8d4f4d11521d275d38cea75fd86354e8cade16d5f0d3c797c69b6"}, + {file = "gdstk-0.9.40-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:10ea58f8536d588899a173b04f6b7532b712c026a096ffe4409452481bdc4343"}, + {file = "gdstk-0.9.40-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:3885b61a1e153e81b9ff35dbb93a292fcc48e9b5760cfe024a81fa723b6b1347"}, + {file = "gdstk-0.9.40-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:adc3f1d911e4e7b828e92fbf554153d381461a0d0a454d53ae9b462e45e84876"}, + {file = "gdstk-0.9.40-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f785101d4cb8d80530bee3c1b8ac4639dc9e9464fcb48df29dce6cdbf0e72aeb"}, + {file = "gdstk-0.9.40-cp310-cp310-win_amd64.whl", hash = "sha256:0020bf6aed278423513a50f42aa19d63e139d23050b7c66de9ef75e0aaeb3a27"}, + {file = "gdstk-0.9.40-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a09e32d75cf152555ae2c47708c1d7a60c641cf7ac09d00565b4bc23cb5072cb"}, + {file = "gdstk-0.9.40-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2e8507a469b865911313e916e06e512ae9c3e8671a460303208d773b1b0e71ab"}, + {file = "gdstk-0.9.40-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:19901d51c0fa929323f50a1be53665205547bcc5a10e2a28b67bb94dfe6e779b"}, + {file = "gdstk-0.9.40-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8429f8c6cd987a7d6832853218966d2d09e1935d0685f11feed0b18e1f479687"}, + {file = "gdstk-0.9.40-cp311-cp311-win_amd64.whl", hash = "sha256:d2d1dccf74488c3cbedaef71d9b9f8554da46a69dd45412a6301e3b2ebedf2a3"}, + {file = "gdstk-0.9.40-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b187e5a5a39505d33fcc10f68865497f98c6d3a75ddd3928c62636cb9e5e9328"}, + {file = "gdstk-0.9.40-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a8a4b337d6353067368be14da86a04c97ba0e9577716000e632d997967fc3367"}, + {file = "gdstk-0.9.40-cp37-cp37m-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:dfa261c231c26fde982996c70a74e1a93d38e9c05b1beff8fd41105cb677a875"}, + {file = "gdstk-0.9.40-cp37-cp37m-win_amd64.whl", hash = "sha256:8858af6391edb39a1ce6bcb96a957a58296d86f2d46d68ff51d04c4b8c2a1da2"}, + {file = "gdstk-0.9.40-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1db0bb5504e2ce62f55d791d611053b9ea9b7a7dc40bc8bd8ef4ab56e148a3ae"}, + {file = "gdstk-0.9.40-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:9ee571e8202f1d5e8c6168eae2ae609d14bc6569c479e8b00b1b0ea1c577f521"}, + {file = "gdstk-0.9.40-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0e396bf468c34e300f89ecd6f3709b33f1d3703d3cd3a55f5c52a74ee0003b9d"}, + {file = "gdstk-0.9.40-cp38-cp38-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7bea46d340c2490625f9651d0f98837c4b3cdeb0146358d3541fbe335f62341b"}, + {file = "gdstk-0.9.40-cp38-cp38-win_amd64.whl", hash = "sha256:927cd1719dc80d6b6002c91296615a3e5cf68acaa2c37e43de12815263420543"}, + {file = "gdstk-0.9.40-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8ee312068c11c293779498b59c8ff4bb1229cb2cf63109e801ba2a743d372c2b"}, + {file = "gdstk-0.9.40-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:590af739d7ac7c8b2944851a144cf0e0eb33bb1f4b1e939cbfcb4ccbbadd3cee"}, + {file = "gdstk-0.9.40-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba266e443cae9d55de901bef944c5c5f319a10712784f68bdc3679da2f6ba3e3"}, + {file = "gdstk-0.9.40-cp39-cp39-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:99f35dd931b7232dd802f4541a1b4644a9f7a0b946e59d980052197afce82a58"}, + {file = "gdstk-0.9.40-cp39-cp39-win_amd64.whl", hash = "sha256:0e0f7d03a57cf1dfd309cf2469cf655caf6d4fea3c7074b87d55ff8f290d7040"}, + {file = "gdstk-0.9.40-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:3a27025fe6b356d904f51eafe9cdcee3e053591f2811e6ce341c98fed8d72a4d"}, + {file = "gdstk-0.9.40-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d9ceb336dc66d1f8f23551055a8b664d1311f66ee13a1d27251b02d1404f8131"}, + {file = "gdstk-0.9.40-pp37-pypy37_pp73-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:cc8d0a64d64eeca51afd5285f3ae0b1006d859f7a34a5a18ae532f28ab4076f5"}, + {file = "gdstk-0.9.40-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:b68d4fac815bf41a4cd17b9be7c974e3ec6731c308c6676de7d16e2df87ec1af"}, + {file = "gdstk-0.9.40-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a133d0382857befdc729443c6175581b0fd72620276be030f4e11109820fc004"}, + {file = "gdstk-0.9.40-pp38-pypy38_pp73-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:52df0b3c598fa2bc369d414e8f93cb26fae991d4f3758cafa2d64762b51dcf1e"}, + {file = "gdstk-0.9.40-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:af5a6fb5fe80f7acb64a349f3358d62cf6c6d383225dc137e7be8f6e2be28e64"}, + {file = "gdstk-0.9.40-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8dce4f42e930aaeed768e0a49782161eb254fffc9c36677e0beef516dd8da653"}, + {file = "gdstk-0.9.40-pp39-pypy39_pp73-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a699d1752afa42cee4d247a3384c0777302e675f90965dcb29119fb52b4de570"}, + {file = "gdstk-0.9.40.tar.gz", hash = "sha256:da84610c6b5720b4df83e7371f9f464eb5645c45010ffa8da8df5f6858c5d5e6"}, ] [package.dependencies] @@ -328,14 +310,14 @@ files = [ [[package]] name = "importlib-metadata" -version = "6.1.0" +version = "6.6.0" description = "Read metadata from Python packages" category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "importlib_metadata-6.1.0-py3-none-any.whl", hash = "sha256:ff80f3b5394912eb1b108fcfd444dc78b7f1f3e16b16188054bd01cb9cb86f09"}, - {file = "importlib_metadata-6.1.0.tar.gz", hash = "sha256:43ce9281e097583d758c2c708c4376371261a02c34682491a8e98352365aad20"}, + {file = "importlib_metadata-6.6.0-py3-none-any.whl", hash = "sha256:43dd286a2cd8995d5eaef7fee2066340423b818ed3fd70adf0bad5f1fac53fed"}, + {file = "importlib_metadata-6.6.0.tar.gz", hash = "sha256:92501cdf9cc66ebd3e612f1b4f0c0765dfa42f0fa38ffb319b6bd84dd675d705"}, ] [package.dependencies] @@ -661,88 +643,88 @@ testing = ["beautifulsoup4", "coverage[toml]", "pytest (>=6,<7)", "pytest-cov", [[package]] name = "networkx" -version = "3.0" +version = "3.1" description = "Python package for creating and manipulating graphs and networks" category = "main" optional = false python-versions = ">=3.8" files = [ - {file = "networkx-3.0-py3-none-any.whl", hash = "sha256:58058d66b1818043527244fab9d41a51fcd7dcc271748015f3c181b8a90c8e2e"}, - {file = "networkx-3.0.tar.gz", hash = "sha256:9a9992345353618ae98339c2b63d8201c381c2944f38a2ab49cb45a4c667e412"}, + {file = "networkx-3.1-py3-none-any.whl", hash = "sha256:4f33f68cb2afcf86f28a45f43efc27a9386b535d567d2127f8f61d51dec58d36"}, + {file = "networkx-3.1.tar.gz", hash = "sha256:de346335408f84de0eada6ff9fafafff9bcda11f0a0dfaa931133debb146ab61"}, ] [package.extras] default = ["matplotlib (>=3.4)", "numpy (>=1.20)", "pandas (>=1.3)", "scipy (>=1.8)"] -developer = ["mypy (>=0.991)", "pre-commit (>=2.20)"] -doc = ["nb2plots (>=0.6)", "numpydoc (>=1.5)", "pillow (>=9.2)", "pydata-sphinx-theme (>=0.11)", "sphinx (==5.2.3)", "sphinx-gallery (>=0.11)", "texext (>=0.6.7)"] +developer = ["mypy (>=1.1)", "pre-commit (>=3.2)"] +doc = ["nb2plots (>=0.6)", "numpydoc (>=1.5)", "pillow (>=9.4)", "pydata-sphinx-theme (>=0.13)", "sphinx (>=6.1)", "sphinx-gallery (>=0.12)", "texext (>=0.6.7)"] extra = ["lxml (>=4.6)", "pydot (>=1.4.2)", "pygraphviz (>=1.10)", "sympy (>=1.10)"] test = ["codecov (>=2.1)", "pytest (>=7.2)", "pytest-cov (>=4.0)"] [[package]] name = "numpy" -version = "1.24.2" +version = "1.24.3" description = "Fundamental package for array computing in Python" category = "main" optional = false python-versions = ">=3.8" files = [ - {file = "numpy-1.24.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:eef70b4fc1e872ebddc38cddacc87c19a3709c0e3e5d20bf3954c147b1dd941d"}, - {file = "numpy-1.24.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e8d2859428712785e8a8b7d2b3ef0a1d1565892367b32f915c4a4df44d0e64f5"}, - {file = "numpy-1.24.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6524630f71631be2dabe0c541e7675db82651eb998496bbe16bc4f77f0772253"}, - {file = "numpy-1.24.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a51725a815a6188c662fb66fb32077709a9ca38053f0274640293a14fdd22978"}, - {file = "numpy-1.24.2-cp310-cp310-win32.whl", hash = "sha256:2620e8592136e073bd12ee4536149380695fbe9ebeae845b81237f986479ffc9"}, - {file = "numpy-1.24.2-cp310-cp310-win_amd64.whl", hash = "sha256:97cf27e51fa078078c649a51d7ade3c92d9e709ba2bfb97493007103c741f1d0"}, - {file = "numpy-1.24.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:7de8fdde0003f4294655aa5d5f0a89c26b9f22c0a58790c38fae1ed392d44a5a"}, - {file = "numpy-1.24.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4173bde9fa2a005c2c6e2ea8ac1618e2ed2c1c6ec8a7657237854d42094123a0"}, - {file = "numpy-1.24.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4cecaed30dc14123020f77b03601559fff3e6cd0c048f8b5289f4eeabb0eb281"}, - {file = "numpy-1.24.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9a23f8440561a633204a67fb44617ce2a299beecf3295f0d13c495518908e910"}, - {file = "numpy-1.24.2-cp311-cp311-win32.whl", hash = "sha256:e428c4fbfa085f947b536706a2fc349245d7baa8334f0c5723c56a10595f9b95"}, - {file = "numpy-1.24.2-cp311-cp311-win_amd64.whl", hash = "sha256:557d42778a6869c2162deb40ad82612645e21d79e11c1dc62c6e82a2220ffb04"}, - {file = "numpy-1.24.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d0a2db9d20117bf523dde15858398e7c0858aadca7c0f088ac0d6edd360e9ad2"}, - {file = "numpy-1.24.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:c72a6b2f4af1adfe193f7beb91ddf708ff867a3f977ef2ec53c0ffb8283ab9f5"}, - {file = "numpy-1.24.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c29e6bd0ec49a44d7690ecb623a8eac5ab8a923bce0bea6293953992edf3a76a"}, - {file = "numpy-1.24.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2eabd64ddb96a1239791da78fa5f4e1693ae2dadc82a76bc76a14cbb2b966e96"}, - {file = "numpy-1.24.2-cp38-cp38-win32.whl", hash = "sha256:e3ab5d32784e843fc0dd3ab6dcafc67ef806e6b6828dc6af2f689be0eb4d781d"}, - {file = "numpy-1.24.2-cp38-cp38-win_amd64.whl", hash = "sha256:76807b4063f0002c8532cfeac47a3068a69561e9c8715efdad3c642eb27c0756"}, - {file = "numpy-1.24.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:4199e7cfc307a778f72d293372736223e39ec9ac096ff0a2e64853b866a8e18a"}, - {file = "numpy-1.24.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:adbdce121896fd3a17a77ab0b0b5eedf05a9834a18699db6829a64e1dfccca7f"}, - {file = "numpy-1.24.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:889b2cc88b837d86eda1b17008ebeb679d82875022200c6e8e4ce6cf549b7acb"}, - {file = "numpy-1.24.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f64bb98ac59b3ea3bf74b02f13836eb2e24e48e0ab0145bbda646295769bd780"}, - {file = "numpy-1.24.2-cp39-cp39-win32.whl", hash = "sha256:63e45511ee4d9d976637d11e6c9864eae50e12dc9598f531c035265991910468"}, - {file = "numpy-1.24.2-cp39-cp39-win_amd64.whl", hash = "sha256:a77d3e1163a7770164404607b7ba3967fb49b24782a6ef85d9b5f54126cc39e5"}, - {file = "numpy-1.24.2-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:92011118955724465fb6853def593cf397b4a1367495e0b59a7e69d40c4eb71d"}, - {file = "numpy-1.24.2-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f9006288bcf4895917d02583cf3411f98631275bc67cce355a7f39f8c14338fa"}, - {file = "numpy-1.24.2-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:150947adbdfeceec4e5926d956a06865c1c690f2fd902efede4ca6fe2e657c3f"}, - {file = "numpy-1.24.2.tar.gz", hash = "sha256:003a9f530e880cb2cd177cba1af7220b9aa42def9c4afc2a2fc3ee6be7eb2b22"}, + {file = "numpy-1.24.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:3c1104d3c036fb81ab923f507536daedc718d0ad5a8707c6061cdfd6d184e570"}, + {file = "numpy-1.24.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:202de8f38fc4a45a3eea4b63e2f376e5f2dc64ef0fa692838e31a808520efaf7"}, + {file = "numpy-1.24.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8535303847b89aa6b0f00aa1dc62867b5a32923e4d1681a35b5eef2d9591a463"}, + {file = "numpy-1.24.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2d926b52ba1367f9acb76b0df6ed21f0b16a1ad87c6720a1121674e5cf63e2b6"}, + {file = "numpy-1.24.3-cp310-cp310-win32.whl", hash = "sha256:f21c442fdd2805e91799fbe044a7b999b8571bb0ab0f7850d0cb9641a687092b"}, + {file = "numpy-1.24.3-cp310-cp310-win_amd64.whl", hash = "sha256:ab5f23af8c16022663a652d3b25dcdc272ac3f83c3af4c02eb8b824e6b3ab9d7"}, + {file = "numpy-1.24.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:9a7721ec204d3a237225db3e194c25268faf92e19338a35f3a224469cb6039a3"}, + {file = "numpy-1.24.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d6cc757de514c00b24ae8cf5c876af2a7c3df189028d68c0cb4eaa9cd5afc2bf"}, + {file = "numpy-1.24.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76e3f4e85fc5d4fd311f6e9b794d0c00e7002ec122be271f2019d63376f1d385"}, + {file = "numpy-1.24.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a1d3c026f57ceaad42f8231305d4653d5f05dc6332a730ae5c0bea3513de0950"}, + {file = "numpy-1.24.3-cp311-cp311-win32.whl", hash = "sha256:c91c4afd8abc3908e00a44b2672718905b8611503f7ff87390cc0ac3423fb096"}, + {file = "numpy-1.24.3-cp311-cp311-win_amd64.whl", hash = "sha256:5342cf6aad47943286afa6f1609cad9b4266a05e7f2ec408e2cf7aea7ff69d80"}, + {file = "numpy-1.24.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:7776ea65423ca6a15255ba1872d82d207bd1e09f6d0894ee4a64678dd2204078"}, + {file = "numpy-1.24.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:ae8d0be48d1b6ed82588934aaaa179875e7dc4f3d84da18d7eae6eb3f06c242c"}, + {file = "numpy-1.24.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ecde0f8adef7dfdec993fd54b0f78183051b6580f606111a6d789cd14c61ea0c"}, + {file = "numpy-1.24.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4749e053a29364d3452c034827102ee100986903263e89884922ef01a0a6fd2f"}, + {file = "numpy-1.24.3-cp38-cp38-win32.whl", hash = "sha256:d933fabd8f6a319e8530d0de4fcc2e6a61917e0b0c271fded460032db42a0fe4"}, + {file = "numpy-1.24.3-cp38-cp38-win_amd64.whl", hash = "sha256:56e48aec79ae238f6e4395886b5eaed058abb7231fb3361ddd7bfdf4eed54289"}, + {file = "numpy-1.24.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:4719d5aefb5189f50887773699eaf94e7d1e02bf36c1a9d353d9f46703758ca4"}, + {file = "numpy-1.24.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0ec87a7084caa559c36e0a2309e4ecb1baa03b687201d0a847c8b0ed476a7187"}, + {file = "numpy-1.24.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ea8282b9bcfe2b5e7d491d0bf7f3e2da29700cec05b49e64d6246923329f2b02"}, + {file = "numpy-1.24.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:210461d87fb02a84ef243cac5e814aad2b7f4be953b32cb53327bb49fd77fbb4"}, + {file = "numpy-1.24.3-cp39-cp39-win32.whl", hash = "sha256:784c6da1a07818491b0ffd63c6bbe5a33deaa0e25a20e1b3ea20cf0e43f8046c"}, + {file = "numpy-1.24.3-cp39-cp39-win_amd64.whl", hash = "sha256:d5036197ecae68d7f491fcdb4df90082b0d4960ca6599ba2659957aafced7c17"}, + {file = "numpy-1.24.3-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:352ee00c7f8387b44d19f4cada524586f07379c0d49270f87233983bc5087ca0"}, + {file = "numpy-1.24.3-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1a7d6acc2e7524c9955e5c903160aa4ea083736fde7e91276b0e5d98e6332812"}, + {file = "numpy-1.24.3-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:35400e6a8d102fd07c71ed7dcadd9eb62ee9a6e84ec159bd48c28235bbb0f8e4"}, + {file = "numpy-1.24.3.tar.gz", hash = "sha256:ab344f1bf21f140adab8e47fdbc7c35a477dc01408791f8ba00d018dd0bc5155"}, ] [[package]] name = "packaging" -version = "23.0" +version = "23.1" description = "Core utilities for Python packages" category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "packaging-23.0-py3-none-any.whl", hash = "sha256:714ac14496c3e68c99c29b00845f7a2b85f3bb6f1078fd9f72fd20f0570002b2"}, - {file = "packaging-23.0.tar.gz", hash = "sha256:b6ad297f8907de0fa2fe1ccbd26fdaf387f5f47c7275fedf8cce89f99446cf97"}, + {file = "packaging-23.1-py3-none-any.whl", hash = "sha256:994793af429502c4ea2ebf6bf664629d07c1a9fe974af92966e4b8d2df7edc61"}, + {file = "packaging-23.1.tar.gz", hash = "sha256:a392980d2b6cffa644431898be54b0045151319d1e7ec34f0cfed48767dd334f"}, ] [[package]] name = "platformdirs" -version = "3.2.0" +version = "3.5.0" description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "platformdirs-3.2.0-py3-none-any.whl", hash = "sha256:ebe11c0d7a805086e99506aa331612429a72ca7cd52a1f0d277dc4adc20cb10e"}, - {file = "platformdirs-3.2.0.tar.gz", hash = "sha256:d5b638ca397f25f979350ff789db335903d7ea010ab28903f57b27e1b16c2b08"}, + {file = "platformdirs-3.5.0-py3-none-any.whl", hash = "sha256:47692bc24c1958e8b0f13dd727307cff1db103fca36399f457da8e05f222fdc4"}, + {file = "platformdirs-3.5.0.tar.gz", hash = "sha256:7954a68d0ba23558d753f73437c55f89027cf8f5108c19844d4b82e5af396335"}, ] [package.extras] -docs = ["furo (>=2022.12.7)", "proselint (>=0.13)", "sphinx (>=6.1.3)", "sphinx-autodoc-typehints (>=1.22,!=1.23.4)"] -test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.2.2)", "pytest-cov (>=4)", "pytest-mock (>=3.10)"] +docs = ["furo (>=2023.3.27)", "proselint (>=0.13)", "sphinx (>=6.1.3)", "sphinx-autodoc-typehints (>=1.23,!=1.23.4)"] +test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.3.1)", "pytest-cov (>=4)", "pytest-mock (>=3.10)"] [[package]] name = "pluggy" @@ -827,14 +809,14 @@ email = ["email-validator (>=1.0.3)"] [[package]] name = "pygments" -version = "2.14.0" +version = "2.15.1" description = "Pygments is a syntax highlighting package written in Python." category = "dev" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" files = [ - {file = "Pygments-2.14.0-py3-none-any.whl", hash = "sha256:fa7bd7bd2771287c0de303af8bfdfc731f51bd2c6a47ab69d117138893b82717"}, - {file = "Pygments-2.14.0.tar.gz", hash = "sha256:b3ed06a9e8ac9a9aae5a6f5dbe78a8a58655d17b43b93c078f094ddc476ae297"}, + {file = "Pygments-2.15.1-py3-none-any.whl", hash = "sha256:db2db3deb4b4179f399a09054b023b6a586b76499d36965813c71aa8ed7b5fd1"}, + {file = "Pygments-2.15.1.tar.gz", hash = "sha256:8ace4d3c1dd481894b2005f560ead0f9f19ee64fe983366be1a21e171d12775c"}, ] [package.extras] @@ -842,18 +824,18 @@ plugins = ["importlib-metadata"] [[package]] name = "pylint" -version = "2.17.1" +version = "2.17.4" description = "python code static checker" category = "dev" optional = false python-versions = ">=3.7.2" files = [ - {file = "pylint-2.17.1-py3-none-any.whl", hash = "sha256:8660a54e3f696243d644fca98f79013a959c03f979992c1ab59c24d3f4ec2700"}, - {file = "pylint-2.17.1.tar.gz", hash = "sha256:d4d009b0116e16845533bc2163493d6681846ac725eab8ca8014afb520178ddd"}, + {file = "pylint-2.17.4-py3-none-any.whl", hash = "sha256:7a1145fb08c251bdb5cca11739722ce64a63db479283d10ce718b2460e54123c"}, + {file = "pylint-2.17.4.tar.gz", hash = "sha256:5dcf1d9e19f41f38e4e85d10f511e5b9c35e1aa74251bf95cdd8cb23584e2db1"}, ] [package.dependencies] -astroid = ">=2.15.0,<=2.17.0-dev0" +astroid = ">=2.15.4,<=2.17.0-dev0" colorama = {version = ">=0.4.5", markers = "sys_platform == \"win32\""} dill = [ {version = ">=0.2", markers = "python_version < \"3.11\""}, @@ -872,18 +854,17 @@ testutils = ["gitpython (>3)"] [[package]] name = "pytest" -version = "7.2.2" +version = "7.3.1" description = "pytest: simple powerful testing with Python" category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "pytest-7.2.2-py3-none-any.whl", hash = "sha256:130328f552dcfac0b1cec75c12e3f005619dc5f874f0a06e8ff7263f0ee6225e"}, - {file = "pytest-7.2.2.tar.gz", hash = "sha256:c99ab0c73aceb050f68929bc93af19ab6db0558791c6a0715723abe9d0ade9d4"}, + {file = "pytest-7.3.1-py3-none-any.whl", hash = "sha256:3799fa815351fea3a5e96ac7e503a96fa51cc9942c3753cda7651b93c1cfa362"}, + {file = "pytest-7.3.1.tar.gz", hash = "sha256:434afafd78b1d78ed0addf160ad2b77a30d35d4bdf8af234fe621919d9ed15e3"}, ] [package.dependencies] -attrs = ">=19.2.0" colorama = {version = "*", markers = "sys_platform == \"win32\""} exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""} iniconfig = "*" @@ -892,7 +873,7 @@ pluggy = ">=0.12,<2.0" tomli = {version = ">=1.0.0", markers = "python_version < \"3.11\""} [package.extras] -testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "xmlschema"] +testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "xmlschema"] [[package]] name = "pyyaml" @@ -946,21 +927,21 @@ files = [ [[package]] name = "requests" -version = "2.28.2" +version = "2.30.0" description = "Python HTTP for Humans." category = "dev" optional = false -python-versions = ">=3.7, <4" +python-versions = ">=3.7" files = [ - {file = "requests-2.28.2-py3-none-any.whl", hash = "sha256:64299f4909223da747622c030b781c0d7811e359c37124b4bd368fb8c6518baa"}, - {file = "requests-2.28.2.tar.gz", hash = "sha256:98b1b2782e3c6c4904938b84c0eb932721069dfdb9134313beff7c83c2df24bf"}, + {file = "requests-2.30.0-py3-none-any.whl", hash = "sha256:10e94cc4f3121ee6da529d358cdaeaff2f1c409cd377dbc72b825852f2f7e294"}, + {file = "requests-2.30.0.tar.gz", hash = "sha256:239d7d4458afcb28a692cdd298d87542235f4ca8d36d03a15bfc128a6559a2f4"}, ] [package.dependencies] certifi = ">=2017.4.17" charset-normalizer = ">=2,<4" idna = ">=2.5,<4" -urllib3 = ">=1.21.1,<1.27" +urllib3 = ">=1.21.1,<3" [package.extras] socks = ["PySocks (>=1.5.6,!=1.5.7)"] @@ -968,18 +949,18 @@ use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] [[package]] name = "ruamel-yaml" -version = "0.17.21" +version = "0.17.26" description = "ruamel.yaml is a YAML parser/emitter that supports roundtrip preservation of comments, seq/map flow style, and map key order" category = "main" optional = false python-versions = ">=3" files = [ - {file = "ruamel.yaml-0.17.21-py3-none-any.whl", hash = "sha256:742b35d3d665023981bd6d16b3d24248ce5df75fdb4e2924e93a05c1f8b61ca7"}, - {file = "ruamel.yaml-0.17.21.tar.gz", hash = "sha256:8b7ce697a2f212752a35c1ac414471dc16c424c9573be4926b56ff3f5d23b7af"}, + {file = "ruamel.yaml-0.17.26-py3-none-any.whl", hash = "sha256:25d0ee82a0a9a6f44683dcf8c282340def4074a4562f3a24f55695bb254c1693"}, + {file = "ruamel.yaml-0.17.26.tar.gz", hash = "sha256:baa2d0a5aad2034826c439ce61c142c07082b76f4791d54145e131206e998059"}, ] [package.dependencies] -"ruamel.yaml.clib" = {version = ">=0.2.6", markers = "platform_python_implementation == \"CPython\" and python_version < \"3.11\""} +"ruamel.yaml.clib" = {version = ">=0.2.7", markers = "platform_python_implementation == \"CPython\" and python_version < \"3.12\""} [package.extras] docs = ["ryd"] @@ -1002,6 +983,8 @@ files = [ {file = "ruamel.yaml.clib-0.2.7-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:045e0626baf1c52e5527bd5db361bc83180faaba2ff586e763d3d5982a876a9e"}, {file = "ruamel.yaml.clib-0.2.7-cp311-cp311-macosx_12_6_arm64.whl", hash = "sha256:721bc4ba4525f53f6a611ec0967bdcee61b31df5a56801281027a3a6d1c2daf5"}, {file = "ruamel.yaml.clib-0.2.7-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:41d0f1fa4c6830176eef5b276af04c89320ea616655d01327d5ce65e50575c94"}, + {file = "ruamel.yaml.clib-0.2.7-cp311-cp311-win32.whl", hash = "sha256:f6d3d39611ac2e4f62c3128a9eed45f19a6608670c5a2f4f07f24e8de3441d38"}, + {file = "ruamel.yaml.clib-0.2.7-cp311-cp311-win_amd64.whl", hash = "sha256:da538167284de58a52109a9b89b8f6a53ff8437dd6dc26d33b57bf6699153122"}, {file = "ruamel.yaml.clib-0.2.7-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:4b3a93bb9bc662fc1f99c5c3ea8e623d8b23ad22f861eb6fce9377ac07ad6072"}, {file = "ruamel.yaml.clib-0.2.7-cp36-cp36m-macosx_12_0_arm64.whl", hash = "sha256:a234a20ae07e8469da311e182e70ef6b199d0fbeb6c6cc2901204dd87fb867e8"}, {file = "ruamel.yaml.clib-0.2.7-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:15910ef4f3e537eea7fe45f8a5d19997479940d9196f357152a09031c5be59f3"}, @@ -1245,14 +1228,14 @@ files = [ [[package]] name = "tomlkit" -version = "0.11.7" +version = "0.11.8" description = "Style preserving TOML library" category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "tomlkit-0.11.7-py3-none-any.whl", hash = "sha256:5325463a7da2ef0c6bbfefb62a3dc883aebe679984709aee32a317907d0a8d3c"}, - {file = "tomlkit-0.11.7.tar.gz", hash = "sha256:f392ef70ad87a672f02519f99967d28a4d3047133e2d1df936511465fbb3791d"}, + {file = "tomlkit-0.11.8-py3-none-any.whl", hash = "sha256:8c726c4c202bdb148667835f68d68780b9a003a9ec34167b6c673b38eff2a171"}, + {file = "tomlkit-0.11.8.tar.gz", hash = "sha256:9330fc7faa1db67b541b28e62018c17d20be733177d290a13b24c62d1614e0c3"}, ] [[package]] @@ -1307,41 +1290,42 @@ files = [ [[package]] name = "urllib3" -version = "1.26.15" +version = "2.0.2" description = "HTTP library with thread-safe connection pooling, file post, and more." category = "dev" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" +python-versions = ">=3.7" files = [ - {file = "urllib3-1.26.15-py2.py3-none-any.whl", hash = "sha256:aa751d169e23c7479ce47a0cb0da579e3ede798f994f5816a74e4f4500dcea42"}, - {file = "urllib3-1.26.15.tar.gz", hash = "sha256:8a388717b9476f934a21484e8c8e61875ab60644d29b9b39e11e4b9dc1c6b305"}, + {file = "urllib3-2.0.2-py3-none-any.whl", hash = "sha256:d055c2f9d38dc53c808f6fdc8eab7360b6fdbbde02340ed25cfbcd817c62469e"}, + {file = "urllib3-2.0.2.tar.gz", hash = "sha256:61717a1095d7e155cdb737ac7bb2f4324a858a1e2e6466f6d03ff630ca68d3cc"}, ] [package.extras] -brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)", "brotlipy (>=0.6.0)"] -secure = ["certifi", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "ipaddress", "pyOpenSSL (>=0.14)", "urllib3-secure-extra"] -socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] +brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"] +secure = ["certifi", "cryptography (>=1.9)", "idna (>=2.0.0)", "pyopenssl (>=17.1.0)", "urllib3-secure-extra"] +socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] +zstd = ["zstandard (>=0.18.0)"] [[package]] name = "virtualenv" -version = "20.21.0" +version = "20.23.0" description = "Virtual Python Environment builder" category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "virtualenv-20.21.0-py3-none-any.whl", hash = "sha256:31712f8f2a17bd06234fa97fdf19609e789dd4e3e4bf108c3da71d710651adbc"}, - {file = "virtualenv-20.21.0.tar.gz", hash = "sha256:f50e3e60f990a0757c9b68333c9fdaa72d7188caa417f96af9e52407831a3b68"}, + {file = "virtualenv-20.23.0-py3-none-any.whl", hash = "sha256:6abec7670e5802a528357fdc75b26b9f57d5d92f29c5462ba0fbe45feacc685e"}, + {file = "virtualenv-20.23.0.tar.gz", hash = "sha256:a85caa554ced0c0afbd0d638e7e2d7b5f92d23478d05d17a76daeac8f279f924"}, ] [package.dependencies] distlib = ">=0.3.6,<1" -filelock = ">=3.4.1,<4" -platformdirs = ">=2.4,<4" +filelock = ">=3.11,<4" +platformdirs = ">=3.2,<4" [package.extras] -docs = ["furo (>=2022.12.7)", "proselint (>=0.13)", "sphinx (>=6.1.3)", "sphinx-argparse (>=0.4)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=22.12)"] -test = ["covdefaults (>=2.2.2)", "coverage (>=7.1)", "coverage-enable-subprocess (>=1)", "flaky (>=3.7)", "packaging (>=23)", "pytest (>=7.2.1)", "pytest-env (>=0.8.1)", "pytest-freezegun (>=0.4.2)", "pytest-mock (>=3.10)", "pytest-randomly (>=3.12)", "pytest-timeout (>=2.1)"] +docs = ["furo (>=2023.3.27)", "proselint (>=0.13)", "sphinx (>=6.1.3)", "sphinx-argparse (>=0.4)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=22.12)"] +test = ["covdefaults (>=2.3)", "coverage (>=7.2.3)", "coverage-enable-subprocess (>=1)", "flaky (>=3.7)", "packaging (>=23.1)", "pytest (>=7.3.1)", "pytest-env (>=0.8.1)", "pytest-freezegun (>=0.4.2)", "pytest-mock (>=3.10)", "pytest-randomly (>=3.12)", "pytest-timeout (>=2.1)", "setuptools (>=67.7.1)", "time-machine (>=2.9)"] [[package]] name = "wrapt" From cf8c55000b92056b640652d4434e6edc0518380b Mon Sep 17 00:00:00 2001 From: Bryan Ngo Date: Thu, 11 May 2023 11:30:29 -0700 Subject: [PATCH 30/36] bump lock file, add typing marker --- hammer/flowgraph/py.typed | 0 poetry.lock | 80 +++++++++++++++++---------------------- 2 files changed, 35 insertions(+), 45 deletions(-) create mode 100644 hammer/flowgraph/py.typed diff --git a/hammer/flowgraph/py.typed b/hammer/flowgraph/py.typed new file mode 100644 index 000000000..e69de29bb diff --git a/poetry.lock b/poetry.lock index 0fa8db890..fc6c8e67a 100644 --- a/poetry.lock +++ b/poetry.lock @@ -565,38 +565,38 @@ files = [ [[package]] name = "mypy" -version = "1.1.1" +version = "1.3.0" description = "Optional static typing for Python" category = "dev" optional = false python-versions = ">=3.7" files = [ - {file = "mypy-1.1.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:39c7119335be05630611ee798cc982623b9e8f0cff04a0b48dfc26100e0b97af"}, - {file = "mypy-1.1.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:61bf08362e93b6b12fad3eab68c4ea903a077b87c90ac06c11e3d7a09b56b9c1"}, - {file = "mypy-1.1.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dbb19c9f662e41e474e0cff502b7064a7edc6764f5262b6cd91d698163196799"}, - {file = "mypy-1.1.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:315ac73cc1cce4771c27d426b7ea558fb4e2836f89cb0296cbe056894e3a1f78"}, - {file = "mypy-1.1.1-cp310-cp310-win_amd64.whl", hash = "sha256:5cb14ff9919b7df3538590fc4d4c49a0f84392237cbf5f7a816b4161c061829e"}, - {file = "mypy-1.1.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:26cdd6a22b9b40b2fd71881a8a4f34b4d7914c679f154f43385ca878a8297389"}, - {file = "mypy-1.1.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5b5f81b40d94c785f288948c16e1f2da37203c6006546c5d947aab6f90aefef2"}, - {file = "mypy-1.1.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21b437be1c02712a605591e1ed1d858aba681757a1e55fe678a15c2244cd68a5"}, - {file = "mypy-1.1.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d809f88734f44a0d44959d795b1e6f64b2bbe0ea4d9cc4776aa588bb4229fc1c"}, - {file = "mypy-1.1.1-cp311-cp311-win_amd64.whl", hash = "sha256:a380c041db500e1410bb5b16b3c1c35e61e773a5c3517926b81dfdab7582be54"}, - {file = "mypy-1.1.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b7c7b708fe9a871a96626d61912e3f4ddd365bf7f39128362bc50cbd74a634d5"}, - {file = "mypy-1.1.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c1c10fa12df1232c936830839e2e935d090fc9ee315744ac33b8a32216b93707"}, - {file = "mypy-1.1.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:0a28a76785bf57655a8ea5eb0540a15b0e781c807b5aa798bd463779988fa1d5"}, - {file = "mypy-1.1.1-cp37-cp37m-win_amd64.whl", hash = "sha256:ef6a01e563ec6a4940784c574d33f6ac1943864634517984471642908b30b6f7"}, - {file = "mypy-1.1.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d64c28e03ce40d5303450f547e07418c64c241669ab20610f273c9e6290b4b0b"}, - {file = "mypy-1.1.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:64cc3afb3e9e71a79d06e3ed24bb508a6d66f782aff7e56f628bf35ba2e0ba51"}, - {file = "mypy-1.1.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ce61663faf7a8e5ec6f456857bfbcec2901fbdb3ad958b778403f63b9e606a1b"}, - {file = "mypy-1.1.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:2b0c373d071593deefbcdd87ec8db91ea13bd8f1328d44947e88beae21e8d5e9"}, - {file = "mypy-1.1.1-cp38-cp38-win_amd64.whl", hash = "sha256:2888ce4fe5aae5a673386fa232473014056967f3904f5abfcf6367b5af1f612a"}, - {file = "mypy-1.1.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:19ba15f9627a5723e522d007fe708007bae52b93faab00f95d72f03e1afa9598"}, - {file = "mypy-1.1.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:59bbd71e5c58eed2e992ce6523180e03c221dcd92b52f0e792f291d67b15a71c"}, - {file = "mypy-1.1.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9401e33814cec6aec8c03a9548e9385e0e228fc1b8b0a37b9ea21038e64cdd8a"}, - {file = "mypy-1.1.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:4b398d8b1f4fba0e3c6463e02f8ad3346f71956b92287af22c9b12c3ec965a9f"}, - {file = "mypy-1.1.1-cp39-cp39-win_amd64.whl", hash = "sha256:69b35d1dcb5707382810765ed34da9db47e7f95b3528334a3c999b0c90fe523f"}, - {file = "mypy-1.1.1-py3-none-any.whl", hash = "sha256:4e4e8b362cdf99ba00c2b218036002bdcdf1e0de085cdb296a49df03fb31dfc4"}, - {file = "mypy-1.1.1.tar.gz", hash = "sha256:ae9ceae0f5b9059f33dbc62dea087e942c0ccab4b7a003719cb70f9b8abfa32f"}, + {file = "mypy-1.3.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c1eb485cea53f4f5284e5baf92902cd0088b24984f4209e25981cc359d64448d"}, + {file = "mypy-1.3.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:4c99c3ecf223cf2952638da9cd82793d8f3c0c5fa8b6ae2b2d9ed1e1ff51ba85"}, + {file = "mypy-1.3.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:550a8b3a19bb6589679a7c3c31f64312e7ff482a816c96e0cecec9ad3a7564dd"}, + {file = "mypy-1.3.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:cbc07246253b9e3d7d74c9ff948cd0fd7a71afcc2b77c7f0a59c26e9395cb152"}, + {file = "mypy-1.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:a22435632710a4fcf8acf86cbd0d69f68ac389a3892cb23fbad176d1cddaf228"}, + {file = "mypy-1.3.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6e33bb8b2613614a33dff70565f4c803f889ebd2f859466e42b46e1df76018dd"}, + {file = "mypy-1.3.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7d23370d2a6b7a71dc65d1266f9a34e4cde9e8e21511322415db4b26f46f6b8c"}, + {file = "mypy-1.3.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:658fe7b674769a0770d4b26cb4d6f005e88a442fe82446f020be8e5f5efb2fae"}, + {file = "mypy-1.3.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:6e42d29e324cdda61daaec2336c42512e59c7c375340bd202efa1fe0f7b8f8ca"}, + {file = "mypy-1.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:d0b6c62206e04061e27009481cb0ec966f7d6172b5b936f3ead3d74f29fe3dcf"}, + {file = "mypy-1.3.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:76ec771e2342f1b558c36d49900dfe81d140361dd0d2df6cd71b3db1be155409"}, + {file = "mypy-1.3.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ebc95f8386314272bbc817026f8ce8f4f0d2ef7ae44f947c4664efac9adec929"}, + {file = "mypy-1.3.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:faff86aa10c1aa4a10e1a301de160f3d8fc8703b88c7e98de46b531ff1276a9a"}, + {file = "mypy-1.3.0-cp37-cp37m-win_amd64.whl", hash = "sha256:8c5979d0deb27e0f4479bee18ea0f83732a893e81b78e62e2dda3e7e518c92ee"}, + {file = "mypy-1.3.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:c5d2cc54175bab47011b09688b418db71403aefad07cbcd62d44010543fc143f"}, + {file = "mypy-1.3.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:87df44954c31d86df96c8bd6e80dfcd773473e877ac6176a8e29898bfb3501cb"}, + {file = "mypy-1.3.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:473117e310febe632ddf10e745a355714e771ffe534f06db40702775056614c4"}, + {file = "mypy-1.3.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:74bc9b6e0e79808bf8678d7678b2ae3736ea72d56eede3820bd3849823e7f305"}, + {file = "mypy-1.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:44797d031a41516fcf5cbfa652265bb994e53e51994c1bd649ffcd0c3a7eccbf"}, + {file = "mypy-1.3.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:ddae0f39ca146972ff6bb4399f3b2943884a774b8771ea0a8f50e971f5ea5ba8"}, + {file = "mypy-1.3.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1c4c42c60a8103ead4c1c060ac3cdd3ff01e18fddce6f1016e08939647a0e703"}, + {file = "mypy-1.3.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e86c2c6852f62f8f2b24cb7a613ebe8e0c7dc1402c61d36a609174f63e0ff017"}, + {file = "mypy-1.3.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:f9dca1e257d4cc129517779226753dbefb4f2266c4eaad610fc15c6a7e14283e"}, + {file = "mypy-1.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:95d8d31a7713510685b05fbb18d6ac287a56c8f6554d88c19e73f724a445448a"}, + {file = "mypy-1.3.0-py3-none-any.whl", hash = "sha256:a8763e72d5d9574d45ce5881962bc8e9046bf7b375b0abf031f3e6811732a897"}, + {file = "mypy-1.3.0.tar.gz", hash = "sha256:e1f4d16e296f5135624b34e8fb741eb0eadedca90862405b1f1fde2040b9bd11"}, ] [package.dependencies] @@ -898,6 +898,13 @@ files = [ {file = "PyYAML-6.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5"}, {file = "PyYAML-6.0-cp310-cp310-win32.whl", hash = "sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513"}, {file = "PyYAML-6.0-cp310-cp310-win_amd64.whl", hash = "sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a"}, + {file = "PyYAML-6.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d4b0ba9512519522b118090257be113b9468d804b19d63c71dbcf4a48fa32358"}, + {file = "PyYAML-6.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:81957921f441d50af23654aa6c5e5eaf9b06aba7f0a19c18a538dc7ef291c5a1"}, + {file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:afa17f5bc4d1b10afd4466fd3a44dc0e245382deca5b3c353d8b757f9e3ecb8d"}, + {file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dbad0e9d368bb989f4515da330b88a057617d16b6a8245084f1b05400f24609f"}, + {file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:432557aa2c09802be39460360ddffd48156e30721f5e8d917f01d31694216782"}, + {file = "PyYAML-6.0-cp311-cp311-win32.whl", hash = "sha256:bfaef573a63ba8923503d27530362590ff4f576c626d86a9fed95822a8255fd7"}, + {file = "PyYAML-6.0-cp311-cp311-win_amd64.whl", hash = "sha256:01b45c0191e6d66c470b6cf1b9531a771a83c1c4208272ead47a3ae4f2f603bf"}, {file = "PyYAML-6.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:897b80890765f037df3403d22bab41627ca8811ae55e9a722fd0392850ec4d86"}, {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:50602afada6d6cbfad699b0c7bb50d5ccffa7e46a3d738092afddc1f9758427f"}, {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:48c346915c114f5fdb3ead70312bd042a953a8ce5c7106d5bfb1a5254e47da92"}, @@ -1013,23 +1020,6 @@ files = [ {file = "ruamel.yaml.clib-0.2.7.tar.gz", hash = "sha256:1f08fd5a2bea9c4180db71678e850b995d2a5f4537be0e94557668cf0f5f9497"}, ] -[[package]] -name = "setuptools" -version = "67.6.0" -description = "Easily download, build, install, upgrade, and uninstall Python packages" -category = "dev" -optional = false -python-versions = ">=3.7" -files = [ - {file = "setuptools-67.6.0-py3-none-any.whl", hash = "sha256:b78aaa36f6b90a074c1fa651168723acbf45d14cb1196b6f02c0fd07f17623b2"}, - {file = "setuptools-67.6.0.tar.gz", hash = "sha256:2ee892cd5f29f3373097f5a814697e397cf3ce313616df0af11231e2ad118077"}, -] - -[package.extras] -docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-hoverxref (<2)", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (==0.8.3)", "sphinx-reredirects", "sphinxcontrib-towncrier"] -testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8 (<5)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pip-run (>=8.8)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] -testing-integration = ["build[virtualenv]", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"] - [[package]] name = "six" version = "1.16.0" @@ -1485,4 +1475,4 @@ asap7-gdstk = ["gdstk"] [metadata] lock-version = "2.0" python-versions = "^3.9" -content-hash = "905376dcbe86ee41ff3fc09b22e3cf3cd05e40e2cf66a327f5412816e01c3c24" +content-hash = "909500729bedc90acb89cc4a4b5c8efa663af9213e0d95ff85341b3c2f0f255c" From d32621171bc08f9bfede65956544c035b6ee49d2 Mon Sep 17 00:00:00 2001 From: Bryan Ngo Date: Thu, 11 May 2023 11:37:28 -0700 Subject: [PATCH 31/36] fix type-checking for networkx --- .github/workflows/pr.yml | 1 + hammer/flowgraph/py.typed | 0 2 files changed, 1 insertion(+) delete mode 100644 hammer/flowgraph/py.typed diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 338a95ca3..405a67f40 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -60,4 +60,5 @@ jobs: id: type-checks run: | touch .venv/lib/python${{ matrix.python-version }}/site-packages/ruamel/py.typed + touch .venv/lib/python${{ matrix.python-version }}/site-packages/networkx/py.typed poetry run mypy --namespace-packages -p hammer diff --git a/hammer/flowgraph/py.typed b/hammer/flowgraph/py.typed deleted file mode 100644 index e69de29bb..000000000 From 8dce117bda8801fa7ea4e529b96df62a8633cb94 Mon Sep 17 00:00:00 2001 From: Bryan Ngo Date: Fri, 1 Dec 2023 13:29:22 -0800 Subject: [PATCH 32/36] fix CI pipeline --- hammer/config/config_src.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hammer/config/config_src.py b/hammer/config/config_src.py index 98d7d2032..80493940d 100644 --- a/hammer/config/config_src.py +++ b/hammer/config/config_src.py @@ -941,7 +941,7 @@ def check_setting(self, key: str, cfg: Optional[dict] = None) -> bool: if cfg is None: cfg = self.get_config() - if key not in self.get_config_types(): + if key not in self.get_config_types: #TODO: compile this at the beginning instead of emitting every instance #self.logger.warning(f"Key {key} is not associated with a type") return True From 842346ffbaa278df49cfb8a5937ec3cb16b0fb91 Mon Sep 17 00:00:00 2001 From: Bryan Ngo Date: Thu, 4 Jan 2024 14:04:29 -0800 Subject: [PATCH 33/36] migrate to current step control names --- hammer/flowgraph/flowgraph.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/hammer/flowgraph/flowgraph.py b/hammer/flowgraph/flowgraph.py index 415d495d7..c56fafcf2 100644 --- a/hammer/flowgraph/flowgraph.py +++ b/hammer/flowgraph/flowgraph.py @@ -51,10 +51,10 @@ class Node: optional_inputs: list[str] = field(default_factory=list) optional_outputs: list[str] = field(default_factory=list) step_controls: dict[str, str] = field(default_factory=lambda: { - "from_step": "", - "after_step": "", - "to_step": "", - "until_step": "", + "start_before_step": "", + "start_after_step": "", + "stop_before_step": "", + "stop_after_step": "", "only_step": "", }) From bbb047fc72da89c2358244331e0efb34c3067162 Mon Sep 17 00:00:00 2001 From: Bryan Ngo Date: Thu, 4 Jan 2024 14:05:52 -0800 Subject: [PATCH 34/36] reorder sections --- doc/Hammer-Use/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/Hammer-Use/index.rst b/doc/Hammer-Use/index.rst index b608c0969..de3649b04 100644 --- a/doc/Hammer-Use/index.rst +++ b/doc/Hammer-Use/index.rst @@ -11,6 +11,6 @@ This documentation will walk through more advanced features of the Hammer infras Hammer-APIs Flow-Control Hooks + Flowgraphs Buildfile Hierarchical - Flowgraphs From 6ca70a599b3fb0bd714464fe3f84b56d580669b2 Mon Sep 17 00:00:00 2001 From: Bryan Ngo Date: Thu, 4 Jan 2024 14:32:26 -0800 Subject: [PATCH 35/36] make docs consistent --- doc/Hammer-Use/Flowgraphs.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/Hammer-Use/Flowgraphs.rst b/doc/Hammer-Use/Flowgraphs.rst index d798ed932..bfd0e3a32 100644 --- a/doc/Hammer-Use/Flowgraphs.rst +++ b/doc/Hammer-Use/Flowgraphs.rst @@ -22,10 +22,10 @@ Each ``Node`` "pulls" from a directory to feed in inputs and "pushes" output fil * A driver to run the node with; this enables backwards compatibility with :ref:`hooks `. * Options to specify steps within an action; this enables backwards compatibility with :ref:`flow control `. - * ``from_step`` - * ``after_step`` - * ``to_step`` - * ``until_step`` + * ``start_before_step`` + * ``start_after_step`` + * ``stop_before_step`` + * ``stop_after_step`` * ``only_step`` A minimal example of a ``Node``: From 4b2a1aeca7d8c60bf0093a91d1c562bafaef7741 Mon Sep 17 00:00:00 2001 From: Bryan Ngo Date: Thu, 4 Jan 2024 14:34:26 -0800 Subject: [PATCH 36/36] convert back to legacy names for plugging into backend --- hammer/flowgraph/flowgraph.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/hammer/flowgraph/flowgraph.py b/hammer/flowgraph/flowgraph.py index c56fafcf2..000ec81bc 100644 --- a/hammer/flowgraph/flowgraph.py +++ b/hammer/flowgraph/flowgraph.py @@ -278,10 +278,10 @@ def __run_single(node: Node) -> int: 'power_rundir': '', 'formal_rundir': '', 'timing_rundir': '', - 'from_step': node.step_controls["from_step"], - 'after_step': node.step_controls["after_step"], - 'to_step': node.step_controls["to_step"], - 'until_step': node.step_controls["until_step"], + "from_step": node.step_controls["start_before_step"], + "after_step": node.step_controls["start_after_step"], + "to_step": node.step_controls["stop_before_step"], + "until_step": node.step_controls["stop_after_step"], 'only_step': node.step_controls["only_step"], 'output': os.path.join(node.push_dir, node.required_outputs[0]), # TODO: fix this 'verilog': None,