Cercis /ˈsɜːrsɪs/ is a Python code formatter that is more configurable than Black (a popular Python code formatter).
Cercis is also the name of a deciduous tree that boasts vibrant pink to purple-hued flowers, which bloom in early spring.
This code repository is forked from and directly inspired by Black. The original license of Black is included in this repository (see LICENSE_ORIGINAL).
While we like the idea of auto-formatting and code readability, we take issue with some style choices and the lack of configurability of the Black formatter. Therefore, Cercis aims at providing some configurability beyond Black's limited offering.
Cercis can be installed by running pip install cercis
. It requires Python 3.7+ to
run. If you want to format Jupyter Notebooks, install with
pip install "cercis[jupyter]"
.
To get started right away with sensible defaults:
cercis {source_file_or_directory}
You can run Cercis as a package if running it as a script doesn't work:
python -m cercis {source_file_or_directory}
The commands above reformat entire file(s) in place.
To format Python files (.py), put the following into your .pre-commit-config.yaml
file. Remember to replace <VERSION>
with your version of this tool (such as v0.1.0
):
- repo: https://github.com/jsh9/cercis
rev: <VERSION>
hooks:
- id: cercis
args: [--line-length=88]
To format Jupyter notebooks (.ipynb), put the following into your
.pre-commit-config.yaml
file:
- repo: https://github.com/jsh9/cercis
rev: <VERSION>
hooks:
- id: cercis-jupyter
args: [--line-length=88]
See pre-commit for more instructions. In particular, here is how to specify arguments in pre-commit config.
The code style in Cercis is largely consistent with the style of of Black.
The main difference is that Cercis provides several configurable options that Black doesn't. That's also our main motivation of creating Cercis.
Cercis offers the following configurable options:
- Extra indentation at function definition
- Single quote vs double quote
- "Simple" lines with long strings
The next section (How to configure Cercis) contains detailed instructions of how to configure these options.
# Cercis's default style
def some_function(
arg1_with_long_name: str,
arg2_with_longer_name: int,
arg3_with_longer_name: float,
arg4_with_longer_name: bool,
) -> None:
... |
# Black's style (not configurable)
def some_function(
arg1_with_long_name: str,
arg2_with_longer_name: int,
arg3_with_longer_name: float,
arg4_with_longer_name: bool,
) -> None:
... |
We choose to indent an extra 4 spaces because it adds a clear visual separation between the function name and the argument list. Not adding extra indentation is also called out as wrong in the the official PEP8 style guide.
If you do not like this default, you can easily turn it off.
Option | |
---|---|
Name | --function-definition-extra-indent |
Abbreviation | -fdei |
Default | True |
Command line usage | cercis -fdei=False myScript.py |
pyproject.toml usage |
function-definition-extra-indent = true under [tool.cercis] |
pre-commit usage |
args: [--function-definition-extra-indent=False] |
Both Cercis and Black default to using double quotes. But in Cercis you can specify using single quotes as the default style.
Option | |
---|---|
Name | --single-quote |
Abbreviation | -sq |
Default | False |
Command line usage | cercis -sq=True myScript.py |
pyproject.toml usage |
single-quote = true under [tool.cercis] |
pre-commit usage |
args: [--single-quote=False] |
By default, Black wraps lines that exceed length limit. But for very simple lines (such as assigning a long string to a variable), line wrapping is not necessary.
Also, as seen below, Black's default style can be a bit hard to predict (var2
vs
var3
).
# Cercis's default style
var1 = "not wrapped even if too long"
var2 = "not wrapped even if too long" # comment
var3 = "not wrapped, if the line gets too long" |
# Black's style (not configurable)
var1 = (
"wrapped when too long"
)
var2 = (
"wrapped when too long"
) # comment
var3 = "not wrapped, if the line gets too long" |
Option | |
---|---|
Name | --wrap-line-with-long-string |
Abbreviation | -wl |
Default | False |
Command line usage | cercis -wl=True myScript.py |
pyproject.toml usage |
wrap-line-with-long-string = true under [tool.cercis] |
pre-commit usage |
args: [--wrap-line-with-long-string=False] |
Here are some examples:
cercis --single-quote=True myScript.py
to format files to single quotescercis --function-definition-extra-indent=False myScript.py
to format files without extra indentation at function definitioncercis --line-length=79 myScript.py
to format files with a line length of 79 characters
You can specify the options under the [tool.cercis]
section of the file:
[tool.cercis]
line-length = 88
function-definition-extra-indent = true
single-quote = false
You can specify the options under the args
section of your .pre-commit-config.yaml
file.
For example:
repos:
- repo: https://github.com/jsh9/cercis
rev: 0.1.0
hooks:
- id: cercis
args: [--function-definition-extra-indent=False, --ling-length=79]
- repo: https://github.com/jsh9/cercis
rev: 0.1.0
hooks:
- id: cercis-jupyter
args: [--function-definition-extra-indent=False, --line-length=79]
Currently, Cercis does not support a config section in tox.ini
. Instead, you can
specify the options in pyproject.toml
.