diff options
author | sotech117 <michael_foiani@brown.edu> | 2025-07-31 17:27:24 -0400 |
---|---|---|
committer | sotech117 <michael_foiani@brown.edu> | 2025-07-31 17:27:24 -0400 |
commit | 5bf22fc7e3c392c8bd44315ca2d06d7dca7d084e (patch) | |
tree | 8dacb0f195df1c0788d36dd0064f6bbaa3143ede /venv/lib/python3.8/site-packages/plotly/utils.py | |
parent | b832d364da8c2efe09e3f75828caf73c50d01ce3 (diff) |
add code for analysis of data
Diffstat (limited to 'venv/lib/python3.8/site-packages/plotly/utils.py')
-rw-r--r-- | venv/lib/python3.8/site-packages/plotly/utils.py | 208 |
1 files changed, 208 insertions, 0 deletions
diff --git a/venv/lib/python3.8/site-packages/plotly/utils.py b/venv/lib/python3.8/site-packages/plotly/utils.py new file mode 100644 index 0000000..f2ecc84 --- /dev/null +++ b/venv/lib/python3.8/site-packages/plotly/utils.py @@ -0,0 +1,208 @@ +import textwrap +from pprint import PrettyPrinter + +from _plotly_utils.utils import NotEncodable, PlotlyJSONEncoder, get_module # noqa: F401 +from _plotly_utils.data_utils import image_array_to_data_uri # noqa: F401 + + +# Pretty printing +def _list_repr_elided(v, threshold=200, edgeitems=3, indent=0, width=80): + """ + Return a string representation for of a list where list is elided if + it has more than n elements + + Parameters + ---------- + v : list + Input list + threshold : + Maximum number of elements to display + + Returns + ------- + str + """ + if isinstance(v, list): + open_char, close_char = "[", "]" + elif isinstance(v, tuple): + open_char, close_char = "(", ")" + else: + raise ValueError("Invalid value of type: %s" % type(v)) + + if len(v) <= threshold: + disp_v = v + else: + disp_v = list(v[:edgeitems]) + ["..."] + list(v[-edgeitems:]) + + v_str = open_char + ", ".join([str(e) for e in disp_v]) + close_char + + v_wrapped = "\n".join( + textwrap.wrap( + v_str, + width=width, + initial_indent=" " * (indent + 1), + subsequent_indent=" " * (indent + 1), + ) + ).strip() + return v_wrapped + + +class ElidedWrapper(object): + """ + Helper class that wraps values of certain types and produces a custom + __repr__() that may be elided and is suitable for use during pretty + printing + """ + + def __init__(self, v, threshold, indent): + self.v = v + self.indent = indent + self.threshold = threshold + + @staticmethod + def is_wrappable(v): + numpy = get_module("numpy") + if isinstance(v, (list, tuple)) and len(v) > 0 and not isinstance(v[0], dict): + return True + elif numpy and isinstance(v, numpy.ndarray): + return True + elif isinstance(v, str): + return True + else: + return False + + def __repr__(self): + numpy = get_module("numpy") + if isinstance(self.v, (list, tuple)): + # Handle lists/tuples + res = _list_repr_elided( + self.v, threshold=self.threshold, indent=self.indent + ) + return res + elif numpy and isinstance(self.v, numpy.ndarray): + # Handle numpy arrays + + # Get original print opts + orig_opts = numpy.get_printoptions() + + # Set threshold to self.max_list_elements + numpy.set_printoptions( + **dict(orig_opts, threshold=self.threshold, edgeitems=3, linewidth=80) + ) + + res = self.v.__repr__() + + # Add indent to all but the first line + res_lines = res.split("\n") + res = ("\n" + " " * self.indent).join(res_lines) + + # Restore print opts + numpy.set_printoptions(**orig_opts) + return res + elif isinstance(self.v, str): + # Handle strings + if len(self.v) > 80: + return "(" + repr(self.v[:30]) + " ... " + repr(self.v[-30:]) + ")" + else: + return self.v.__repr__() + else: + return self.v.__repr__() + + +class ElidedPrettyPrinter(PrettyPrinter): + """ + PrettyPrinter subclass that elides long lists/arrays/strings + """ + + def __init__(self, *args, **kwargs): + self.threshold = kwargs.pop("threshold", 200) + PrettyPrinter.__init__(self, *args, **kwargs) + + def _format(self, val, stream, indent, allowance, context, level): + if ElidedWrapper.is_wrappable(val): + elided_val = ElidedWrapper(val, self.threshold, indent) + + return self._format(elided_val, stream, indent, allowance, context, level) + else: + return PrettyPrinter._format( + self, val, stream, indent, allowance, context, level + ) + + +def node_generator(node, path=()): + """ + General, node-yielding generator. + + Yields (node, path) tuples when it finds values that are dict + instances. + + A path is a sequence of hashable values that can be used as either keys to + a mapping (dict) or indices to a sequence (list). A path is always wrt to + some object. Given an object, a path explains how to get from the top level + of that object to a nested value in the object. + + :param (dict) node: Part of a dict to be traversed. + :param (tuple[str]) path: Defines the path of the current node. + :return: (Generator) + + Example: + + >>> for node, path in node_generator({'a': {'b': 5}}): + ... print(node, path) + {'a': {'b': 5}} () + {'b': 5} ('a',) + + """ + if not isinstance(node, dict): + return # in case it's called with a non-dict node at top level + yield node, path + for key, val in node.items(): + if isinstance(val, dict): + for item in node_generator(val, path + (key,)): + yield item + + +def get_by_path(obj, path): + """ + Iteratively get on obj for each key in path. + + :param (list|dict) obj: The top-level object. + :param (tuple[str]|tuple[int]) path: Keys to access parts of obj. + + :return: (*) + + Example: + + >>> figure = {'data': [{'x': [5]}]} + >>> path = ('data', 0, 'x') + >>> get_by_path(figure, path) + [5] + """ + for key in path: + obj = obj[key] + return obj + + +def decode_unicode(coll): + if isinstance(coll, list): + for no, entry in enumerate(coll): + if isinstance(entry, (dict, list)): + coll[no] = decode_unicode(entry) + else: + if isinstance(entry, str): + try: + coll[no] = str(entry) + except UnicodeEncodeError: + pass + elif isinstance(coll, dict): + keys, vals = list(coll.keys()), list(coll.values()) + for key, val in zip(keys, vals): + if isinstance(val, (dict, list)): + coll[key] = decode_unicode(val) + elif isinstance(val, str): + try: + coll[key] = str(val) + except UnicodeEncodeError: + pass + coll[str(key)] = coll.pop(key) + return coll |