Package: cercis
CercisCercis/ˈsɜːrsɪs/ is a Python code formatter that is more configurable thanBlack(a popular Python code formatter).Cercisis 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 byBlack. The original license of Black is included in this
repository (seeLICENSE_ORIGINAL).Cercisinherited Black's very comprehensive test cases, which means we are confident
that our configurability addition does not introduce any undesirable side effects. We
also thoroughly tested every configurable options that we added.In particular, via its configurable options,Cerciscan completely fall back to Black.
SeeSection 4.5below for more details.Table of Contents1. Motivations2. Installation and usage2.1. Installation2.2. Usage2.2.1. Command line usage2.2.2. As pre-commit hook3.Cercis's code style3.1. Line length3.2. Single quote vs double quote3.3. Tabs vs spaces3.4. Base indentation spaces3.5. Extra indentation at line continuations3.5.1. At function definition (--function-definition-extra-indent)3.5.2. In other line continuations (--other-line-continuation-extra-indent)3.5.3. At closing brackets (--closing-bracket-extra-indent)3.6. "Simple" lines with long strings3.7. Collapse nested brackets3.8. Wrapping long lines ending with comments3.9. Keep blank lines in brackets4. How to configureCercis4.1. Dynamically in the command line4.2. In your project'spyproject.tomlfile4.3. In your project's.pre-commit-config.yamlfile4.4. Specify options intox.ini4.5. How to fall back to Black's behavior5. Maintainer resources5.1. How to rebase on top ofBlack?5.2. Change logs1. MotivationsWhile 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,Cercisaims at providing some configurability beyond Black's limited offering.2. Installation and usage2.1. InstallationCerciscan be installed by runningpip install cercis. It requires Python 3.8+ to
run. If you want to format Jupyter Notebooks, install withpip install "cercis[jupyter]".2.2. Usage2.2.1. Command line usageTo get started right away with sensible defaults:cercis{source_file_or_directory}You can runCercisas a package if running it as a script doesn't work:python-mcercis{source_file_or_directory}The commands above reformat entire file(s) in place.2.2.2. As pre-commit hookTo format Python files (.py), put the following into your.pre-commit-config.yamlfile. Remember to replace<VERSION>with your version of this tool (such asv0.1.0):-repo:https://github.com/jsh9/cercisrev:<VERSION>hooks:-id:cercisargs:[--line-length=88]To format Jupyter notebooks (.ipynb), put the following into your.pre-commit-config.yamlfile:-repo:https://github.com/jsh9/cercisrev:<VERSION>hooks:-id:cercis-jupyterargs:[--line-length=88]Seepre-commitfor more instructions. In
particular,hereis how to specify
arguments in pre-commit config.3.Cercis's code styleCercis's code style is largely consistent with thestyle of of Black.The main difference is thatCercisprovides several configurable options that Black
doesn't. Configurability is our main motivation behind creatingCercis.The next section (How to configureCercis) contains
detailed instructions of how to configure these options.3.1. Line lengthCercisuses 79 characters as the line length limit, instead of 88 (Black's default).You can override this default if necessary.OptionName--line-lengthAbbreviation-lDefault79Black's default88Command line usagecercis -l=120 myScript.pypyproject.tomlusageline-length = 120under[tool.cercis]pre-commitusageargs: [--line-length=120]3.2. Single quote vs double quoteCercisuses single quotes (') as the default for strings, instead of double quotes
(") which is Black's default.You can override this default if necessary.OptionName--single-quoteAbbreviation-sqDefaultTrueBlack's defaultFalseCommand line usagecercis -sq=True myScript.pypyproject.tomlusagesingle-quote = falseunder[tool.cercis]pre-commitusageargs: [--single-quote=False]3.3. Tabs vs spacesCercisoffers users the ability to use tabs rather than spaces.There are two associated options:--use-tabs(bool): whether to use tabs or spaces to format the codeOptionName--use-tabsAbbreviation-tabDefaultFalseBlack's defaultFalseCommand line usagecercis -tab=True myScript.pypyproject.tomlusageuse-tabs = falseunder[tool.cercis]pre-commitusageargs: [--use-tabs=False]--tab-width(int): when calculating line length (to determine whether to wrap
lines), how wide shallCercistreat each tab. Only effective when--use-tabsis
set toTrue.OptionName--tab-widthAbbreviation-twDefault4Black's defaultN/ACommand line usagecercis -tab=True -tw=2 myScript.pypyproject.tomlusagetab-width = 2under[tool.cercis]pre-commitusageargs: [--tab-width=2]3.4. Base indentation spacesThis option defines the number of spaces that each indentation level adds. This option
has no effect when--use-tabsis set toTrue.For example, if you set it to 2, contents within aforblock is indented 2 spaces:foriin(1,2,3,4,5):print(i)OptionName--base-indentation-spacesAbbreviation-bisDefault4Black's default4Command line usagecercis -bis=True -tw=2 myScript.pypyproject.tomlusagebase-indentation-spaces = 2under[tool.cercis]pre-commitusageargs: [--base-indentation-spaces=2]3.5. Extra indentation at line continuationsThere are three associated options:--function-definition-extra-indent--other-line-continuation-extra-indent--closing-bracket-extra-indentThey control whether we add anadditionalindentation level in some situations. Note
that these options can work well with tabs (--use-tabs=True).3.5.1. At function definition (--function-definition-extra-indent)# Cercis's default styledefsome_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)defsome_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 add an extra indentation level when wrapping a function signature line.
This is becausedef␣happens to be 4 characters, so when the base indentation is 4
spaces, it can be difficult to visually distinguish the function name and the argument
list if we don't add an extra indentation.If you set--base-indentation-spacesto other values than 4, this visual separation
issue will disappear, and you may not need to turn this option on.This style is encouragedin PEP8.OptionName--function-definition-extra-indentAbbreviation-fdeiDefaultTrueBlack's defaultFalseCommand line usagecercis -fdei=False myScript.pypyproject.tomlusagefunction-definition-extra-indent = trueunder[tool.cercis]pre-commitusageargs: [--function-definition-extra-indent=False]3.5.2. In other line continuations (--other-line-continuation-extra-indent)"Other line continuations" are cases other than in function definitions, such as:var=some_function(arg1_with_long_name,arg2_with_longer_name,)var2=['something','something else','something more',]So if you set this option (--other-line-continuation-extra-indent) toTrue, you can
add an extra level of indentation in these cases:var=some_function(arg1_with_long_name,arg2_with_longer_name,)var2=['something','something else','something more',]OptionName--other-line-continuation-extra-indentAbbreviation-olceiDefaultFalseBlack's defaultFalseCommand line usagecercis -olcei=True myScript.pypyproject.tomlusageother-line-continuation-extra-indent = trueunder[tool.cercis]pre-commitusageargs: [----other-line-continuation-extra-indent=False]3.5.3. At closing brackets (--closing-bracket-extra-indent)This option lets people customize where the closing bracket should be. Note that both
styles are OK according toPEP8.# --closing-bracket-extra-indent=Falsedeffunction(arg1:int,arg2:float,arg3_with_long_name:list,)->None:print('Hello world')result=func2(12345,3.1415926,[1,2,3],)something={'a':1,'b':2,'c':3,}# --closing-bracket-extra-indent=Truedeffunction(arg1:int,arg2:float,arg3_with_long_name:list,)->None:print('Hello world')result=func2(12345,3.1415926,[1,2,3],)something={'a':1,'b':2,'c':3,}OptionName--closing-bracket-extra-indentAbbreviation-cbeiDefaultFalseBlack's defaultFalseCommand line usagecercis -cbei=True myScript.pypyproject.tomlusageclosing-bracket-extra-indent = trueunder[tool.cercis]pre-commitusageargs: [--closing-bracket-extra-indent=False]3.6. "Simple" lines with long stringsBy 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.# Cercis's default style# (Suppose line length limit is 30 chars)# Cercis doesn't wrap slightly long linesvar1='This line has 31 chars'# Cercis doesn't wrap longer linesvar2='This line has 43 characters_______'# Falls back to Black when comments presentvar3=('shorter line'# comment)# Black's style (not configurable)# (Suppose line length limit is 30 chars)# Black wraps slightly long linesvar1=("This line has 31 chars")# But Black doesn't wrap longer linesvar2="This line has 43 characters_______"# Black wraps comments like this:var3=("shorter line"# comment)OptionName--wrap-line-with-long-stringAbbreviation-wlDefaultFalseBlack's defaultTrueCommand line usagecercis -wl=True myScript.pypyproject.tomlusagewrap-line-with-long-string = trueunder[tool.cercis]pre-commitusageargs: [--wrap-line-with-long-string=False]3.7. Collapse nested bracketsCercisby default collapses nested brackets to make the code more compact.# Cercis's default style# If line length limit is 30value=np.array([[1,2,3,4,5],[6,7,8,9,0],])# If line length limit is 10value=function({1,2,3,4,5,})# Black's style (not configurable)# If line length limit is 30value=np.array([[1,2,3,4,5],[6,7,8,9,0],])# If line length limit is 10value=function({1,2,3,4,5,})OptionName--collapse-nested-bracketsAbbreviation-cnbDefaultTrueBlack's styleFalseCommand line usagecercis -cnb=True myScript.pypyproject.tomlusagecollapse-nested-brackets = trueunder[tool.cercis]pre-commitusageargs: [--collapse-nested-brackets=False]The code implementation of this option comes fromPyink, another forked project from Black.3.8. Wrapping long lines ending with commentsSometimes we have lines that exceed the length limit only because of the in-line
comment. If we do not want to wrap those lines, we can use two options provided here:--wrap-comments--wrap-pragma-comments"Pragma comments", in this context, mean the directives for Python linters usually to
tell them to ignore certain errors. Pragma comments thatCerciscurrently recognizes
include:noqa:# noqa: E501type: ignore:# type: ignore[no-untyped-def]pylint:# pylint: disable=protected-accesspytype:# pytype: disable=attribute-errorOptionName--wrap-commentsAbbreviation-wcDefaultFalseBlack's styleTrueCommand line usagecercis -wc=True myScript.pypyproject.tomlusagewrap-comments = trueunder[tool.cercis]pre-commitusageargs: [--wrap-comments=False]OptionName--wrap-pragma-commentsAbbreviation-wpcDefaultFalseBlack's styleTrueCommand line usagecercis -wpc=True myScript.pypyproject.tomlusagewrap-pragma-comments = trueunder[tool.cercis]pre-commitusageargs: [--wrap-pragma-comments=False]And below is a 2x2 matrix to explain how these two options work together:-wc=True-wc=False-wpc=TrueAll comments wrapped w.n.No comments are wrapped-wpc=Falsep.c. not wrapped; o.c. wrapped w.n.No comments are wrappedNote:"w.n." means "when necessary""p.c." means "pragma comments""o.c." means "other comments"3.9. Keep blank lines in bracketsThis option allows us to keep the blank lines that we intentionally add into the
contents of brackets.Cercis's default style:my_list=[# Group 11,2,# Group 23,4,# Group 35,6,]Black's default style (not configurable):my_list=[# Group 11,2,# Group 23,4,# Group 35,6,]OptionName--keep-blank-lines-in-bracketsAbbreviation-kblibDefaultTrueBlack's styleFalseCommand line usagecercis -kblib=True myScript.pypyproject.tomlusagekeep-blank-lines-in-brackets = trueunder[tool.cercis]pre-commitusageargs: [--keep-blank-lines-in-bracketss=False](Note: if--keep-blank-lines-in-bracketsisTrue, multiple consecutive blank lines
are compressed into one blank line after formatting.)4. How to configureCercis4.1. Dynamically in the command lineHere are some examples:cercis --single-quote=True myScript.pyto format files to single quotescercis --function-definition-extra-indent=False myScript.pyto format files without
extra indentation at function definitioncercis --line-length=79 myScript.pyto format files with a line length of 79
characters4.2. In your project'spyproject.tomlfileYou can specify the options under the[tool.cercis]section of the file:[tool.cercis]line-length=88function-definition-extra-indent=truesingle-quote=false4.3. In your project's.pre-commit-config.yamlfileYou can specify the options under theargssection of your.pre-commit-config.yamlfile.For example:repos:-repo:https://github.com/jsh9/cercisrev:0.1.0hooks:-id:cercisargs:[--function-definition-extra-indent=False,--line-length=79]-repo:https://github.com/jsh9/cercisrev:0.1.0hooks:-id:cercis-jupyterargs:[--function-definition-extra-indent=False,--line-length=79]The value inrevcan be anyCercisrelease, or it can bemain, which means to
always use the latest (including unreleased)Cercisfeatures.4.4. Specify options intox.iniCurrently,Cercisdoes not support a config section intox.ini. Instead, you can
specify the options inpyproject.toml.4.5. How to fall back to Black's behaviorHere are the configuration options to fall back to Black's behavior. Put them inpyproject.toml:[tool.cercis]line-length=88single-quote=falseuse-tabs=falsebase-indentation-spaces=4function-definition-extra-indent=falseother-line-continuation-extra-indent=falseclosing-bracket-extra-indent=falsewrap-line-with-long-string=truecollapse-nested-brackets=falsewrap-comments=truewrap-pragma-comments=true5. Maintainer resourcesHere are some resources and notes for maintainers ofCercis:5.1. How to rebase on top ofBlack?Please refer to the fileHOW_TO_REBASE.md.5.2. Change logsThere are 2 files in this repo:CHANGELOG.mdandCHANGES.md.The former tracks the changes ofCercis(Blackdoes not have this file). The latter
tracks the changes onBlack(it exists in theBlackrepo as well).Change Log[0.2.5] - 2023-11-08ChangedRebasedCercisto be head to head withBlack(v23.11.0)Diffhttps://github.com/jsh9/cercis/compare/0.2.4...0.2.5[0.2.4] - 2023-10-23ChangedRebasedCercisto be head to head withBlack(v23.10.1)Diffhttps://github.com/jsh9/cercis/compare/0.2.3...0.2.4[0.2.3] - 2023-10-19ChangedRebasedCercisto be head to head withBlack(v23.10.0)Diffhttps://github.com/jsh9/cercis/compare/0.2.2...0.2.3[0.2.2] - 2023-09-13ChangedRebasedCercisto be head to head withBlackDiffhttps://github.com/jsh9/cercis/compare/0.2.1...0.2.2[0.2.1] - 2023-07-23ChangedRebasedCercisto be head to head withBlackFixedFixed a pytest regression where Python warnings are treated as errors
(https://github.com/jsh9/cercis/commit/1229b9dd18f861423e26f8de3f4b5e714d72bd9c)Diffhttps://github.com/jsh9/cercis/compare/0.2.0...0.2.1[0.2.0] - 2023-07-12ChangedRebasedCercisto be head to head withBlackversion 23.7.0Diffhttps://github.com/jsh9/cercis/compare/0.1.7...0.2.0[0.1.7] - 2023-06-19ChangedPulled in the latest changes from psf/black (code diff:https://github.com/jsh9/cercis/pull/27)[0.1.6] - 2023-05-23AddedA new option--wrap-commentsto not wrap any comments (not just pragma comments)A new option--keep-blank-lines-in-bracketsChangedImproved the CLI output text colors because the current colors are confusing or not
quite legible[0.1.5] - 2023-05-09AddedConfigurability to use tabs instead of spaces (two new options:--use-tabsand--tab-width)Configurability on base indentation spaces and extra indentation at different line
continuation situations[0.1.4] - 2023-05-07AddedA new configurable option:--closing-bracket-extra-indent[0.1.3] - 2023-05-07AddedA new configurable option:--collapse-nested-bracketsA new configurable option:--wrap-pragma-commentsSome Github workflow actions to make sure CHANGELOG.md is updatedChangedChanged the default quote to single quoteChanged the default line length to 79 charactersRemovedSome unrelated documentation and config files[0.1.2] - 2023-05-04AddedMerged 2 changes from psf/black:main (#5)Added option to not wrap "simple" lines with long strings
(#6)Full changeloghttps://github.com/jsh9/cercis/compare/0.1.1...0.1.2[0.1.1] - 2023-05-03AddedA configurable option:single-quote, for formatting code into single quotesFull changeloghttps://github.com/jsh9/cercis/compare/0.1.0...0.1.1[0.1.0] - 2023-04-30This is the initial version that branches away from Black (commit:e712e4)ChangedThe default indentation within a function definition (when line wrap happens) is now
8 spaces. (Black's default is 4, which isnot PEP8-compatible)Updated README, becausecercisnow branches away from BlackAddedA configurable option (function-definition-extra-indent) is added instead of
enforcing 8 spaces for everyone