Package: pyppy
pyppypyppyis a Python library that allows to initialize a global config object that can be used
throughout your code without passing a config object between all of your methods. Additionally,
pyppy comes with a function decorator that allows for easy retrieval of config attributes in methods.Please Read the Docshttps://pyppy.readthedocs.io/en/latest/InstallationpipinstallpyppyTable of ContentsUsecasesGlobal Config ObjectAutomatic Argument Filling from Config ObjectAutomatic Detection of Arguments to be FilledMixed ParametersExplicit Parameter FillingConditional Execution of Functions based on Global Config StateExact Value MatchingCustom ConditionsLogical Conjunction and Disjunction of ConditionsEnhancementsContributionUsecasespyppymight help you if you want one of the following:Easy global config access throughout your codeExecute methods conditionally based on the global configurationGlobal Config ObjectMore here:https://pyppy.readthedocs.io/en/latest/pyppy.config.htmlYou can use the methodinitialize_configto initialize a global config and then use
the config withconfig()all throughout your project. In the following example we use
it as a wrapper for arguments parsed withArgumentParserbut you can you any object
that has attributes to initialize a config.fromargparseimportArgumentParserfrompyppy.configimportinitialize_config,configparser=ArgumentParser()parser.add_argument("--debug",action="store_true",default=False)cli_args=["--debug"]args=parser.parse_args(cli_args)initialize_config(args)defdebug_log():ifconfig().debug:return"debugging">>>debug_log()debuggingAutomatic Argument Filling from Config ObjectMore here:https://pyppy.readthedocs.io/en/latest/pyppy.args.htmlAutomatic Detection of Arguments to be FilledIt gets even better. You can use the@fill_argsdecorator to automatically fill
function arguments from the global config object. If a function argument has the same name
as an attribute of your config it will automatically be filled with the corresponding value.
(We're assuming here you have initialized the same config as in the last example.)frompyppy.argsimportfill_argsinitialize_config()config().debug=True@fill_args()defdebug_log(debug):ifdebug:return"debugging">>>debug_log()debuggingMixed ParametersIf you have mixed parameters (parameters coming from the global config and parameters passed ad-hoc)
the decorator only fills the arguments which names exactly match with one of the attributes of
the global config.Please notethat the "normal" parameters
can then only be passed as keyword arguments when calling the function.frompyppy.configimportinitialize_config,configinitialize_config()config().debug=True@fill_args()defdebug_log(debug,message):ifdebug:returnf"debugging:{message}">>>debug_log(message="useful logs")debugging:usefullogsExplicit Parameter FillingIn some cases it's necessary to tell the decorator exactly which arguments should be filled
from the global config (e.g. when a function argument has the same name as an attribute of the
global config but should not be filled from the global config). Then you can pass the names of
the arguments to be filled to the decorator as strings. The decorator will then only fill the
parameters that are explicitly passed.initialize_config()config().debug=True@fill_args("debug")defdebug_log(debug,message):ifdebug:returnf"debugging:{message}">>>debug_log(message="useful logs")debugging:usefullogsConditional Execution of Functions based on Global Config StateMore here:https://pyppy.readthedocs.io/en/latest/pyppy.conditions.htmlExact Value Matchingpyppyallows you to execute functions based on conditions in your global config object.
In the example below, the@conditiondecorator will only execute the decorated function
when the specified condition evaluates to true in based on the global config. An expression
likeexp(debug=True)means that the function will only be executed if the attributedebughas the valueTrue.frompyppy.conditionsimportExp,conditioninitialize_config()config().debug=False@condition(Exp(debug=True))defdebug_log():return"hello">>>debug_log()<nooutput>>>>config().debug=True>>>debug_log()helloCustom ConditionsIn cases you want to apply more complex conditions the decorator allows you to pass
a function with custom logic. The function should always return a boolean value (which
specifies if the decorated function should be executed or not). In the example below, we
use a lambda function but you can naturally use normal functions too. The only requirements
are that the function should exactly expect one argument (the global config) and should return
a boolean value.initialize_config()config().log_level="WARN_LEVEL_1"@condition(Exp(lambdaconfig:config.log_level.startswith("WARN")))deflog_warn():return"WARNING">>>log_warn()WARNING>>>config().log_level>>>log_warn()INFO_LEVEL_2Logical Conjunction and Disjunction of ConditionsIf you have multiple conditions that have to be true at the same time or either one has
to be true you can useor_andand_to build the logic around them.or_andandcan be nested if necessary.frompyppy.conditionsimportcondition,Exp,and_initialize_config()config().log_level="WARN"config().specific_log_level="LEVEL_1"@condition(and_(Exp(log_level="WARN"),Exp(specific_log_level="LEVEL_1")))deflog_warn_level_1():return"WARNING LEVEL 1">>>log_warn_level_1()WARNINGLEVEL1>>>config().log_level="INFO">>>log_warn_level_1()<nooutput>EnhancementsWe're working on some enhancements so stay tuned :)ContributionFeel free to create pull requests or contact me if you want to become a permanent
contributor.