PK!4 Everyone is permitted to copy and distribute verbatim or modified copies of this license document, and changing it is allowed as long as the name is changed. DO WHAT THE FUCK YOU WANT TO BUT IT'S NOT MY FAULT PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. You just DO WHAT THE FUCK YOU WANT TO. 1. Do not hold the author(s), creator(s), developer(s) or distributor(s) liable for anything that happens or goes wrong with your use of the work. PK!po/__init__.pyPK!MMpo/simple_test/__init__.pyfrom .run import run from .meta import version __all__ = ["run", "version"] PK!Mf(>>po/simple_test/cli/__init__.pyfrom .index import runSimpleTest __all__ = ["runSimpleTest"] PK! ɑpo/simple_test/cli/index.py# ------- # # Imports # # ------- # from traceback import format_exc from types import SimpleNamespace as o from ..meta import version from .usage import usage from .validateAndParseArgs import validateAndParseArgs import os # ---- # # Init # # ---- # twoLineSeps = os.linesep + os.linesep # ---- # # Main # # ---- # def createRunSimpleTest(run): return lambda args: runSimpleTest(run, args) def runSimpleTest(run, args): result = o(stdout=None, stderr=None, code=None) numArgs = len(args) if numArgs == 1: if args[0] == "--help": result.stdout = usage result.code = 0 return result elif args[0] == "--version": result.stdout = version result.code = 0 return result validationResult = validateAndParseArgs(args, result) if validationResult.hasError: return validationResult.cliResult argsObj = validationResult.argsObj isSilent = argsObj.silent try: subprocessReturnCode = run( reporter=argsObj.reporter, projectDir=argsObj.projectDir, silent=isSilent, ) result.code = subprocessReturnCode return result except: if not isSilent: result.stderr = ( "An unexpected error occurred" + twoLineSeps + format_exc() ) result.code = 2 return result PK!\epo/simple_test/cli/usage.pyfrom textwrap import dedent usage = dedent( f""" Usage simple-test [options] simple-test (--help | --version) Options --project-dir the project dir from which tests are found. Defaults to `os.getcwd()` --silent a flag which disables output and prevents the reporter from being called. --reporter module name with a 'report' function. The default reporter is 'simple_test_default_reporter'. Relative modules e.g. "..myModule" are not yet supported. Returns an exit code of 0 for a successful run 1 for a failed run 2 for an error """ ) PK!/S *po/simple_test/cli/validateAndParseArgs.py# ------- # # Imports # # ------- # from types import SimpleNamespace as o from ..fns import isLaden from .usage import usage import os # ---- # # Init # # ---- # arguments = set(["--project-dir", "--reporter", "--silent"]) helpOrVersion = set(["--help", "--version"]) # ---- # # Main # # ---- # def validateAndParseArgs(args, cliResult): argsObj = o(reporter=None, projectDir=None, silent=False) validationResult = o( argsObj=argsObj, cliResult=cliResult, hasError=False, positionalArgs=[] ) i = 0 while i < len(args): if not args[i].startswith("--"): break arg = args[i] if arg not in arguments: if not argsObj.silent: if arg in helpOrVersion: cliResult.stderr = ( f"'{arg}' must be the only argument when passed" ) else: cliResult.stderr = f"invalid option '{arg}'" cliResult.stderr += os.linesep + usage cliResult.code = 2 validationResult.hasError = True return validationResult if arg == "--silent": argsObj.silent = True elif arg == "--reporter": if i == len(args) - 1: if not argsObj.silent: cliResult.stderr = "'--reporter' must be given a value" cliResult.stderr += os.linesep + usage cliResult.code = 2 validationResult.hasError = True return validationResult i += 1 arg = args[i] argsObj.reporter = arg elif arg == "--project-dir": if i == len(args) - 1: if not argsObj.silent: cliResult.stderr = "'--project-dir' must be given a value" cliResult.stderr += os.linesep + usage cliResult.code = 2 validationResult.hasError = True return validationResult i += 1 arg = args[i] argsObj.projectDir = arg i += 1 positionalArgs = args[i:] if isLaden(positionalArgs): if not argsObj.silent: cliResult.stderr = "this command doesn't take positional arguments" cliResult.stderr += os.linesep + usage cliResult.code = 2 validationResult.hasError = True return validationResult return validationResult PK!d po/simple_test/fns/__init__.pyfrom .forEach import forEach from .invokeAttr import invokeAttr from .isEmpty import isEmpty from .isLaden import isLaden from .isSomething import isSomething from .joinWith import joinWith from .justReturn import justReturn from .keepWhen import keepWhen from .passThrough import passThrough from .raise_ import raise_ __all__ = [ "forEach", "invokeAttr", "isEmpty", "isLaden", "isSomething", "joinWith", "justReturn", "keepWhen", "passThrough", "raise_", ] PK!)po/simple_test/fns/decorators/__init__.pyPK![`)gEE.po/simple_test/fns/decorators/argIsCallable.pyfrom inspect import signature import wrapt @wrapt.decorator def argIsCallable(fn, _instance, args, kwargs): if not callable(args[0]): argName = list(signature(fn).parameters)[0] fnName = fn.__name__ raise ValueError(f"{fnName} requires {argName} to be callable") return fn(*args, **kwargs) PK!waII+po/simple_test/fns/decorators/argIsClass.pyfrom inspect import isclass, signature import wrapt @wrapt.decorator def argIsClass(fn, _instance, args, kwargs): if not isclass(args[0]): argName = list(signature(fn).parameters)[0] fnName = fn.__name__ raise ValueError(f"{fnName} requires {argName} to be a class") return fn(*args, **kwargs) PK!WḲ.po/simple_test/fns/decorators/argIsInstance.pyfrom inspect import signature from ..internal.raise_ import raise_ import wrapt def argIsInstance(aType, fnName=None): @wrapt.decorator def wrapper(fn, _instance, args, kwargs): nonlocal fnName typePassed = type(args[0]) if not isinstance(typePassed, aType): argName = list(signature(fn).parameters)[0] fnName = fnName or fn.__name__ typeName = aType.__name__ raise_( ValueError, f""" {fnName} requires {argName} to be an instance of {typeName} type passed: {typePassed.__name__} """, ) return fn(*args, **kwargs) return wrapper PK!0po/simple_test/fns/decorators/argIsListOfType.pyfrom ordered_set import OrderedSet import wrapt from ..internal.discardWhen import discardWhen from ..internal.get import get from ..internal.getArgName import getArgName from ..internal.isLaden import isLaden from ..internal.isType import isType from ..internal.joinWith import joinWith from ..internal.map_ import map_ from ..internal.passThrough import passThrough from ..internal.raise_ import raise_ from ..internal.sort import sort from ..internal.toType import toType def argIsListOfType(aType): @wrapt.decorator def wrapper(fn, _instance, args, kwargs): typePassed = type(args[0]) fnName = fn.__name__ typeName = aType.__name__ if typePassed is not list: argName = getArgName(fn) raise_( ValueError, f"""\ {fnName} requires {argName} to have the type list type passed: {typePassed.__name__} """, ) invalidTypes = discardWhen(isType(aType))(args[0]) if isLaden(invalidTypes): argName = getArgName(fn) invalidTypeNames = passThrough( invalidTypes, [ map_(toType), OrderedSet, list, map_(get("__name__")), sort, joinWith(", "), ], ) raise_( ValueError, f"""\ {fnName} requires {argName} to be a list of {typeName} invalid types passed: {invalidTypeNames} """, ) return fn(*args, **kwargs) return wrapper PK!E*po/simple_test/fns/decorators/argIsType.pyfrom inspect import signature from ..internal.raise_ import raise_ import wrapt def argIsType(aType): @wrapt.decorator def wrapper(fn, _instance, args, kwargs): typePassed = type(args[0]) if typePassed is not aType: argName = list(signature(fn).parameters)[0] fnName = fn.__name__ typeName = aType.__name__ raise_( ValueError, f""" {fnName} requires {argName} to have the type {typeName} type passed: {typePassed.__name__} """, ) return fn(*args, **kwargs) return wrapper PK!`c??po/simple_test/fns/forEach.py# ------- # # Imports # # ------- # from types import SimpleNamespace from .internal.makeGenericCallFn import makeGenericCallFn from .internal.getTypedResult import getTypedResult from .decorators.argIsCallable import argIsCallable # ---- # # Main # # ---- # @argIsCallable def forEach(fn): fnName = forEach.__name__ callFn = makeGenericCallFn(fn, 3, fnName) def forEach_inner(collection): typedForEach = getTypedResult(collection, typeToForEach, fnName) return typedForEach(callFn, collection) return forEach_inner # ------- # # Helpers # # ------- # def forEach_dict(callFn, aDict): for key, val in aDict.items(): callFn(val, key, aDict) return aDict def forEach_list(callFn, aList): for idx, el in enumerate(aList): callFn(el, idx, aList) return aList def forEach_simpleNamespace(callFn, aSimpleNamespace): forEach_dict(callFn, aSimpleNamespace.__dict__) return aSimpleNamespace typeToForEach = { dict: forEach_dict, list: forEach_list, SimpleNamespace: forEach_simpleNamespace, } PK!B u*po/simple_test/fns/internal/NotCallable.pyfrom types import SimpleNamespace from .mAssignToSelf import mAssignToSelf from .raise_ import raise_ import os class NotCallable(SimpleNamespace): def __init__(self, fnName, **typeToFn): self._fnName = fnName self._typeToFn = typeToFn mAssignToSelf(typeToFn, self) def __call__(self, *args, **kwargs): availableKeys = list(self._typeToFn.keys()) fnName = self._fnName raise_( TypeError, f""" The utility '{fnName}' is not callable because it needs to know what to return in the case of an empty list. example usage: {fnName}.{availableKeys[0]}([...]) available keys: {os.linesep.join(availableKeys)} """, ) PK!'po/simple_test/fns/internal/__init__.pyPK!F*po/simple_test/fns/internal/discardWhen.py# ------- # # Imports # # ------- # from .getTypedResult import getTypedResult from .makeGenericCallFn import makeGenericCallFn from ..decorators.argIsCallable import argIsCallable # ---- # # Main # # ---- # @argIsCallable def discardWhen(predicate): fnName = discardWhen.__name__ shouldDiscard = makeGenericCallFn(predicate, 3, fnName) def discardWhen_inner(collection): typedDiscardWhen = getTypedResult(collection, typeToDiscardWhen, fnName) return typedDiscardWhen(shouldDiscard, collection) return discardWhen_inner # ------- # # Helpers # # ------- # def discardWhen_list(shouldDiscard, aList): result = [] for idx, el in enumerate(aList): if not shouldDiscard(el, idx, aList): result.append(el) return result def discardWhen_dict(shouldDiscard, aDict): result = {} for key, val in aDict.items(): if shouldDiscard(val, key, aDict): result[key] = val return result typeToDiscardWhen = {list: discardWhen_list, dict: discardWhen_dict} PK!ss"po/simple_test/fns/internal/get.pydef get(attrName): def get_inner(something): return getattr(something, attrName) return get_inner PK!)jj)po/simple_test/fns/internal/getArgName.pyfrom inspect import signature def getArgName(fn, idx=0): return list(signature(fn).parameters)[idx] PK!X-po/simple_test/fns/internal/getFnSignature.pyfrom inspect import signature from .raise_ import raise_ def getFnSignature(fn, callerName): try: return signature(fn) except Exception as e: raise_( ValueError, f"""\ '{callerName}' is unable to get the signature of the passed callable callable passed: {fn.__name__} one reason this could occur is the callable is written in c (e.g. the builtin 'str' callable). """, fromException=e, ) PK!k5po/simple_test/fns/internal/getNumPositionalParams.py# ------- # # Imports # # ------- # from inspect import Parameter from math import inf from .getFnSignature import getFnSignature from .iif import iif # ---- # # Init # # ---- # _nonVarPositionalParamKinds = { Parameter.POSITIONAL_ONLY, Parameter.POSITIONAL_OR_KEYWORD, } # ---- # # Main # # ---- # # # Returns a tuple # numRequired: number of required positional params # numAllowed: number of allowed positional params # def getNumPositionalParams(fn, callerName): sig = getFnSignature(fn, callerName) numAllowed = iif(_hasVarPositionalParam(sig), inf, 0) numRequired = 0 for p in sig.parameters.values(): if p.kind in _nonVarPositionalParamKinds: numAllowed += 1 if p.default is Parameter.empty: numRequired += 1 return (numRequired, numAllowed) # ------- # # Helpers # # ------- # def _hasVarPositionalParam(sig): for p in sig.parameters.values(): if p.kind is Parameter.VAR_POSITIONAL: return True PK!w<-po/simple_test/fns/internal/getTypedResult.py# # README # - I'm not sure what to call this. Its purpose is to centralize the type # validation, minimizing copy/paste. # # ------- # # Imports # # ------- # from .raise_ import raise_ from .get import get # ---- # # Init # # ---- # getName = get("__name__") # # we need a unique object here to ensure the 'typeToSomething' doesn't lead us # to a 'None' value # nothing = object() # ---- # # Main # # ---- # def getTypedResult(value, typeToSomething, fnName): valueType = type(value) result = typeToSomething.get(valueType, nothing) if _isSomething(result): return result supportedTypes = ", ".join(map(getName, typeToSomething.keys())) raise_( ValueError, f"""\ {fnName} doesn't support the type '{valueType.__name__}' supported types: {supportedTypes} """, ) # ------- # # Helpers # # ------- # def _isSomething(x): return x is not nothing PK!;||"po/simple_test/fns/internal/iif.pydef iif(condition, whenTruthy, whenFalsey): if condition: return whenTruthy else: return whenFalsey PK!ws{33&po/simple_test/fns/internal/isLaden.pydef isLaden(aList): return len(aList) is not 0 PK!Ȋ/po/simple_test/fns/internal/isOnlyWhitespace.pyimport re onlyWhitespaceRe = re.compile(r"\s*$") def isOnlyWhitespace(aString): return onlyWhitespaceRe.match(aString) is not None PK!f%po/simple_test/fns/internal/isType.pyfrom inspect import isclass def isType(aType): if not isclass(aType): raise ValueError("isType requires argument 'aType' to pass isclass") def isType_inner(something): return type(something) is aType return isType_inner PK!v_R*++'po/simple_test/fns/internal/joinWith.py# ------- # # Imports # # ------- # from ordered_set import OrderedSet from .getTypedResult import getTypedResult # ---- # # Main # # ---- # def joinWith(separator): def joinWith_inner(collection): typedJoinWith = getTypedResult(collection, typeToJoinWith, "joinWith") return typedJoinWith(separator, collection) return joinWith_inner # ------- # # Helpers # # ------- # def joinWith_iterable(separator, aList): return separator.join(aList) typeToJoinWith = {list: joinWith_iterable, OrderedSet: joinWith_iterable} PK!K,po/simple_test/fns/internal/mAssignToSelf.py# # assigns dict key-values onto self as attributes # return secondaryObj # ** mutates secondaryObj # def mAssignToSelf(aDict, aSelf): for k, v in aDict.items(): setattr(aSelf, k, v) return aSelf PK!K)po/simple_test/fns/internal/makeCallFn.py# ------- # # Imports # # ------- # from math import inf from .returnFirstArgument import returnFirstArgument as identity from .getNumPositionalParams import getNumPositionalParams # ---- # # Main # # ---- # def makeCallFn(fn, callerName, *, modifyResult=identity): (_, allowed) = getNumPositionalParams(fn, callerName) if allowed is inf: return lambda *args, **kwargs: modifyResult(fn(*args, **kwargs)) else: return lambda *args, **kwargs: modifyResult( fn(*args[:allowed], **kwargs) ) PK!T-0po/simple_test/fns/internal/makeGenericCallFn.py# ------- # # Imports # # ------- # from math import inf from .getNumPositionalParams import getNumPositionalParams from .raise_ import raise_ # ---- # # Main # # ---- # def makeGenericCallFn(fn, maxParams, callerName): required, allowed = getNumPositionalParams(fn, callerName) if allowed is inf: allowed = maxParams if required > maxParams: raise_( ValueError, f""" {callerName} can only take functions with up to {maxParams} positional params. The function '{fn.__name__}' requires {required} """, ) return lambda *args, **kwargs: fn(*args[:allowed], **kwargs) PK!G~#po/simple_test/fns/internal/map_.py# ------- # # Imports # # ------- # from .makeGenericCallFn import makeGenericCallFn from .getTypedResult import getTypedResult from ..decorators.argIsCallable import argIsCallable # ---- # # Main # # ---- # @argIsCallable def map_(mapperFn): fnName = map_.__name__ callMapperFn = makeGenericCallFn(mapperFn, 3, fnName) def map_inner(collection): typedMap = getTypedResult(collection, typeToMap, fnName) return typedMap(callMapperFn, collection) return map_inner # ------- # # Helpers # # ------- # def map_list(callMapperFn, aList): result = [] for idx, el in enumerate(aList): result.append(callMapperFn(el, idx, aList)) return result typeToMap = {list: map_list} PK!yy*po/simple_test/fns/internal/passThrough.pyfrom .reduce import reduce def passThrough(arg, fnList): return reduce(lambda result, fn: fn(result), arg)(fnList) PK!W%po/simple_test/fns/internal/raise_.pyfrom tedent import tedent from .isOnlyWhitespace import isOnlyWhitespace import os def raise_(errorClass, message, *, fromException=None): allLines = message.split(os.linesep) if isOnlyWhitespace(allLines[0]) and isOnlyWhitespace(allLines[-1]): message = tedent(message) err = errorClass(message) if fromException is None: raise err else: raise err from fromException PK!Et%po/simple_test/fns/internal/reduce.py# ------- # # Imports # # ------- # from .makeGenericCallFn import makeGenericCallFn from .getTypedResult import getTypedResult from ..decorators.argIsCallable import argIsCallable # ---- # # Main # # ---- # @argIsCallable def reduce(fn, initial): reducerFn = makeGenericCallFn(fn, 4, "reduce") def reduce_inner(collection): typedReduce = getTypedResult(collection, typeToReduce, "reduce") return typedReduce(reducerFn, initial, collection) return reduce_inner # ------- # # Helpers # # ------- # def reduce_list(reducerFn, initial, aList): result = initial for idx, el in enumerate(aList): result = reducerFn(result, el, idx, aList) return result typeToReduce = {list: reduce_list} PK!pjj2po/simple_test/fns/internal/returnFirstArgument.pyfrom .iif import iif def returnFirstArgument(*args, **kwargs): return iif(len(args), args[0], None) PK!\xx.po/simple_test/fns/internal/sanitizeAscDesc.pyfrom .raise_ import raise_ ascDescSet = {"asc", "desc"} def sanitizeAscDesc(ascOrDesc): sanitized = ascOrDesc.lower() if sanitized not in ascDescSet: raise_( ValueError, f""" ascOrDesc must be either 'asc' or 'desc' (case insensitive) value given: {ascOrDesc} """, ) return sanitized PK!0oo#po/simple_test/fns/internal/sort.py# ------- # # Imports # # ------- # from .getTypedResult import getTypedResult # ---- # # Main # # ---- # def sort(collection): typedSort = getTypedResult(collection, typeToSort, "sort") return typedSort(collection) # ------- # # Helpers # # ------- # def sort_viaSorted(something): return sorted(something) typeToSort = {list: sort_viaSorted} PK!V;22%po/simple_test/fns/internal/toType.pydef toType(something): return type(something) PK!%tt po/simple_test/fns/invokeAttr.pydef invokeAttr(key): def invokeAttr_inner(obj): return getattr(obj, key)() return invokeAttr_inner PK!¢[po/simple_test/fns/isEmpty.pyfrom types import SimpleNamespace # TODO: make 'isEmpty' generic like the other utils def isEmpty(lenAble): if isinstance(lenAble, SimpleNamespace): return len(lenAble.__dict__) is 0 else: return len(lenAble) is 0 PK!X33po/simple_test/fns/isLaden.pyfrom .internal.isLaden import isLaden # noqa f401 PK!P1--!po/simple_test/fns/isSomething.pydef isSomething(x): return x is not None PK!955po/simple_test/fns/joinWith.pyfrom .internal.joinWith import joinWith # noqa f401 PK!< HH po/simple_test/fns/justReturn.pydef justReturn(something): return lambda *args, **kwargs: something PK!Bpo/simple_test/fns/keepWhen.py# ------- # # Imports # # ------- # from .internal.makeGenericCallFn import makeGenericCallFn from .internal.getTypedResult import getTypedResult from .decorators.argIsCallable import argIsCallable # ---- # # Main # # ---- # @argIsCallable def keepWhen(predicate): fnName = keepWhen.__name__ shouldKeep = makeGenericCallFn(predicate, 3, fnName) def keepWhen_inner(collection): typedKeepWhen = getTypedResult(collection, typeToKeepWhen, fnName) return typedKeepWhen(shouldKeep, collection) return keepWhen_inner # ------- # # Helpers # # ------- # def keepWhen_list(shouldKeep, aList): result = [] for idx, el in enumerate(aList): if shouldKeep(el, idx, aList): result.append(el) return result def keepWhen_dict(shouldKeep, aDict): result = {} for key, val in aDict.items(): if shouldKeep(val, key, aDict): result[key] = val return result typeToKeepWhen = {list: keepWhen_list, dict: keepWhen_dict} PK!F;;!po/simple_test/fns/passThrough.pyfrom .internal.passThrough import passThrough # noqa f401 PK!(11po/simple_test/fns/raise_.pyfrom .internal.raise_ import raise_ # noqa f401 PK!po/simple_test/meta.pyversion = "0.1.0" PK!tcaapo/simple_test/run/__init__.pyfrom .run import createRun import subprocess run = createRun(subprocess.run) __all__ = ["run"] PK!pJpo/simple_test/run/run.py# ------- # # Imports # # ------- # from os import path from .validateRunParams import validateRunParams from ..fns import raise_ import os import sys # ---- # # Main # # ---- # def createRun(subprocessRun): return lambda **kwargs: run(subprocessRun, **kwargs) def run(subprocessRun, *, projectDir=None, reporter=None, silent=False): validateRunParams(projectDir, reporter, silent) if projectDir is None: projectDir = os.getcwd() else: projectDir = path.normpath(projectDir) if reporter is None: reporter = "simple_test_default_reporter" ensureTestsDirExists(projectDir) subprocessResult = subprocessRun( [ sys.executable, "-m", "simple_test_process", projectDir, reporter, str(silent), ], cwd=projectDir, ) return subprocessResult.returncode # ------- # # Helpers # # ------- # def ensureTestsDirExists(projectDir): testsDir = path.join(projectDir, "tests") if not path.isdir(testsDir): raise_( Exception, f""" projectDir must contain a directory 'tests' projectDir: {projectDir} """, ) PK!,xx'po/simple_test/run/validateRunParams.py# ------- # # Imports # # ------- # from ..fns import isEmpty, isSomething, raise_ from os import path # ---- # # Main # # ---- # def validateRunParams(projectDir, reporter, silent): if isSomething(projectDir): if not isinstance(projectDir, str): raise_( TypeError, f"""\ 'projectDir' must be an instance of str type: {type(silent).__name__} """, ) if isEmpty(projectDir): raise ValueError("'projectDir' cannot be an empty string") if not path.isabs(projectDir): raise_( ValueError, f""" 'projectDir' must pass 'os.path.isabs' projectDir: {projectDir} """, ) if not path.isdir(projectDir): raise_( ValueError, f""" 'projectDir' must pass 'os.path.isdir' projectDir: {projectDir} """, ) if isSomething(reporter): if not isinstance(reporter, str): raise_( TypeError, f""" 'reporter' must be an instance of str type: {type(reporter).__name__} """, ) if isEmpty(reporter): raise ValueError("'reporter' cannot be an empty string") if reporter.startswith("."): raise_( ValueError, f""" relative reporter modules are not yet supported reporter: {reporter} """, ) if isSomething(silent) and not isinstance(silent, bool): raise_( TypeError, f"""\ 'silent' must be an instance of bool type: {type(silent).__name__} """, ) PK!p:22po/simple_test/script.pyfrom .cli import runSimpleTest from .run import run import sys def printErr(msg): print(msg, file=sys.stderr) def main(): result = runSimpleTest(run, sys.argv[1:]) if result.stdout: print(result.stdout) if result.stderr: printErr(result.stderr) exit(result.code) PK!H\H1:/po.simple_test-0.1.0.dist-info/entry_points.txtN+I/N.,()*-I-I-.-׃pA\=<..PK!HڽTU$po.simple_test-0.1.0.dist-info/WHEEL A н#Z;/"d&F[xzw@Zpy3Fv]\fi4WZ^EgM_-]#0(q7PK!HM'po.simple_test-0.1.0.dist-info/METADATAOo0siH˶R8L2I\XK=Aťɖ{otM)87HQgÊ1KF]>;Mq|$Li.M_]3DŜ՜Ȥ%FoZy\v ziZ1dˤTW_$k]<>:]lx|L!agjaz: #HDnRObPd#@ʈ ILdJPK!HJ I%po.simple_test-0.1.0.dist-info/RECORDIZ`>fPZpB{__܌xf^ފ:Xa q!(Ak!#$_VltDvWZ\އHk = ]A8 [dfY)ue$9`O5nq$f6ynUQ4aUjκ~Љkt)//e:𑓛+əVW}͛(^_p deF! /ƀ{lRQs@0C3vER~r#cnI0D; <c6C𢰃'|2Xi]5wnWip5m -ZB58I3+oi 3(f'vjJ@1N N|P8l{0[i>TUdu=UVq!T &2g;7}n[ /*`#1݊tW֣F$wT8$>5 #hy kYy yj]x:|BFGâ7Rǖ,ܧwy\w:o, [^qk!o!bW;Z=o3„%i[I!dEf/P XgW\5e{lCqxgM炙.!{ ,`_R & ? )RK쏜ݣ;Em/~|AYܼvVo"IL Y<2}p=Ӧcjg p-`./tحBK"W4{qOiv^`ҽ-bu+y7 ԯ?ZkͮsQĔsh육fl.ݞN@jC>Ŗ۠~M-1d9$XLCw@۬dP7B:XSۏ5,D)}ٖV@Z \oO-S% tey%+LXkL29^2 ݖ L6)ѤgF޳%3zq3 ٶ>_emE7n>P9ӟJu#QC4@Rv:_[faZq'W6T)ƗwA-[Ő4X"_Gj #S6{!LD)ќ<+ٞkqwuW0NpCч>n>?M !%+Pm7^o'sC,B|IC$ jнNmQ9OK'f ZeM#j-e`$_ ;-B_\w5k#Ɔ^ [V|cSHܜzV\T>ϕ3li0-G'Dw[v :X8~E'RU?rId1>Y\hlyM'mg>Һ~8:n^s.%2-\N^[+44t_v=3fPNǸ==DA! xJXxDQߨ (=8YUI`Xu1\v,8%pO5!jcGE0.\lVܒ3Ox$fj߳綌q_2ErHWHp͖= 8L(oN1_AI&RuY0DBi}9CCՐZU{?}:NBrHO%3lk䪐7Hh :N1˛; c,9Rlkyiz% CM[ x)ˬ~y=tMqȴ4 mV0?^2{"nUr/2dڑz.s}ֵһ`^D-D\@m1>:<*d^Ǟ\c>y[8Fi^Uƒ&^5;,h|OY73KߜHZIѥi"{@::]fdVzC?!~ yN5ܣw_ ]l;ދ½|;|ZywhR<3Ƚ!;T- M1sPϗgXU»Gr @GoO7+ D  5?O[?̩s99CGG\z2&'ujٮ iϻL=#~hޜ{2s4#%B?3&itO{zm v-Nf/(k8LU.>Ipo/simple_test/cli/__init__.pyPK! ɑpo/simple_test/cli/index.pyPK!\e po/simple_test/cli/usage.pyPK!/S * po/simple_test/cli/validateAndParseArgs.pyPK!d po/simple_test/fns/__init__.pyPK!)po/simple_test/fns/decorators/__init__.pyPK![`)gEE.po/simple_test/fns/decorators/argIsCallable.pyPK!waII+po/simple_test/fns/decorators/argIsClass.pyPK!WḲ.$po/simple_test/fns/decorators/argIsInstance.pyPK!0>po/simple_test/fns/decorators/argIsListOfType.pyPK!E*9&po/simple_test/fns/decorators/argIsType.pyPK!`c?? )po/simple_test/fns/forEach.pyPK!B u*-po/simple_test/fns/internal/NotCallable.pyPK!'0po/simple_test/fns/internal/__init__.pyPK!F*(1po/simple_test/fns/internal/discardWhen.pyPK!ss"5po/simple_test/fns/internal/get.pyPK!)jj)?6po/simple_test/fns/internal/getArgName.pyPK!X-6po/simple_test/fns/internal/getFnSignature.pyPK!k5A9po/simple_test/fns/internal/getNumPositionalParams.pyPK!w<-=po/simple_test/fns/internal/getTypedResult.pyPK!;||"Apo/simple_test/fns/internal/iif.pyPK!ws{33&JBpo/simple_test/fns/internal/isLaden.pyPK!Ȋ/Bpo/simple_test/fns/internal/isOnlyWhitespace.pyPK!f%Cpo/simple_test/fns/internal/isType.pyPK!v_R*++'Dpo/simple_test/fns/internal/joinWith.pyPK!K,GGpo/simple_test/fns/internal/mAssignToSelf.pyPK!K)jHpo/simple_test/fns/internal/makeCallFn.pyPK!T-0Jpo/simple_test/fns/internal/makeGenericCallFn.pyPK!G~#Mpo/simple_test/fns/internal/map_.pyPK!yy*Ppo/simple_test/fns/internal/passThrough.pyPK!W%Qpo/simple_test/fns/internal/raise_.pyPK!Et%Spo/simple_test/fns/internal/reduce.pyPK!pjj2Vpo/simple_test/fns/internal/returnFirstArgument.pyPK!\xx.eWpo/simple_test/fns/internal/sanitizeAscDesc.pyPK!0oo#)Ypo/simple_test/fns/internal/sort.pyPK!V;22%Zpo/simple_test/fns/internal/toType.pyPK!%tt N[po/simple_test/fns/invokeAttr.pyPK!¢[\po/simple_test/fns/isEmpty.pyPK!X33-]po/simple_test/fns/isLaden.pyPK!P1--!]po/simple_test/fns/isSomething.pyPK!955^po/simple_test/fns/joinWith.pyPK!< HH x^po/simple_test/fns/justReturn.pyPK!B^po/simple_test/fns/keepWhen.pyPK!F;;!-cpo/simple_test/fns/passThrough.pyPK!(11cpo/simple_test/fns/raise_.pyPK!dpo/simple_test/meta.pyPK!tcaaXdpo/simple_test/run/__init__.pyPK!pJdpo/simple_test/run/run.pyPK!,xx'jpo/simple_test/run/validateRunParams.pyPK!p:22qpo/simple_test/script.pyPK!H\H1:/-spo.simple_test-0.1.0.dist-info/entry_points.txtPK!HڽTU$spo.simple_test-0.1.0.dist-info/WHEELPK!HM'Atpo.simple_test-0.1.0.dist-info/METADATAPK!HJ I%vpo.simple_test-0.1.0.dist-info/RECORDPK99O`