PK!hf99shinyutils/__init__.py__version__ = "0.5.0" import argparse from shinyutils.matwrap import MatWrap from shinyutils.subcls import ( get_subclasses, get_subclass_names, get_subclass_from_name, build_subclass_object, ) from shinyutils.argp import ( comma_separated_ints, LazyHelpFormatter, OutputFileType, OutputDirectoryType, ClassType, ) from shinyutils.logng import build_log_argp, conf_logging shiny_arg_parser = argparse.ArgumentParser( usage=argparse.SUPPRESS, formatter_class=LazyHelpFormatter ) build_log_argp(shiny_arg_parser) conf_logging() PK!Xfshinyutils/argp.py"""argp.py: utilities for argparse.""" from argparse import ( ArgumentDefaultsHelpFormatter, ArgumentTypeError, MetavarTypeHelpFormatter, FileType, ) import logging import os import re import crayons from shinyutils.subcls import get_subclass_from_name class LazyHelpFormatter( ArgumentDefaultsHelpFormatter, MetavarTypeHelpFormatter ): # pylint: disable=no-member DEF_PAT = re.compile(r"(\(default: (.*?)\))") DEF_CSTR = str(crayons.magenta("default")) def _format_action(self, action): if action.dest == "help": return "" helpstr = action.help action.help = "\b" if action.nargs == 0: # hack to fix length of option strings action.option_strings = [ s + str(crayons.normal("", bold=True)) for s in action.option_strings ] astr = super()._format_action(action) m = re.search(self.DEF_PAT, astr) if m: mstr, dstr = m.groups() astr = astr.replace( mstr, f"({self.DEF_CSTR}: {crayons.magenta(dstr, bold=True)})" ) if helpstr: astr += f"\t{helpstr}\n" return astr def _get_default_metavar_for_optional(self, action): if action.type: try: return action.type.__name__ except AttributeError: return type(action.type).__name__ return None def _get_default_metavar_for_positional(self, action): if action.type: try: return action.type.__name__ except AttributeError: return type(action.type).__name__ return None def _metavar_formatter(self, action, default_metavar): base_formatter = super()._metavar_formatter(action, default_metavar) def color_wrapper(tuple_size): f = base_formatter(tuple_size) if not f: return f return ( str(crayons.red(" ".join(map(str, f)), bold=True)), *(("",) * (len(f) - 1)), ) return color_wrapper def __init__(self, *args, **kwargs): if "max_help_position" not in kwargs: kwargs["max_help_position"] = float("inf") if "width" not in kwargs: kwargs["width"] = float("inf") super().__init__(*args, **kwargs) def comma_separated_ints(string): try: return list(map(int, string.split(","))) except: raise ArgumentTypeError( f"`{string}` is not a comma separated list of ints" ) class OutputFileType(FileType): def __init__(self, *args, **kwargs): super().__init__("w", *args, **kwargs) def __call__(self, string): file_dir = os.path.dirname(string) if not os.path.exists(file_dir): logging.warning(f"no directory for {string}: trying to create") try: os.makedirs(file_dir) except Exception as e: raise ArgumentTypeError(f"could not create {file_dir}: {e}") logging.info(f"created {file_dir}") return super().__call__(string) class OutputDirectoryType: def __call__(self, string): if not os.path.exists(string): logging.warning(f"{string} not found: trying to create") try: os.makedirs(string) except Exception as e: raise ArgumentTypeError(f"cound not create {string}: {e}") logging.info(f"created {string}") return string class ClassType: def __init__(self, cls): self.cls = cls def __call__(self, string): try: return get_subclass_from_name(self.cls, string) except Exception as e: raise ArgumentTypeError(e) PK!R=ssshinyutils/data/mplcfg.json{ "axes.grid": true, "axes.grid.axis": "y", "axes.grid.which": "major", "axes.spines.bottom": false, "axes.spines.left": false, "axes.spines.right": false, "axes.spines.top": false, "backend": "pgf", "figure.constrained_layout.use": true, "legend.fancybox": false, "legend.frameon": false, "pgf.rcfonts": false, "pgf.texsystem": "lualatex", "savefig.format": "pdf", "savefig.frameon": false, "savefig.transparent": false, "scatter.marker": ".", "text.usetex": false, "xtick.direction": "out", "ytick.direction": "out", "ytick.major.size": 0 } PK!Crshinyutils/logng.py"""logng.py: utilities for logging.""" import argparse import logging import sys import crayons def build_log_argp(base_parser): """Add an argument for logging to the base_parser.""" class _SetLogLevel(argparse.Action): def __call__(self, parser, namespace, values, option_string=None): conf_logging(log_level=values) setattr(namespace, self.dest, values) base_parser.add_argument( "--log-level", type=str, choices=["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"], action=_SetLogLevel, ) return base_parser class ColorfulLogRecord(logging.LogRecord): """LogRecord with colors.""" def __init__(self, *args, **kwargs): # pylint: disable=no-member super().__init__(*args, **kwargs) if self.levelno == logging.CRITICAL: colf = crayons.red elif self.levelno == logging.ERROR: colf = crayons.magenta elif self.levelno == logging.WARNING: colf = crayons.yellow elif self.levelno == logging.INFO: colf = crayons.cyan else: colf = crayons.green self.levelname = str(colf(self.levelname, bold=True, always=True)) self.msg = ( crayons.colorama.Style.BRIGHT + str(self.msg) + crayons.colorama.Style.NORMAL ) def conf_logging(args=None, log_level=None): """Configure logging using args from `build_log_argp`.""" if log_level is None: if args is not None and hasattr(args, "log_level"): log_level = args.log_level else: log_level = "INFO" log_level_i = getattr(logging, log_level, logging.INFO) logging.basicConfig( level=log_level_i, format="%(levelname)s:%(filename)s.%(funcName)s.%(lineno)d:%(message)s", ) logging.root.setLevel(log_level_i) if sys.stderr.isatty(): logging.setLogRecordFactory(ColorfulLogRecord) PK!7K{ shinyutils/matwrap.py"""matwrap.py: wrapper around matplotlib.""" import json import warnings from pkg_resources import resource_filename class MatWrap: _rc_defaults_path = resource_filename("shinyutils", "data/mplcfg.json") with open(_rc_defaults_path, "r") as f: _rc_defaults = json.load(f) _mpl = None _plt = None _sns = None @classmethod def configure( cls, context="paper", style="ticks", font="Latin Modern Roman", latex_pkgs=None, **rc_extra, ): """ Arguments: context: seaborn context (paper/notebook/poster). style: seaborn style (whitegrid, darkgrid, etc.) font: latex font (passed directly to fontspec). latex_pkgs: list of packages to load in pgf preamble. rc_extra: matplotlib params (will overwrite defaults). """ rc = MatWrap._rc_defaults.copy() rc["pgf.preamble"] = [r"\usepackage{fontspec}"] rc["pgf.preamble"].append(rf"\setmainfont{{{font}}}") rc["pgf.preamble"].append(rf"\setsansfont{{{font}}}") if latex_pkgs is not None: for pkg in reversed(latex_pkgs): rc["pgf.preamble"].insert(0, rf"\usepackage{{{pkg}}}") rc.update(rc_extra) if cls._mpl is None: import matplotlib cls._mpl = matplotlib cls._mpl.rcParams.update(rc) import matplotlib.pyplot import seaborn cls._plt = matplotlib.pyplot cls._sns = seaborn else: cls._mpl.rcParams.update(rc) cls._sns.set(context, style, rc=rc) def __new__(cls): raise NotImplementedError( "MatWrap does not provide instances. Use the class methods." ) @classmethod def _ensure_conf(cls): if cls._mpl is None: cls.configure() @classmethod def mpl(cls): cls._ensure_conf() return cls._mpl @classmethod def plt(cls): cls._ensure_conf() return cls._plt @classmethod def sns(cls): cls._ensure_conf() return cls._sns @staticmethod def set_size_tight(fig, size): warnings.warn( "constrained_layout is enabled by default: don't use tight_layout", DeprecationWarning, ) fig.set_size_inches(*size) fig.tight_layout(pad=0, w_pad=0, h_pad=0) PK!oRvshinyutils/subcls.py"""subcls.py: utility functions for dealing with subclasses.""" def get_subclasses(cls): """Get all subclasses (even indirect) of the given class.""" subclasses = [] for c in cls.__subclasses__(): subclasses.append(c) subclasses.extend(get_subclasses(c)) return subclasses def get_subclass_names(cls): """Get the names of all subclasses of the given class.""" return [c.__name__ for c in get_subclasses(cls)] def get_subclass_from_name(base_cls, cls_name): """Get a subclass given its name.""" for c in get_subclasses(base_cls): if c.__name__ == cls_name: return c raise RuntimeError( "No such subclass of {}: {}".format(base_cls.__name__, cls_name) ) def build_subclass_object(base_cls, cls_name, kwargs): """Build an object of the named subclass.""" return get_subclass_from_name(base_cls, cls_name)(**kwargs) PK!u::"shinyutils-0.5.0.dist-info/LICENSEThe MIT License (MIT) Copyright (c) 2018 Jayanth Koushik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. PK!Hu)GTU shinyutils-0.5.0.dist-info/WHEEL HM K-*ϳR03rOK-J,/R(O-)$qzd&Y)r$UV&UrPK!Hy#shinyutils-0.5.0.dist-info/METADATAWr6+nEIIN9'jn ĘXt=II4Bq\ܰΤex]G+[?MUL]c_ T9Ȑ(ɸ˂%˜RG{{,IѽOf,e{~ϳ)Z[2 "v?>/saxcW)U5b9ə,|?\n 3(ЯSOt$ )OJ3.JHJOJ\݌, T.\!L+ʾ<Ӌ19t)/->azJ+ iɋ]z|?4neM%SWȦoBmعisU߭ iTZG3e.MMh`;c?wE5grDn|јRgF^ßr=UYiHc&K0ݧr)P)g 'ȹnw։zS'snVIG+ 0ˌ,l#0hw#|l+j tѨm6gy1|ԵqY7u.ZgRey$'vJ<Ƨ{ y/,ᚽ_A'Q/@Pi[fk uٕث܌:Ms~1\%^n *7R4 Ry3t LhK#4 6ɬ otq q"݌v t`x_e>ܪk词Es6H6;"鄪8R(ߪcXlG#SEsŐ[<=?XƢi `ǧo%<0KŚ3<3aG)6Д%nB*0w0ZhMЀ?0Sr_a.i׎ XO 2eeβ{۠0s킷CY^qD6l )^#_pQr>w@ZՖm-9ia%$Ҋs\eۑv5k:Zae ,/(T+m Lw}׻wp<]ߎWcd<{y§ nhO/ss'3ȌIPX"fqkIǗ{?hr]+YŰǫ(֍6'Y7s۵C A*Kok{^/JD'Oi4Mr8f]gZ|gabnͺ5 v3 wU=ip&wǽ<,pA5PK!HX!shinyutils-0.5.0.dist-info/RECORD}ɖ0@}} Xaы HbD&hPԯM=ힷc؉HuSEЌW)綾y=eCm)iZ 3U  ʏ(٘9x 5}`(t2:r2feY߽M D}:!T|j}p INnS՜lfy sڣ K\Kω?LJpaym?[/̤$HTZ5