{ "info": { "author": "Michal Hordecki", "author_email": "mhordecki@gmail.com", "bugtrack_url": null, "classifiers": [ "License :: OSI Approved :: BSD License", "Programming Language :: Python :: 2.6", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3", "Topic :: Software Development :: Libraries" ], "description": "LogPy\n=====\nUnorthodox logging for Python\n-----------------------------\n\n:Author: Michal Hordecki\n:URL: http://github.com/MHordecki/LogPy\n\nIntroduction\n============\n\nLogPy is an alternative for standard Python logging facilities, loosely\nbased on Lisp's log5. LogPy is based on KISS principles - therefore I wanted\nit to be as most transparent as possible. \n\nThe main difference when compared to stdlib's logging is tag-based architecture.\nIn logging, each log has assigned a certain level (be it debug, error, etc.).\nThat's all. LogPy, on the other hand, sports tags - you can attach short strings\nto each message. Tag can represent variety of things: severity level, module\nname, or some custom log categorization.\n\nLogPy requires Python 2.6 or higher. It works seamlessly on Python 3 too\n(in fact, it's developed with py3k in mind and then backported to Python 2.6).\n\nGetting started \n===============\n\nUsing LogPy is dead simple::\n\n from logpy import LogPy\n import sys\n\n log = LogPy()\n log.add_output(sys.stderr.write)\n\n log('debug')('Hello World!')\n\nVoila! LogPy instances are callable. To output a log, call log \"twice\" - in\nfirst call pass all tags of the log, and everything passed to the second one\nwill be considered a part of the message. The example will output logs to the\nstandard error output. Easy, isn't it?\n\nUnder the hood\n--------------\n\nLogPy has a few layers of abstraction:\n\n 1. LogPy - it accepts data from the user, combines them into a Message\n instance and passes them down to all outputs.\n 2. Output - it filters messages based on some predefined conditions, and\n if the message passes them all, it's formatted by the Formatter and\n then passed to the actual output.\n 3. Formatter - takes message and formats it ;) (in standard implementation\n it uses string.format for the job).\n 4. Actual output - a callable that, for example, outputs the Formatter's\n output to the screen.\n\nAll those layers/objects are callables.\n\nCommon tasks\n============\n\nOutput filtering\n----------------\n\nWith multiple outputs, you probably want to filter out some logs in each of them. There is support for that::\n\n log = LogPy()\n\n log.add_output(my_output, filter = lambda m: 'error' in m.tags)\n \n # Equivalent to:\n\n log.add_output(my_output, filter = [lambda m: 'error' in m.tags])\n\nAs you can see, filters are callables, taking ``Message`` object as an argument\nand returning ``bool``. Multiple filters can be provided by a list.\n\nCustom formatting\n-----------------\n\nYou can customize formatting by either replacing the format string or by replacing the Formatting object altogether. Your choice.\n\nCustom format string\n~~~~~~~~~~~~~~~~~~~~\n\nThis one will meet 90% of your needs. You can change your format string with keyword argument to the add_output method of LogPy (also possible when directly instantiating Output objects)::\n\n log.add_output(..., formatter = 'my custom format string!')\n\nWhen processing a message, method ``format`` of the string will be called with\nfollowing, predefined arguments:\n\n + date - datetime object\n + tags - space-delimited list of tags (string)\n + args - list of arguments in the message\n + kwargs - dict of keyword arguments in the message\n + message - the actual message object. All arguments above are actually\n just a syntactic sugar, as they are all attributes of this object.\n\nDefault format string looks like this: ``{date} : {tags} : {args} {kwargs}\\n``\n\nDon't forget to put a newline at the ending, or your logs will look crippled.\n\nWorking with multiple modules\n-----------------------------\n\nYou can help yourself while using LogPy with multiple modules by predefining\nsome of the tags::\n\n # Main module\n\n log = LogPy()\n\n # Child module\n \n import mainmodule\n \n log = mainmodule.log('module:childmodule', curry = True)\n \n # Now:\n\n log('debug')('Hello World!')\n\n # is equivalent to\n\n log('module:childmodule', 'debug')('Hello World')\n\nCustom format object\n~~~~~~~~~~~~~~~~~~~~\n\nIn case you want the full power - you can get rid of the default formatter::\n\n log.add_output(..., formatter = my_formatter_object)\n\nFormatter objects must comply to the simple protocol::\n\n class Formatter:\n def __call__(message: Message) -> Someting reasonable:\n pass\n\n class Message:\n tags = set(str)\n args = [] # passed by the user\n kwargs = {} # passed by the user\n date = datetime.datetime\n\n(I have no idea whatsoever if there's standard formal notation for describing\nprotocols in Python besides things like zope.interface. I hope my ramblings\nare clear.)\n\nWhere something reasonable means: everything that will be accepted by\nthe output of the Output (sounds kinda silly) - it usually means\n``str``, but not always.\n\nCustom Output object \n--------------------\n\nIf you're willing to scrap 50% of the LOC of LogPy, feel free to do so::\n\n log.add_raw_output(my_customized_output_object)\n\nWorth mentioning is the fact that ``LogPy.add_output`` is just a wrapper for::\n\n log.add_output(...)\n # Equivalent to\n log.add_raw_output(Output(...))\n\nOutput protocol looks as follows::\n\n class Output:\n def __call__(message: Message):\n pass\n\nIn other words: you will be called with every log issued by the user.\n\nNote: Please, treat messages as immutable objects - they are being reused\nfor all Outputs.\n\nThread safety\n-------------\n\nLogPy employs some basic thread safety; a threading.Lock is used in __call__ method of LogPy. It can be easily replaced::\n\n from threading import RLock\n\n log = LogPy()\n log.lock = RLock()", "description_content_type": null, "docs_url": null, "download_url": "UNKNOWN", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "http://github.com/MHordecki/LogPy", "keywords": null, "license": "UNKNOWN", "maintainer": null, "maintainer_email": null, "name": "LogPy", "package_url": "https://pypi.org/project/LogPy/", "platform": "UNKNOWN", "project_url": "https://pypi.org/project/LogPy/", "project_urls": { "Download": "UNKNOWN", "Homepage": "http://github.com/MHordecki/LogPy" }, "release_url": "https://pypi.org/project/LogPy/1.0.1/", "requires_dist": null, "requires_python": null, "summary": "Unorthodox logging for python", "version": "1.0.1" }, "last_serial": 784638, "releases": { "1.0": [ { "comment_text": "", "digests": { "md5": "a2fb5d480a78ef72ac683d3ceada1e6e", "sha256": "325bc60d76e9a3661b8524e2dde4420410709a382baea7c10acfa649970e45cd" }, "downloads": -1, "filename": "LogPy-1.0.tar.gz", "has_sig": false, "md5_digest": "a2fb5d480a78ef72ac683d3ceada1e6e", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 4311, "upload_time": "2010-02-06T22:23:16", "url": "https://files.pythonhosted.org/packages/b7/58/53ce8f101c036dd848f86fe6ebedcd849aa4802e1cfc5f613a31f7e93852/LogPy-1.0.tar.gz" } ], "1.0.1": [] }, "urls": [] }