Skip to main content

Extensible and customizable file formatter with reading (me) friendly defaults.

Project description

cleer

cleer is a file formatter that is customizable and easy to extend.

It was primarily made for python (in python), but can work with any language.

It has a set of defaults that I have chosen for a specific and readable style. It does not try to make the smallest git diffs, but he most readable code in general. Objectively speaking of course (I like the formatting).

Installation

pip install cleer

Tutorial

Quickstart

Out of the box it comes with a CLI.

Use --helpon the base or any commands for all options.

cleer --help

It has 2 main commands:

  • inspect - JSON output of the formatting violations
  • format - format files in place

You can use them both on a single file or a all files/dirs in a directory.

cleer inspect path/to/file.py
cleer inspect path/to/dir/

Output example for inspect:

[
    {
        "path": "/full/path/to/file.py",
        "violations": [
            {
                "start_index": 49,
                "length": 22,
                "message": "Lines should not have any trailing whitespace."
            }
        ]
    }
]

Format files in place:

cleer format path/to/file.py

Inspect or format with specific config and log level

cleer format --log-level DEBUG --cleer python_path.to.my_file:my_cleer_instance  path/to/file.py

Formatters for python packages are recommended to create a clr.py file in the root of the project.

If the package can by imported as "my_package", and you just want the default formatting:

"""clr.py"""

from cleer import cleer_default


clr = cleer_default(current_packages=["my_package"])

This will ensure that imports are properly grouped and sorted.

Configuration

The chain of configuration is as follows:

  1. If a custom cleer instance is given with the --cleer argument.
  2. The default python path of clr:clr.
  3. A default configuration is generated.

Example of custom Cleer instance/config:

from cleer import *


# use the defaults with minimal input
clr = cleer_default(current_packages=["my_package"], internal_packages=["my_other_private_package"])
# create your own config from scratch
clr = Cleer(
    config={
        "groups": [ # Groups are collections of formatting stages
            {
                "includes": ["**/*.py"], # A group uses glob style include and exclude patterns to determine which files be collected
                "excludes": [
                    "**/.venv*/**",
                    "**/venv*/**"
                ],
                "stages": [ # stages are run in serial to format or inspect documents
                    {
                        "tokenizer": LineTokenizer(), # each stage has a tokenizer, that will tokenize and iterate through the tokens
                        "formatters": [ # formatters are all run in order on each token. 
                            TrailingWhitespaceFormatter(),
                        ]
                    }
                ]
            }
        ]
    }
)

Logging

cleer uses standard python logging levels. By default it is set to CRITICAL. You can change this with the --log-level argument.

  • DEBUG
  • INFO
  • WARNING
  • ERROR
  • CRITICAL

Run with VSCode

