lkj


Namelkj JSON
Version 0.1.45 PyPI version JSON
download
home_pagehttps://github.com/thorwhalen/lkj
SummaryA dump of homeless useful utils
upload_time2025-08-14 13:43:49
maintainerNone
docs_urlNone
authorThor Whalen
requires_pythonNone
licenseapache-2.0
keywords
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # lkj

Lightweight Kit Jumpstart. A place for useful python utils built only with pure python.

To install:	```pip install lkj```

[Documentation](https://i2mint.github.io/lkj)

Note: None of the tools here require anything else but pure python.
Additionally, things are organized in such a way that these can be 
easily copy-pasted into other projects. 
That is, modules are all self contained (so can easily be copy-paste-vendored 
(do be nice and mention the source!))
Further, many functions will contain their own imports: Those functions can even be 
copy-paste-vendored by just copying the function body.

# Examples of utils

## Find and replace

`FindReplaceTool` is a general-purpose find-and-replace tool that can treat the input text as a continuous sequence of characters, 
even if operations such as viewing context are performed line by line.

The basic usage is 

```python
FindReplaceTool("apple banana apple").find_and_print_matches(r'apple')
```
    
    Match 0 (around line 1):
    apple banana apple
    ^^^^^
    ----------------------------------------
    Match 1 (around line 1):
    apple banana apple
                 ^^^^^
    ----------------------------------------

```python
FindReplaceTool("apple banana apple").find_and_replace(r'apple', "orange")
```

    'orange banana orange'

[See more examples in documentation](https://i2mint.github.io/lkj/module_docs/lkj/strings.html#lkj.strings.FindReplaceTool)

[See here a example of how I used this to edit my CI yamls](https://github.com/i2mint/lkj/discussions/4#discussioncomment-12104547)

## loggers

### clog

Conditional log

```python
>>> clog(False, "logging this")
>>> clog(True, "logging this")
logging this
```

One common usage is when there's a verbose flag that allows the user to specify
whether they want to log or not. Instead of having to litter your code with
`if verbose:` statements you can just do this:

```python
>>> verbose = True  # say versbose is True
>>> _clog = clog(verbose)  # makes a clog with a fixed condition
>>> _clog("logging this")
logging this
```

You can also choose a different log function.
Usually you'd want to use a logger object from the logging module,
but for this example we'll just use `print` with some modification:

```python
>>> _clog = clog(verbose, log_func=lambda x: print(f"hello {x}"))
>>> _clog("logging this")
hello logging this
```

### print_with_timestamp

Prints with a timestamp and optional refresh.
- input: message, and possibly args (to be placed in the message string, sprintf-style
- output: Displays the time (HH:MM:SS), and the message
- use: To be able to track processes (and the time they take)

```python
>>> print_with_timestamp('processing element X')
(29)09:56:36 - processing element X
```

### return_error_info_on_error

Decorator that returns traceback and local variables on error.

This decorator is useful for debugging. It will catch any exceptions that occur
in the decorated function, and return an ErrorInfo object with the traceback and
local variables at the time of the error.
- `func`: The function to decorate.
- `caught_error_types`: The types of errors to catch.
- `error_info_processor`: A function that processes the ErrorInfo object.

Tip: To parametrize this decorator, you can use a functools.partial function.

Tip: You can have your error_info_processor persist the error info to a file or
database, or send it to a logging service.

```python
>>> from lkj import return_error_info_on_error, ErrorInfo
>>> @return_error_info_on_error
... def foo(x, y=2):
...     return x / y
...
>>> t = foo(1, 2)
>>> assert t == 0.5
>>> t = foo(1, y=0)
Exiting from foo with error: division by zero
>>> if isinstance(t, ErrorInfo):
...     assert isinstance(t.error, ZeroDivisionError)
...     hasattr(t, 'traceback')
...     assert t.locals['args'] == (1,)
...     assert t.locals['kwargs'] == {'y': 0}
```

## Miscellaneous

### chunker

Chunk an iterable into non-overlapping chunks of size chk_size.

```python
chunker(a, chk_size, *, include_tail=True)
```

```python
>>> from lkj import chunker
>>> list(chunker(range(8), 3))
[(0, 1, 2), (3, 4, 5), (6, 7)]
>>> list(chunker(range(8), 3, include_tail=False))
[(0, 1, 2), (3, 4, 5)]
```

### import_object

Import and return an object from a dot string path.

```python
import_object(dot_path: str)
```

```python 
>>> f = import_object('os.path.join')
>>> from os.path import join
>>> f is join
True
```

## Pretty Printing Lists

The `print_list` function provides flexible, human-friendly ways to display lists and collections. It supports multiple display styles and can be used in several ways.

### Basic Usage

```python
from lkj.strings import print_list

items = ['apple', 'banana', 'cherry', 'date', 'elderberry', 'fig']

# Different display styles
print_list(items, style='wrapped')      # Automatic line wrapping
print_list(items, style='columns')      # Column format
print_list(items, style='numbered')     # Numbered list
print_list(items, style='bullet')       # Bullet points
print_list(items, style='compact')      # All on one line
print_list(items, style='table')        # Table format
```

### Direct Usage with Customization

```python
# Customize width, separators, and formatting
print_list(items, style='wrapped', max_width=40, sep=' | ')
print_list(items, style='columns', items_per_line=3)
print_list(items, style='numbered', line_prefix='  ')
print_list(items, style='bullet', show_count=False)

# Return string instead of printing
result = print_list(items, style='numbered', print_func=None)
print(result)
```

### Partial Function Factory

When you don't specify the `items` parameter, `print_list` returns a partial function that you can reuse:

```python
# Create specialized printers
numbered_printer = print_list(style='numbered', show_count=False)
bullet_printer = print_list(style='bullet', print_func=None)
compact_printer = print_list(style='compact', max_width=60)

# Reuse with different data
numbered_printer(['a', 'b', 'c'])        # Prints: 1. a\n2. b\n3. c
result = bullet_printer(['x', 'y', 'z']) # Returns: '• x\n• y\n• z'
compact_printer(['item1', 'item2'])      # Prints: item1, item2
```

### Convenience Methods

The `print_list` object provides convenient pre-configured methods:

```python
# Quick access to common styles
print_list.compact(items)    # Compact format, no count
print_list.wrapped(items)    # Wrapped format, no count  
print_list.columns(items)    # Column format, no count
print_list.numbered(items)   # Numbered format, no count
print_list.bullets(items)    # Bullet format, no count

# Specialized methods
print_list.as_table(data)    # Table with headers
print_list.summary(items)    # Summary for long lists
```

### Advanced Examples

```python
# Table with custom data
data = [['Name', 'Age', 'City'], ['Alice', 25, 'NYC'], ['Bob', 30, 'LA']]
print_list.as_table(data)

# Summary for long lists
long_list = list(range(100))
print_list.summary(long_list, max_items=6)  # Shows: [0, 1, 2, ..., 97, 98, 99]

# Custom print function (e.g., for logging)
def my_logger(msg):
    print(f"[LOG] {msg}")

print_list(items, style='bullet', print_func=my_logger)

# Combine partial with custom parameters
custom_compact = print_list(style='compact', sep=' | ')
custom_compact(items)  # Prints: apple | banana | cherry | date | elderberry | fig
```

### Key Features

- **Multiple Styles**: `wrapped`, `columns`, `numbered`, `bullet`, `compact`, `table`
- **Flexible Output**: Print directly or return strings with `print_func=None`
- **Partial Functions**: Create reusable printers with pre-configured settings
- **Customizable**: Control width, separators, line prefixes, and more
- **Type Safe**: Uses `Literal` types for style validation
- **Self-Contained**: No external dependencies beyond Python standard library

The `print_list` function is perfect for debugging, logging, user interfaces, and any situation where you need to display lists in a readable format.

            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/thorwhalen/lkj",
    "name": "lkj",
    "maintainer": null,
    "docs_url": null,
    "requires_python": null,
    "maintainer_email": null,
    "keywords": null,
    "author": "Thor Whalen",
    "author_email": null,
    "download_url": "https://files.pythonhosted.org/packages/ab/ff/4ff342e7f54795c29085a13f6fc3d5450d980a418e06caa1bd35a3b3f913/lkj-0.1.45.tar.gz",
    "platform": "any",
    "description": "# lkj\n\nLightweight Kit Jumpstart. A place for useful python utils built only with pure python.\n\nTo install:\t```pip install lkj```\n\n[Documentation](https://i2mint.github.io/lkj)\n\nNote: None of the tools here require anything else but pure python.\nAdditionally, things are organized in such a way that these can be \neasily copy-pasted into other projects. \nThat is, modules are all self contained (so can easily be copy-paste-vendored \n(do be nice and mention the source!))\nFurther, many functions will contain their own imports: Those functions can even be \ncopy-paste-vendored by just copying the function body.\n\n# Examples of utils\n\n## Find and replace\n\n`FindReplaceTool` is a general-purpose find-and-replace tool that can treat the input text as a continuous sequence of characters, \neven if operations such as viewing context are performed line by line.\n\nThe basic usage is \n\n```python\nFindReplaceTool(\"apple banana apple\").find_and_print_matches(r'apple')\n```\n    \n    Match 0 (around line 1):\n    apple banana apple\n    ^^^^^\n    ----------------------------------------\n    Match 1 (around line 1):\n    apple banana apple\n                 ^^^^^\n    ----------------------------------------\n\n```python\nFindReplaceTool(\"apple banana apple\").find_and_replace(r'apple', \"orange\")\n```\n\n    'orange banana orange'\n\n[See more examples in documentation](https://i2mint.github.io/lkj/module_docs/lkj/strings.html#lkj.strings.FindReplaceTool)\n\n[See here a example of how I used this to edit my CI yamls](https://github.com/i2mint/lkj/discussions/4#discussioncomment-12104547)\n\n## loggers\n\n### clog\n\nConditional log\n\n```python\n>>> clog(False, \"logging this\")\n>>> clog(True, \"logging this\")\nlogging this\n```\n\nOne common usage is when there's a verbose flag that allows the user to specify\nwhether they want to log or not. Instead of having to litter your code with\n`if verbose:` statements you can just do this:\n\n```python\n>>> verbose = True  # say versbose is True\n>>> _clog = clog(verbose)  # makes a clog with a fixed condition\n>>> _clog(\"logging this\")\nlogging this\n```\n\nYou can also choose a different log function.\nUsually you'd want to use a logger object from the logging module,\nbut for this example we'll just use `print` with some modification:\n\n```python\n>>> _clog = clog(verbose, log_func=lambda x: print(f\"hello {x}\"))\n>>> _clog(\"logging this\")\nhello logging this\n```\n\n### print_with_timestamp\n\nPrints with a timestamp and optional refresh.\n- input: message, and possibly args (to be placed in the message string, sprintf-style\n- output: Displays the time (HH:MM:SS), and the message\n- use: To be able to track processes (and the time they take)\n\n```python\n>>> print_with_timestamp('processing element X')\n(29)09:56:36 - processing element X\n```\n\n### return_error_info_on_error\n\nDecorator that returns traceback and local variables on error.\n\nThis decorator is useful for debugging. It will catch any exceptions that occur\nin the decorated function, and return an ErrorInfo object with the traceback and\nlocal variables at the time of the error.\n- `func`: The function to decorate.\n- `caught_error_types`: The types of errors to catch.\n- `error_info_processor`: A function that processes the ErrorInfo object.\n\nTip: To parametrize this decorator, you can use a functools.partial function.\n\nTip: You can have your error_info_processor persist the error info to a file or\ndatabase, or send it to a logging service.\n\n```python\n>>> from lkj import return_error_info_on_error, ErrorInfo\n>>> @return_error_info_on_error\n... def foo(x, y=2):\n...     return x / y\n...\n>>> t = foo(1, 2)\n>>> assert t == 0.5\n>>> t = foo(1, y=0)\nExiting from foo with error: division by zero\n>>> if isinstance(t, ErrorInfo):\n...     assert isinstance(t.error, ZeroDivisionError)\n...     hasattr(t, 'traceback')\n...     assert t.locals['args'] == (1,)\n...     assert t.locals['kwargs'] == {'y': 0}\n```\n\n## Miscellaneous\n\n### chunker\n\nChunk an iterable into non-overlapping chunks of size chk_size.\n\n```python\nchunker(a, chk_size, *, include_tail=True)\n```\n\n```python\n>>> from lkj import chunker\n>>> list(chunker(range(8), 3))\n[(0, 1, 2), (3, 4, 5), (6, 7)]\n>>> list(chunker(range(8), 3, include_tail=False))\n[(0, 1, 2), (3, 4, 5)]\n```\n\n### import_object\n\nImport and return an object from a dot string path.\n\n```python\nimport_object(dot_path: str)\n```\n\n```python \n>>> f = import_object('os.path.join')\n>>> from os.path import join\n>>> f is join\nTrue\n```\n\n## Pretty Printing Lists\n\nThe `print_list` function provides flexible, human-friendly ways to display lists and collections. It supports multiple display styles and can be used in several ways.\n\n### Basic Usage\n\n```python\nfrom lkj.strings import print_list\n\nitems = ['apple', 'banana', 'cherry', 'date', 'elderberry', 'fig']\n\n# Different display styles\nprint_list(items, style='wrapped')      # Automatic line wrapping\nprint_list(items, style='columns')      # Column format\nprint_list(items, style='numbered')     # Numbered list\nprint_list(items, style='bullet')       # Bullet points\nprint_list(items, style='compact')      # All on one line\nprint_list(items, style='table')        # Table format\n```\n\n### Direct Usage with Customization\n\n```python\n# Customize width, separators, and formatting\nprint_list(items, style='wrapped', max_width=40, sep=' | ')\nprint_list(items, style='columns', items_per_line=3)\nprint_list(items, style='numbered', line_prefix='  ')\nprint_list(items, style='bullet', show_count=False)\n\n# Return string instead of printing\nresult = print_list(items, style='numbered', print_func=None)\nprint(result)\n```\n\n### Partial Function Factory\n\nWhen you don't specify the `items` parameter, `print_list` returns a partial function that you can reuse:\n\n```python\n# Create specialized printers\nnumbered_printer = print_list(style='numbered', show_count=False)\nbullet_printer = print_list(style='bullet', print_func=None)\ncompact_printer = print_list(style='compact', max_width=60)\n\n# Reuse with different data\nnumbered_printer(['a', 'b', 'c'])        # Prints: 1. a\\n2. b\\n3. c\nresult = bullet_printer(['x', 'y', 'z']) # Returns: '\u2022 x\\n\u2022 y\\n\u2022 z'\ncompact_printer(['item1', 'item2'])      # Prints: item1, item2\n```\n\n### Convenience Methods\n\nThe `print_list` object provides convenient pre-configured methods:\n\n```python\n# Quick access to common styles\nprint_list.compact(items)    # Compact format, no count\nprint_list.wrapped(items)    # Wrapped format, no count  \nprint_list.columns(items)    # Column format, no count\nprint_list.numbered(items)   # Numbered format, no count\nprint_list.bullets(items)    # Bullet format, no count\n\n# Specialized methods\nprint_list.as_table(data)    # Table with headers\nprint_list.summary(items)    # Summary for long lists\n```\n\n### Advanced Examples\n\n```python\n# Table with custom data\ndata = [['Name', 'Age', 'City'], ['Alice', 25, 'NYC'], ['Bob', 30, 'LA']]\nprint_list.as_table(data)\n\n# Summary for long lists\nlong_list = list(range(100))\nprint_list.summary(long_list, max_items=6)  # Shows: [0, 1, 2, ..., 97, 98, 99]\n\n# Custom print function (e.g., for logging)\ndef my_logger(msg):\n    print(f\"[LOG] {msg}\")\n\nprint_list(items, style='bullet', print_func=my_logger)\n\n# Combine partial with custom parameters\ncustom_compact = print_list(style='compact', sep=' | ')\ncustom_compact(items)  # Prints: apple | banana | cherry | date | elderberry | fig\n```\n\n### Key Features\n\n- **Multiple Styles**: `wrapped`, `columns`, `numbered`, `bullet`, `compact`, `table`\n- **Flexible Output**: Print directly or return strings with `print_func=None`\n- **Partial Functions**: Create reusable printers with pre-configured settings\n- **Customizable**: Control width, separators, line prefixes, and more\n- **Type Safe**: Uses `Literal` types for style validation\n- **Self-Contained**: No external dependencies beyond Python standard library\n\nThe `print_list` function is perfect for debugging, logging, user interfaces, and any situation where you need to display lists in a readable format.\n",
    "bugtrack_url": null,
    "license": "apache-2.0",
    "summary": "A dump of homeless useful utils",
    "version": "0.1.45",
    "project_urls": {
        "Homepage": "https://github.com/thorwhalen/lkj"
    },
    "split_keywords": [],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "55a16d4b9a6551214122fbeea57c0de0ed3e110795aef5dcbf3a6f62b86b02b3",
                "md5": "e599a51d44d5b4410325e981c730e333",
                "sha256": "27a2e155d5b434ec3331f593abcf3953a20d1ab4a1d11aa432a2b8bdd03308a3"
            },
            "downloads": -1,
            "filename": "lkj-0.1.45-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "e599a51d44d5b4410325e981c730e333",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": null,
            "size": 41496,
            "upload_time": "2025-08-14T13:43:48",
            "upload_time_iso_8601": "2025-08-14T13:43:48.743530Z",
            "url": "https://files.pythonhosted.org/packages/55/a1/6d4b9a6551214122fbeea57c0de0ed3e110795aef5dcbf3a6f62b86b02b3/lkj-0.1.45-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "abff4ff342e7f54795c29085a13f6fc3d5450d980a418e06caa1bd35a3b3f913",
                "md5": "00546820e17eb3a1424d89404884378e",
                "sha256": "7d073372cc0be238d6efe193d994e7b88762f7d817aa26ff0c4c91279a4b4229"
            },
            "downloads": -1,
            "filename": "lkj-0.1.45.tar.gz",
            "has_sig": false,
            "md5_digest": "00546820e17eb3a1424d89404884378e",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": null,
            "size": 40494,
            "upload_time": "2025-08-14T13:43:49",
            "upload_time_iso_8601": "2025-08-14T13:43:49.839983Z",
            "url": "https://files.pythonhosted.org/packages/ab/ff/4ff342e7f54795c29085a13f6fc3d5450d980a418e06caa1bd35a3b3f913/lkj-0.1.45.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-08-14 13:43:49",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "thorwhalen",
    "github_project": "lkj",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "lcname": "lkj"
}
        
Elapsed time: 0.57176s