Package: python-utils
Python Utils is a collection of small Python functions and
classes which make common patterns shorter and easier. It is by no means a
complete collection but it has served me quite a bit in the past and I will
keep extending it.One of the libraries using Python Utils is Django Utils.Documentation is available at:https://python-utils.readthedocs.org/en/latest/LinksThe source:https://github.com/WoLpH/python-utilsProject page:https://pypi.python.org/pypi/python-utilsReporting bugs:https://github.com/WoLpH/python-utils/issuesDocumentation:https://python-utils.readthedocs.io/en/latest/My blog:https://wol.ph/Security contact informationTo report a security vulnerability, please use theTidelift security contact.
Tidelift will coordinate the fix and disclosure.Requirements for installing:For the Python 3+ release (i.e. v3.0.0 or higher) there are no requirements.
For the Python 2 compatible version (v2.x.x) thesixpackage is needed.Installation:The package can be installed throughpip(this is the recommended method):pipinstallpython-utilsOr ifpipis not available,easy_installshould work as well:easy_installpython-utilsOr download the latest release from Pypi (https://pypi.python.org/pypi/python-utils) or Github.Note that the releases on Pypi are signed with my GPG key (https://pgp.mit.edu/pks/lookup?op=vindex&search=0xE81444E9CE1F695D) and can be checked using GPG:gpg--verifypython-utils-<version>.tar.gz.ascpython-utils-<version>.tar.gzQuickstartThis module makes it easy to execute common tasks in Python scripts such as
converting text to numbers and making sure a string is in unicode or bytes
format.ExamplesAutomatically converting a generator to a list, dict or other collections
using a decorator:>>>@decorators.listify()...defgenerate_list():...yield1...yield2...yield3...>>>generate_list()[1, 2, 3]>>>@listify(collection=dict)...defdict_generator():...yield'a',1...yield'b',2>>>dict_generator(){'a': 1, 'b': 2}Retrying until timeoutTo easily retry a block of code with a configurable timeout, you can use thetime.timeout_generator:>>>foriintime.timeout_generator(10):...try:...# Run your code here...exceptExceptionase:...# Handle the exceptionFormatting of timestamps, dates and timesEasy formatting of timestamps and calculating the time since:>>>time.format_time('1')'0:00:01'>>>time.format_time(1.234)'0:00:01'>>>time.format_time(1)'0:00:01'>>>time.format_time(datetime.datetime(2000,1,2,3,4,5,6))'2000-01-02 03:04:05'>>>time.format_time(datetime.date(2000,1,2))'2000-01-02'>>>time.format_time(datetime.timedelta(seconds=3661))'1:01:01'>>>time.format_time(None)'--:--:--'>>>formatters.timesince(now)'just now'>>>formatters.timesince(now-datetime.timedelta(seconds=1))'1 second ago'>>>formatters.timesince(now-datetime.timedelta(seconds=2))'2 seconds ago'>>>formatters.timesince(now-datetime.timedelta(seconds=60))'1 minute ago'Converting your test from camel-case to underscores:>>>camel_to_underscore('SpamEggsAndBacon')'spam_eggs_and_bacon'Attribute setting decorator. Very useful for the Django adminA convenient decorator to set function attributes using a decorator:You can use:>>>@decorators.set_attributes(short_description='Name')...defupper_case_name(self,obj):...return("%s%s"%(obj.first_name,obj.last_name)).upper()Instead of:>>>defupper_case_name(obj):...return("%s%s"%(obj.first_name,obj.last_name)).upper()>>>upper_case_name.short_description='Name'This can be very useful for the Django admin as it allows you to have all
metadata in one place.Scaling numbers between ranges>>>converters.remap(500,old_min=0,old_max=1000,new_min=0,new_max=100)50

# Or with decimals:>>>remap(decimal.Decimal('250.0'),0.0,1000.0,0.0,100.0)Decimal('25.0')Get the screen/window/terminal size in characters:>>>terminal.get_terminal_size()(80, 24)That method supports IPython and Jupyter as well as regular shells, usingblessingsand other modules depending on what is available.Extracting numbers from nearly every string:>>>converters.to_int('spam15eggs')15>>>converters.to_int('spam')0>>>number=converters.to_int('spam',default=1)1Doing a global import of all the modules in a package programmatically:To do a global import programmatically you can use theimport_globalfunction. This effectively emulates afrom … import *frompython_utils.import_importimport_global# The following is  the equivalent of `from some_module import *`import_global('some_module')Automatically named logger for classes:Or add a correclty named logger to your classes which can be easily accessed:classMyClass(Logged):def__init__(self):Logged.__init__(self)my_class=MyClass()# Accessing the logging method:my_class.error('error')# With formatting:my_class.error('The logger supports%(formatting)s',formatting='named parameters')# Or to access the actual log function (overwriting the log formatting can# be done n the log method)importloggingmy_class.log(logging.ERROR,'log')Alternatively loguru is also supported. It is largely a drop-in replacement for the logging module which is a bit more convenient to configure:First install the extra loguru package:pipinstall'python-utils[loguru]'classMyClass(Logurud):...Now you can use theLogurudclass to make functions such asself.info()available. The benefit of this approach is that you can add extra context or
options to you specific loguru instance (i.e.self.logger):Convenient type aliases and some commonly used types:# For type hinting scopes such as locals/globals/varsScope=Dict[str,Any]OptionalScope=O[Scope]# Note that Number is only useful for extra clarity since float# will work for both int and float in practice.Number=U[int,float]DecimalNumber=U[Number,decimal.Decimal]# To accept an exception or list of exceptionsExceptionType=Type[Exception]ExceptionsType=U[Tuple[ExceptionType,...],ExceptionType]# Matching string/bytes types:StringTypes=U[str,bytes]