Metadata-Version: 2.1
Name: debugprint
Version: 0.1.10
Summary: A clone of the npm debug module with ability to implement custom formatting
Home-page: https://github.com/phil-arh/debugprint
Author: Phil Howe
Author-email: philhbusiness@gmail.com
License: Apache 2.0
Description: # debugprint
        
        *A light zero-dependency module for nicely printing things for debugging*
        
        `debugprint` is a slightly more featureful Python clone of the node.js `debug` module. It behaves almost exactly as node.js debug does, with the following exceptions:
        
         - Python imports behave differently from node.js `require` so `debug` instances are created differently
         - You can define custom format functions in debugprint
         - You can add captions to print-outs in debugprint
         - In node.js debug, you can change the enabled namespace within a module by doing `debug.disable()` or `debug.enable('some:namespaces:*')`
        
        Otherwise, the usage is pretty much exactly the same - make a new `Debug` instance for each module, and run the program with the `DEBUG` environment variable set to something sensible (details on setting `DEBUG` are below).
        
        Why use `debugprint` instead of just regular `print`?
        
         - Prints only when the `DEBUG` environment variable is set to a matching value (more on this below) so you don't need to spend time finding and removing print statements prior to releasing for production
         - Prints to `stderr` not `stdout` - much better for command line tools as it doesn't interfere with piping the data on to other programs
         - Provides the name of the module the statement is being output from - module name is also colour-coded
         - Allows passing an optional caption
         - Automatically pretty-prints built-in collection types
         - Allows adding custom format functions to pretty-print custom data types like `lxml` trees or `pyrsistent` immutable data structures.
        
        ## Example print-outs
        
        ### Scalar values
        
        `debug("Hello, world!")` and `debug("Hello, world!", "a caption")`:
        
        ![Basic](https://github.com/phil-arh/debugprint/blob/master/screenshots/basic.png)
        
        ### Dicts
        
        `debug(example_dict)`
        
        ![Dict no caption](https://github.com/phil-arh/debugprint/blob/master/screenshots/dict_no_caption.png)
        
        `debug(example_dict, "A pretty-printed nested dict")`
        
        ![Dict with caption](https://github.com/phil-arh/debugprint/blob/master/screenshots/dict_caption.png)
        
        ### XML
        
        `debug(example_xml)`
        
        ![XML](https://github.com/phil-arh/debugprint/blob/master/screenshots/xml.png)
        
        **`debugprint` can also pretty-print nested lists, tuples, and mixed JSON by default - essentially anything that can be handled by the standard library `pprint` module.**
        
        ## Installation
        
        ```bash
        # via pip
        pip install debugprint
        
        # via pipenv
        pipenv install debugprint
        
        ```
        
        ## Usage
        
        Import into every module where you want to do debug printing, then create an instance of the `Debug` class for that module.
        
        ```python
        from debugprint import Debug
        
        # module names can contain: letters, numbers, underscores, hyphens, and colons
        # the actual regex is this: /^[A-Za-z0-9:_\-]+$/
        debug = Debug("my_application:some_subpackage:this_module")
        
        # simple printing
        debug("some string value")
        debug(123)
        debug(False)
        
        # pretty printing collections
        debug([1, 2, 3])
        debug({"a": 1, "b": 2, "c": 3})
        
        # printing things with captions
        debug(call_this_function_that_returns_a_bool(), "bool returned by this function")
        debug(some_var, "the value of some_var at this point in the pipeline")
        
        ```
        
        ## Setting the `DEBUG` environment variable
        
        By default, `debugprint` doesn't print anything. This is intentional - debug printouts are unnecessary in production and can be actively irritating to users - not to mention, depending on the situation, a potential security risk.
        
        In order to get `debugprint` to print, you need to run your module/script/application with the `DEBUG` environment variable set.
        
        There are two ways to do this in bash:
        
        ```bash
        # setting the DEBUG environment variable to "*" as an example
        
        $ DEBUG="*" python3 myscript.py
        
        # or
        
        $ export DEBUG="*"
        $ python3 myscript.py
        ```
        
        Setting `DEBUG` to `*` tells `debugprint` to always print. Occasionally that's the behaviour you want, but more likely you'll want to restrict it to a limited subset of possible `debug()` calls. You can therefore set it to colon-separated paths, like the following examples:
        
         - `app` - `debug()` calls will only print in this scenario: `debug = Debug("app")`
         - `app:thing` will only print for `debug = Debug(app:thing)`
         - `app:*` - will print if `debug = Debug("app")` or `debug = Debug(app:thing)` or `debug = Debug(app:thing:anotherthing)` etc.
         - `app:*:anotherthing` will print if `debug = Debug("app:thing:anotherthing")` or `debug = Debug("app:somethingelse:anotherthing")` etc.
        
        You can also set `DEBUG` so multiple different paths are enabled. For instance:
        
         - `app,app:thing` - `debug()` calls will print where `debug = Debug("app")` or `debug = Debug("app:thing")`
         - `app:thing,app:anotherthing` - will print where `debug = Debug("app:thing")` or `debug = Debug("app:anotherthing")`
        
        This should hopefully be fairly intuitive. Just set the path of the `DEBUG` environment variable to match what you want to print. You'll usually be fine with setting it to `DEBUG=nameofmyapp,nameofmyapp:*` and leaving it, but if you're working on a big codebase or trying to figure out a particularly persistent bug, you may want to adjust it to narrow down what gets printed.
        
        ## Custom format functions
        
        By default, `debugprint` will attempt to pretty-print `list`s, `dict`s, `set`s, `tuple`s, and `xml.etree.ElementTree.ElementTree`s. But what if you're using non-standard data structures, like `lxml` trees or `pyrsistent` immutable data structures?
        
        You can define custom format functions for any data type you like. The general structure of a custom format function is that it returns either a string to be printed or `None`. `debugprint` will call each defined custom format function in turn. The logic in `debugprint` is similar to this:
        
        ```python
        # not the actual code but not far off
        input_value # value to print
        for function in custom_functions:
            output_string = function(input_value)
            if output_string:
                break
        if output_string:
            # print this string
        else:
            # carry on and try using the default formatters
        ```
        
        ### Example custom format functions
        
        The best way to see what a custom format function looks like is to check out a couple of examples:
        
        ```python
        from pprint import pformat
        
        from lxml import etree
        from pyrsistent import PRecord, PMap, PVector, PSet, thaw
        
        import debugprint
        
        
        # a custom format function for LXML element trees
        def lxml_formatter(possible_lxml_object):
            if isinstance(possible_lxml_object, etree._Element):
                return etree.tostring(
                    possible_lxml_object,
                    pretty_print=True,
                    encoding="unicode",
                )
            else:
                return None
        
        # a custom format function for pyrsistent immutable data structures
        def pyrsistent_formatter(possible_pyrsistent_data_structure):
            if isinstance(possible_pyrsistent_data_structure, (PRecord, PMap, PVector, PSet)):
                return pformat(thaw(possible_pyrsistent_data_structure))
            else:
                return None
        
        debugprint.use_format(lxml_formatter)
        debugprint.use_format(pyrsistent_formatter)
        ```
        
        The basic logic of a custom format function is just:
        
        ```python
        def custom_format_function(some_input):
            if isinstance(some_input, the_type_this_function_is_looking_for):
                return format_this_special_type_for_printing(some_input)
            else:
                # you can return any falsy value here
                return None
        ```
        
Keywords: debug print
Platform: UNKNOWN
Description-Content-Type: text/markdown
