{"id":13594546,"url":"https://github.com/gaogaotiantian/objprint","last_synced_at":"2025-05-14T07:09:04.328Z","repository":{"id":38235224,"uuid":"342402680","full_name":"gaogaotiantian/objprint","owner":"gaogaotiantian","description":"A library that can print Python objects in human readable format","archived":false,"fork":false,"pushed_at":"2025-04-02T17:54:07.000Z","size":105,"stargazers_count":646,"open_issues_count":6,"forks_count":45,"subscribers_count":6,"default_branch":"master","last_synced_at":"2025-05-12T19:49:34.345Z","etag":null,"topics":["debug","print","python","python3"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/gaogaotiantian.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null},"funding":{"github":"gaogaotiantian"}},"created_at":"2021-02-25T23:02:55.000Z","updated_at":"2025-05-12T10:33:10.000Z","dependencies_parsed_at":"2025-04-11T01:36:41.789Z","dependency_job_id":"dce9d83b-4bbf-449a-9902-447b60c84457","html_url":"https://github.com/gaogaotiantian/objprint","commit_stats":{"total_commits":67,"total_committers":10,"mean_commits":6.7,"dds":"0.16417910447761197","last_synced_commit":"7b27b205d68409818a65e80141e19226095fcef2"},"previous_names":[],"tags_count":14,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gaogaotiantian%2Fobjprint","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gaogaotiantian%2Fobjprint/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gaogaotiantian%2Fobjprint/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gaogaotiantian%2Fobjprint/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/gaogaotiantian","download_url":"https://codeload.github.com/gaogaotiantian/objprint/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254092776,"owners_count":22013290,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["debug","print","python","python3"],"created_at":"2024-08-01T16:01:35.443Z","updated_at":"2025-05-14T07:08:59.314Z","avatar_url":"https://github.com/gaogaotiantian.png","language":"Python","funding_links":["https://github.com/sponsors/gaogaotiantian"],"categories":["Python"],"sub_categories":[],"readme":"# objprint\n\n[![build](https://github.com/gaogaotiantian/objprint/workflows/build/badge.svg)](https://github.com/gaogaotiantian/objprint/actions?query=workflow%3Abuild)  [![coverage](https://img.shields.io/codecov/c/github/gaogaotiantian/objprint)](https://codecov.io/gh/gaogaotiantian/objprint)  [![pypi](https://img.shields.io/pypi/v/objprint.svg)](https://pypi.org/project/objprint/)  [![support-version](https://img.shields.io/pypi/pyversions/objprint)](https://img.shields.io/pypi/pyversions/objprint)  [![license](https://img.shields.io/github/license/gaogaotiantian/objprint)](https://github.com/gaogaotiantian/objprint/blob/master/LICENSE)  [![commit](https://img.shields.io/github/last-commit/gaogaotiantian/objprint)](https://github.com/gaogaotiantian/objprint/commits/master)\n\nA library that can print Python objects in human readable format\n\n## Install\n```\npip install objprint\n```\n\n## Usage\n\n### op\n\nUse ```op()``` (or ```objprint()```) to print objects.\n\n```python\nfrom objprint import op\n\nclass Position:\n    def __init__(self, x, y):\n        self.x = x\n        self.y = y\n\nclass Player:\n    def __init__(self):\n        self.name = \"Alice\"\n        self.age = 18\n        self.items = [\"axe\", \"armor\"]\n        self.coins = {\"gold\": 1, \"silver\": 33, \"bronze\": 57}\n        self.position = Position(3, 5)\n\nop(Player())\n```\n\n```\n\u003cPlayer 0x7fe44e1e3070\n  .age = 18,\n  .coins = {'bronze': 57, 'gold': 1, 'silver': 33},\n  .items = ['axe', 'armor'],\n  .name = 'Alice',\n  .position = \u003cPosition\n    .x = 3,\n    .y = 5\n  \u003e\n\u003e\n```\n\nYou can print multiple objects just like print, except ``op`` will print them in separate lines\n\n```python\nop([1, 2], {'a': 1})\n```\n\n```\n[1, 2]\n{'a': 1}\n```\n\n``op`` will return the same object it prints, so you can do something like this\n\n```python\na = MyObject()\n# print the args inline with minumum change\nfunction_using_object(op(a))\n# the difference is more significant with complex expressions\n# original: function_using_object(a.f() + a.g())\nfunction_using_object(op(a.f() + a.g()))\n```\n\nIt works on multiple objects as well, as it returns a tuple, you need to unpack it for functions\n\n```python\na = MyObject()\nfunction_using_object(*op(a.f(), a.g()))\n```\n\n### add_objprint\n\nIf you want to use ```print()``` to print your object, you can also use the class decorator\n```add_objprint``` to add ```__str__``` method for your class.\n\n```python\nfrom objprint import add_objprint\n\nclass Position:\n    def __init__(self, x, y):\n        self.x = x\n        self.y = y\n\n@add_objprint\nclass Player:\n    def __init__(self):\n        self.name = \"Alice\"\n        self.age = 18\n        self.items = [\"axe\", \"armor\"]\n        self.coins = {\"gold\": 1, \"silver\": 33, \"bronze\": 57}\n        self.position = Position(3, 5)\n\n# This will print the same thing as above\nprint(Player())\n```\n\n### objstr\n\nIf you want the ``str`` representation of the object, instead of printing it on the screen,\nyou can use ``objstr`` function\n\n```python\nfrom objprint import objstr\n\ns = objstr(my_object)\n```\n\n### print more\n\nThere are some optional information you can print with [config](#config).\n\n#### \"Public\" Methods\n\nThere are no REAL public methods in python, here I simply meant you can print methods that do not start with ``__`` as there will be\na lot of default magic methods and you don't want that.\n\n```python\nclass Player:\n    def attack(self, opponent):\n        pass\n\nop(Player(), print_methods=True)\n```\n\n```\n\u003cPlayer 0x7fe44e1e3070\n  def attack(opponent)\n\u003e\n```\n\nAs you can see, it will also print the method signature(without ``self`` argument).\n\n#### Line numbers\n\nYou can print execution info, including the function it's in, the file and the line number of the printing line.\nThis is helpful for you to locate where this object is printed.\n\n```python\ndef f():\n    op(Player(), line_number=True)\nf()\n```\n\n```\nf (my_script.py:29)\n\u003cPlayer 0x7f30e8cb1ac0\n  ...\n\u003e\n```\n\n### Argument names\n\nYou can print the expression of the argument with `arg_name`\n\n```python\nop(Player(), arg_name=True)\n```\n\n```\nPlayer():\n\u003cPlayer 0x7f495850a8d0\n  ...\n\u003e\n```\n\n### objjson\n\n``objprint`` supports print objects to json to make it easier to serialize an object.\n\n``objjson`` returns a jsonifiable object that can be dumped with ``json.dumps``\n\n```python\nfrom objprint import objjson\n\njson_obj = objjson(Player())\n\nprint(json.dumps(json_obj, indent=2))\n```\n\n```\n{\n  \".type\": \"Player\",\n  \"name\": \"Alice\",\n  \"age\": 18,\n  \"items\": [\n    \"axe\",\n    \"armor\"\n  ],\n  \"coins\": {\n    \"gold\": 1,\n    \"silver\": 33,\n    \"bronze\": 57\n  },\n  \"position\": {\n    \".type\": \"Position\",\n    \"x\": 3,\n    \"y\": 5\n  }\n}\n```\n\nYou can use ``op`` to print in json format directly with ``format=\"json\"``. You can pass in argument for ```json.dumps```\n\n```python\nop(Player(), format=\"json\", indent=2)\n```\n\n``add_objprint`` also works with ``format=\"json``\"\n\n```python\n@add_objprint(format=\"json\", indent=2)\nclass Player:\n    pass\n```\n\n### Enable/Disable the print\n\nYou can disable prints from all the ``op()`` calls globally with ``enable`` config.\n\n```python\nfrom objprint import op\n\nop.disable()\nop([1, 2, 3])  # This won't print anything\nop.enable()  # This could fix it!\n```\n\nOr you can use it for ``op()`` functions individually with some conditions\n\n```python\nop(obj, enable=check_do_print())\n```\n\n### attribute selection\n\nYou can customize which attribute to print with name filters.\n\n``objprint`` will try to match the attribute name with ``attr_pattern`` regex. The default\n``attr_pattern`` is ``r\"(!_).*\"``, which means anything that does NOT start with an `_`.\n\nYou can customize ``attr_pattern`` to select the attributes you want to print:\n\n```python\n# This will print all the attributes that do not start with __\nop(Player(), attr_pattern=r\"(!__).*\")\n```\n\nYou can also use ``include`` and ``exclude`` to specify attributes to print with regular expression\nso ```objprint``` will only print out the attributes you are interested in.\n\n```python\nop(Player(), include=[\"name\"])\n```\n```\n\u003cPlayer\n  .name = 'Alice'\n\u003e\n```\n\n```python\nop(Player(), exclude=[\".*s\"])\n```\n\n```\n\u003cPlayer 0x7fe44e1e3070\n  .name = 'Alice',\n  .age = 18,\n  .position = \u003cPosition\n    .x = 3,\n    .y = 5\n  \u003e\n\u003e\n```\n\nIf you specify both ``include`` and ``exclude``, it will do a inclusive check first, then filter out the attributes\nthat match exclusive check.\n\n```attr_pattern```, ```include``` and ```exclude``` arguments work on ```objprint```, ```objstr``` and ```@add_objprint```.\n\n### Register Custom Type Formatter\n\nYou can also customize how certain types of objects are displayed by registering a custom formatter function to transform an object of a specific type into a string. \n\nFor example, you can print all integers in hexadecimal format by registering the ```hex()``` function for the ```int``` data type, or registering a custom ```lambda``` function. \n\n```python\nfrom objprint import op\n\nop.register_formatter(int, hex)\nop.register_formatter(float, lambda x: f\"{round(x, 3)}\")\nop(10)  # prints 0xa\nop(3.14159)  # prints 3.142\n```\n\nAlternatively, you can also register a custom formatter function using a decorator:\n\n```python\n@op.register_formatter(str)\ndef custom_formatter(obj: str):\n    return f\"custom_print: {obj}\"\n\nop(\"hi\")  # prints custom_print: hi\n```\n\nDuring registration, ```objprint``` will examine the specified object type, and raise a ```TypeError``` if an invalid object type is provided.\n\nWhen you finish using the custom formatters, you can unregister them with ```unregister_formatter()```.\n\n```python\nop.unregister_formatter(int, float, str)\nop(10)  # prints 10\nop(3.14159)  # prints 3.14159\nop(\"hi\")  # prints hi\n```\n\nOr you can unregister everything by passing no argument to it.\n\n```python\nop.unregister_formatter()\n```\n\nThe ```register_formatter()``` function also accepts an ```inherit``` argument (default ```True```) to dictate if the registered formatter should also apply to any derived classes of the object type.\n\n```python\nclass BaseClass:\n    name = 'A'\n\nclass DerivedClass(BaseClass):\n    name = 'B'\n```\n\nWith ```inherit=True```, derived class will share the same formatter registered under base class. \n\n```python\ndef base_formatter(obj: BaseClass) -\u003e str:\n    return f'Print {obj.name} with Base Class Formatter'\n\nop.register_formatter(BaseClass, base_formatter, inherit=True)\n\nop(DerivedClass())\n```\n\n```\nPrint B with Base Class Formatter\n```\n\nWith ```inherit=False```, derived class will use the default formatter provided by ```objprint```. \n\n```python\n@op.register_formatter(BaseClass, inherit=False)\ndef base_formatter(obj: BaseClass) -\u003e str:\n    return f'Print {obj.name} with Base Class Formatter'\n\nop(DerivedClass())\n```\n\n```\n\u003cDerivedClass 0x7fb42e8216a0\n  .name = 'B'\n\u003e\n```\n\nIf a derived class inherits from multiple base classes, each with a registered formatter, the chosen formatter adheres to the Method Resolution Order (MRO) of the derived class.\n\nTo check all the registered functions and their inheritance status, you can use the ```get_formatter()``` method. It returns a dictionary-like object that you can print for easy inspection.\n\n```python\nfmts = op.get_formatter()\nprint(fmts)\n```\n\n```\n{\u003cclass '__main__.BaseClass'\u003e: FormatterInfo(formatter=\u003cfunction base_formatter at 0x7feaf33d1f70\u003e, inherit=False)}\n```\n\nPlease note that registering a formatter function with ```op``` will affect the output of ```objprint``` and ```objstr``` methods in the same way.\n\n### config\n\n```objprint``` formats the output based on some configs\n\n* ``config_name(default_value)`` - this config's explanation\n* ``enable(True)`` - whether to print, it's like a switch\n* ``depth(100)`` - how deep ```objprint``` goes into nested data structures\n* ``indent(2)`` - the indentation\n* ``width(80)`` - the maximum width a data structure will be presented as a single line\n* ``elements(-1)`` - the maximum number of elements that will be displayed, ``-1`` means no restriction\n* ``color(True)`` - whether to use colored scheme\n* ``line_number(False)`` - whether to print the ``function (filename:line_number)`` before printing the object\n* ``arg_name(False)`` - whether to print the argument expression before the argument value\n* ``skip_recursion(True)`` - whether skip printing recursive data, which would cause infinite recursion without ``depth`` constraint\n* ``honor_existing(True)`` - whether to use the existing user defined ``__repr__`` or ``__str__`` method\n* ``attr_pattern(r\"(!_).*\")`` - the regex pattern for attribute selection\n* ``include([])`` - the list of attribute regex to do an inclusive filter\n* ``exclude([])`` - the list of attribute regex to do an exclusive filter\n\nYou can set the configs globally using ``config`` function\n\n```python\nfrom objprint import config\nconfig(indent=4)\n```\n\nOr if you don't want to mess up your name space\n\n```python\nfrom objprint import op\nop.config(indent=4)\n```\n\nOr you can do a one time config by passing the arguments into ``objprint`` function\n\n```python\nfrom objprint import op\n\nop(var, indent=4)\n```\n\n### install\n\nMaybe you don't want to import ``op`` in every single file that you want to use. You can\nuse ``install`` to make it globally accessible\n\n```python\nfrom objprint import op, install\n\n# Now you can use op() in any file\ninstall()\n\n# This is the same\nop.install()\n\n# You can specify a name for objprint()\ninstall(\"my_print\")\nmy_print(my_object)\n```\n\n## Bugs/Requests\n\nPlease send bug reports and feature requests through [github issue tracker](https://github.com/gaogaotiantian/objprint/issues).\n\n## License\n\nCopyright 2020-2023 Tian Gao.\n\nDistributed under the terms of the  [Apache 2.0 license](https://github.com/gaogaotiantian/objprint/blob/master/LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgaogaotiantian%2Fobjprint","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgaogaotiantian%2Fobjprint","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgaogaotiantian%2Fobjprint/lists"}