Package: logfunc
logfunc - @logf()@logf()is a Python decorator designed for uncomplicated and immediate addition of logging to functions. Its main goal is to provide developers with a tool that can be added quickly to any function and left in place without further adjustments.I originally made@logf()for my own use, but I hope it can be useful to others as well.HighlightsAsync Support: Incorporated from version 1.6 onwards.Broad Python 3 Compatibility: Designed to work seamlessly across multiple Python 3 versions,Effortless Logging: Implement logging without disrupting the flow of your code.Leave-and-Forget: Once integrated, no further adjustments are needed.Encourages Logic Compartmentalization.Customizable: Numerous settings available for tailoring logging behavior to specific needs.Environment Variables: Overriding default settings made easy with environment variables.Log Exceptions: Option to log exceptions before they are raised.UsageInstallationTo integrate@logf()into your projects:pipinstalllogfuncImportingSimply import the decorator to start using it:fromlogfuncimportlogfBasic UsageApply the@logf()decorator to functions you intend to log:fromlogfuncimportlogf@logf()defconcatenate_strings(str1:str,str2:str)->str:returnstr1+str2This setup ensures automatic logging of function name, parameters, return values, and execution time.@logf() argslevel: Set the log level (DEBUG, INFO, WARNING, etc.).log_args&log_return: Control whether to log arguments and return values.max_str_len: Limit the length of logged strings.log_exec_time: Option to log the execution time.single_msg: Consolidate all log data into a single message.use_print: Choose toprint()log messages instead of using standard logging.log_stack_info: Passstack_info=$xto.log()but not printuse_logger: Pass a logger name or logger object to use instead of logging.lolog_exception: Log exceptions if they occur before they are raised.single_exception: Consolidate all exception log data into a single message (intended to be used withlog_exception).print_allused to be an env var, now just unset LOGF_LEVEL and set USE_PRINT=True for the same effect.Environment Variable OverridesModify the behavior of@logf()using environment variables:Env VarExample ValuesLOGF_LEVELDEBUG, INFO, WARNINGLOGF_MAX_STR_LEN10, 50, 10000000LOGF_SINGLE_MSGTrue, FalseLOGF_USE_PRINTTrue, FalseLOGF_STACK_INFOTrue, FalseLOGF_LOG_EXEC_TIMETrue, FalseLOGF_LOG_ARGSTrue, FalseLOGF_LOG_RETURNTrue, FalseLOGF_LOG_EXCEPTIONTrue, FalseLOGF_USE_LOGGER'logger_name'LOGF_SINGLE_EXCEPTIONTrue, FalseLOGF_LOG_LEVELDEBUG, INFO, WARNINGSee the following output for an example of how an env var will affect@logf()behaviour:WithoutLOGF_USE_PRINT:mym2@Carys-MacBook-Pro liberfy-cli % ./cli user me
Namespace(cmd='user', act='me')
email='a@a.a' id='a4c3f7ac-4649-4e74-ad07-1cd8e9626bbc'WithLOGF_USE_PRINT=True: (jwt here isnt sensitive so no worries)mym2@Carys-MacBook-Pro liberfy-cli % LOGF_USE_PRINT=True ./cli user me
async_main | () {}
setup_argparse | () {}
setup_argparse() 0.00144s | ArgumentParser(prog='main.py', usage=None, description='CLI for user, project, sync directory, and directory file management.', formatter_class=<class 'argparse.HelpFormatter'>, conflict_handler='error', add_help=True)
apicmd | (ArgumentParser(prog='main.py', usage=None, description='CLI for user, project, sync directory, and directory file management.', formatter_class=<class 'argparse.HelpFormatter'>, conflict_handler='error', add_help=True),) {}
Namespace(cmd='user', act='me')
me | () {}
get | ('/u/me',) {}
_method | ('get', '/u/me') {}
_inject_auth | ({},) {}
load_token | () {}
load_token() 0.00004s | eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2OTQ1NTQ1MjAsInN1YiI6ImFAYS5hIiwiaWF0IjoxNjk0NTQ3MzIwfQ.p6NPOEAedaV6SzBkv3XYWTGmZ4sdAEshk76wacV6Jlw
_inject_auth() 0.00005s | {'headers': {'Authorization': 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2OTQ1NTQ1MjAsInN1YiI6ImFAYS5hIiwiaWF0IjoxNjk0NTQ3MzIwfQ.p6NPOEAedaV6SzBkv3XYWTGmZ4sdAEshk76wacV6Jlw'}}
resp_exceptions | (<Response [200 OK]>,) {}
resp_exceptions() 0.00002s | None
_method() 0.01756s | {'email': 'a@a.a', 'id': 'a4c3f7ac-4649-4e74-ad07-1cd8e9626bbc'}
get() 0.01757s | {'email': 'a@a.a', 'id': 'a4c3f7ac-4649-4e74-ad07-1cd8e9626bbc'}
me() 0.01760s | email='a@a.a' id='a4c3f7ac-4649-4e74-ad07-1cd8e9626bbc'
apicmd() 0.01773s | email='a@a.a' id='a4c3f7ac-4649-4e74-ad07-1cd8e9626bbc'
email='a@a.a' id='a4c3f7ac-4649-4e74-ad07-1cd8e9626bbc'
async_main() 0.01922s | email='a@a.a' id='a4c3f7ac-4649-4e74-ad07-1cd8e9626bbc'Real-world ExamplesHere are a couple of real-world examples of@logf()usage:fromlogfuncimportlogf# Database operations@logf(level='ERROR')defdb_insert(item):# Insert item into databasepass# Asynchronous tasks in an application@logf()asyncdeffetch_data(url):# Fetch data from URL asynchronouslyreturndataTestingActivate/create your venv withpython3 -m venv venvandsource venv/bin/activateif you haven't already.Runpip install -r requirements_dev.txtto install the testing dependencies.Runpytest tests.pyto run the tests.Output should look like this:----------coverage:platformdarwin,python3.11.5-final-0----------
NameStmtsMissCoverMissing
---------------------------------------------------
logfunc/__init__.py10100%
logfunc/config.py220100%
logfunc/defaults.py10100%
logfunc/main.py1070100%
logfunc/utils.py280100%
tests.py2820100%
---------------------------------------------------
TOTAL4410100%You can also just run thetests.pyfile directly.ContributingContributions are welcome! Please feel free to submit a pull request or open an issue.LicenseMITContactccarterdev@gmail.com