You can automatically format on save in vscode by installing the (Run On Save)[https://marketplace.visualstudio.com/items?itemName=emeraldwalk.RunOnSave] extension and adding a config like this under .vscode/settings.json:

{
    "emeraldwalk.runonsave": {
        "commands": [
            {
                "cmd": "./venv/bin/cleer format --log-level DEBUG ${file}"
            }
        ]
    }
}

Update the path to cleer to where ever you installed cleer at.

Programmatic API

The cleer CLI is a thin wrapper around the Cleer class.

You can directly call different inspect and format options on the Cleer class instance.

import pathlib

from cleer import *


# get a default instance, set some configs
clr = cleer_default(current_packages=["my_package"], internal_packages=["my_internal_pkg"])
# Or create your own instance from scratch
clr = Cleer(
    config={
        "groups": [
            {
                "includes": ["**/*.py"],
                "excludes": [
                    "**/.venv*/**",
                    "**/venv*/**"
                ],
                "stages": [
                    {
                        "tokenizer": LineTokenizer(),
                        "formatters": [
                            TrailingWhitespaceFormatter(),
                        ]
                    }
                ]
            }
        ]
    }
)

# inspect a document string for violations
violations = clr.inspect_str("x = 1   \n", "my_pkg/thing.py") 
# note that even for strings you have to pass a "file name"
# this is so that the "file" can be picked up by the matching config groups. 
# [
#     {
#         "start_index": 29,
#         "length": 20,
#         "message": "Lines should not have any trailing whitespace."
#     }
# ]


# inspect a file pointer
with open("thing.py", "r") as fp:
    violations = clr.inspect_fp(fp, "my_pkg/thing.py")
# note that even for strings you have to pass a "file name"
# this is so that the "file" can be picked up by the matching config groups. 
# [
#     {
#         "start_index": 29,
#         "length": 20,
#         "message": "Lines should not have any trailing whitespace."
#     }
# ]

# inspect a file by path
violations = clr.inspect_file("my_pkg/thing.py")
# [
#     {
#         "start_index": 29,
#         "length": 20,
#         "message": "Lines should not have any trailing whitespace."
#     }
# ]

# inspect all matching files in a directory
results = clr.inspect_dir(pathlib.Path("./"))
# [
#     {
#         "path": "my_pkg/thing.py",
#         "violations": [
#             {
#                 "start_index": 29,
#                 "length": 20,
#                 "message": "Lines should not have any trailing whitespace."
#             }
#         ]
#     }
# ]

# inspect a path (file or directory, auto-detected)
# this is what is used by the CLI to take either
results = clr.inspect_path("my_pkg/")
# for files, one entry at most will be returned.
# [
#     {
#         "path": "my_pkg/thing.py",
#         "violations": [
#             {
#                 "start_index": 29,
#                 "length": 20,
#                 "message": "Lines should not have any trailing whitespace."
#             }
#         ]
#     }
# ]

# format a document string (returns the formatted string)
formatted = clr.format_str("x = 1   \n", "my_pkg/thing.py")

# format a file pointer in place
with open("thing.py", "r+") as fp:
    clr.format_fp(fp, "my_pkg/thing.py")

# format a file in place by path
clr.format_file("my_pkg/thing.py")

# format all matching files in a directory in place
clr.format_dir(pathlib.Path("./"))

# format a path (file or directory, auto-detected)
# this is what is used by the CLI to take either
clr.format_path("my_pkg/")

Changelog

Changelog for cleer. All notable changes to this project will be documented in this file.

The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.

[0.1.0a2] - 2026-07-20

Initial Release

[0.1.0a1] - 2024-02-18

Initial stub

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

cleer-0.1.0a2.tar.gz (63.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

cleer-0.1.0a2-py3-none-any.whl (108.0 kB view details)

Uploaded Python 3

File details

Details for the file cleer-0.1.0a2.tar.gz.

File metadata

  • Download URL: cleer-0.1.0a2.tar.gz
  • Upload date:
  • Size: 63.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.6

File hashes

Hashes for cleer-0.1.0a2.tar.gz
Algorithm Hash digest
SHA256 97771184b4456b2d70121d8d02ff788f1e9b22a88196571f906d61cf563778ee
MD5 b2398a58cbc3750c5727e04593c81454
BLAKE2b-256 713e1a92d8e90db962808c9e66c989734a9f5455bfb524516bcb96ba524fc4b3

See more details on using hashes here.

File details

Details for the file cleer-0.1.0a2-py3-none-any.whl.

File metadata

  • Download URL: cleer-0.1.0a2-py3-none-any.whl
  • Upload date:
  • Size: 108.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.6

File hashes

Hashes for cleer-0.1.0a2-py3-none-any.whl
Algorithm Hash digest
SHA256 7c417a3cda82595ce3b18a716a90490245e05f01a79b9164847b14e542ab7928
MD5 94c8b028a9f6f2c1ebb0c56a3e6b3e3d
BLAKE2b-256 1491fed30b18e294455530050c2cfd2295af306b567b17babc529412eb567073

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page