Package: oitnb
The uncompromising code formatterBlackhas very many good points, but by design
it is not very flexible. If you cannot accept it as is,oitnbmight be an
alternative for you.In short, on top ofBlack’s features,oitnb:defaults to single-quotes, but allows you to select double-quotes for
strings (triple quotes and an empty string use double-quotes). Option--double.allows you to runmeldfor visual comparison of reformatted code,
so you can easily insert some# fmt: offat appropriate places. Option--meld.reads your configuration in a format that you already know (Python) from a file
that you most likely already have in your project anyway (__init__.py).have project spanning base defaults in your configuration directory
(XDG). That is e.g. where your line-length goes, that is carefully
brought in sync with your editor width, the width of the three
terminals fitting on your screen or your multi-file diff utility.makes displaying icons optional. They might not display in your
terminal in the first place, or not fit your professional environment.has support for diffing against version committed to the projectbeforestarting to
useoitnbWork-in-progress/things planned:triple quotes multi-line strings that start after the left
parenthesis of a function. Option--multi-line-unwrap. (A must
if you write a lot of in-file , dedented, strings with YAML, as e.g.
YAML library developer would.)control spreading of multi-element list to one per lineyour wish here (we can always make it a configuration option, command-line option)keep alignment of EOL commentsDetailsCode baseoitnbcode is directly derived fromBlack’s and uses many files
as-is.It can run most ofBlack’s tests without problems but there is a
handful of errors, which should all have to do with hard-coded
references toBlackin both file content and file naming.Extra options, defaults and configurationextra options:--double,--meld,--multi-line-unwrapoitnbdefaults to single-quotes around strings, if you want to use
the quoting likeBlackhas use the option--doubleoption.--meldwhich works like--diff,
but for the invocation ofmeldon the original file and the
reformatted version.meldallows you to directly edit the left
hand side (original) so you can at that point decide to insert some# fmt: off/# fmt: oncomments around lines, or to abandon
the use of a formatter altogether.Specifying--multi-line-unwrapruns an ugly post-processor on the reformatted linesundoingthe rewrite of:x = yaml.load("""
a: 1
b: 2
""")into:x = yaml.load(
    """
a: 1
b: 2
"""
)The program starts with an empty config dict and tries to read the basic
configuration fromoitnb.ponin the user config dir usingappdirs.user_config_dir. This adheres to the XDG standard on Linux
(i.e.~/.config/oitnb)if no environment variables are set to
change the defaults. That file should contain a valid Python dict
definition ( with{}ordict(), and from thisdictthe value
fordefaultis taken (using safe evaluation) to update the config dict:dict(
   default=dict(line_length=666, double=True),
)After that the directory hierarchy up-the-tree is searched until.gitis found, or.hgor an__init__.pyfile with a module
level definition of_package_data. That should be a dict and from
there the value for the keyoitnbis taken to update the
config:_package_data = dict(
    oitnb=dict(line_length=88),
)oitnb’s__init__.pyhas more information there used (withoutimport-ing!), and
programmatically updated, by other tools:_package_data = dict(
    full_package_name='oitnb',
    version_info=(0, 1, 1),
    __version__='0.1.1',
    author='Anthon van der Neut',
    author_email='a.van.der.neut@ruamel.eu',
    description="oitnb works around some of black's issues",
    entry_points='oitnb=oitnb:main',
    license='MIT',
    since=2018,
    status=alpha,
    package_data={"_oitnb_lib2to3": ["*.txt"]},
    install_requires=['click>=6.5', 'attrs>=17.4.0', 'appdirs', 'toml>=0.9.4'],
    test_suite="_test.test_oitnb",
    tox=dict(
        env='36',
    ),
    oitnb=dict(line_length=88),
)


version_info = _package_data['version_info']
__version__ = _package_data['__version__']On top of this, any command-line options are used to overrule the config, and
then the program is initialised.Dashes (-) in options are internally replaced by underscore (_),
you can use that form as key indict(op_tion=True). With dashes you
would need to use{“op-tion”: True}There is currently no computer wide, setting for defaults, such as/etc/xdg/oitnb(is anyone sharing their development machines these
days?).Finding changes against pre-oitnbrevisionsIf you have an existing project with revision history, and applyoitnbto your sources, then diffing between pre- and
post-oitnbversions is going to be cluttered.If your application ofoitnbwas applied without Internal errors, and if you did
not have to apply# fmt: noto often, then you can use the
following to get more useful visual diffs usingmeld.The installation ofoitnbincludes a minimal utilityomeld,
add this as an external diff tool to your mercurials.hgrcfile:[extensions]
hgext.extdiff =

[extdiff]
cmd.omeld =Now you can executehg omeld-r-4-r-1orhg omeld-r-4(assuming revision -4 was from before applyingoitnb) andomeldwill runoitnbton both temporarily created source
trees, before handing those trees over tomeld. That means
e.g. that any source changes regarding quotes or removal of
superfluous u’s from u’’ strings, rewrapping, etc. are going to be the same for both
sides of the revisions. Thereby leaving the real code changes in the
diff thatmeldpresents.If the omeld tools gets a file or directory as argument that isnotunder/tmpor/var/tmp, it will not runoitnbon that
file/directory. If you keep your source tree under/var/tmp, you are
out of luck: your python will be formatted.The above approach:check out both (old) revisions trees, code format
them with ``oitnb`` and run a diff, is generic.meldandmercurialare just
the tools I use and can easily provide a working setup for.For git, which in my experience is a bit more difficult to get to
understand multiple external difftools, you can do:alias gomeld='git difftool --extcmd=omeld -y'and use that alias.gitseems somewhat more optimised thanhgin that if the current checked out
version of a file is the same as one of the reversions asked, that it
will not make a temporary version (not even if you have to compare
multiple files). Versions before 0.1.4 should therefore not be used
with the above alias, as those may result updated files
in your source tree (which should not break anything, but not be what
you expected).Problems you might encounter with BlackDouble-quotes everywhereIf you use single-quotes for your strings you are in good company:“People use to really love double quotes. I don’t know
why..
And as PEP8 has the following to say about quotes around strings:In Python, single-quoted strings and double-quoted strings are the same. This PEP
does not make a recommendation for this. Pick a rule and stick to it.Googling forStick to it: continue or confine oneself to doing or using a particular thing.It is not just the consistency of confining yourself, it is also the long term continuation.Unwrapping where a second line might doIf you have a list of short strings that fit on a line and add one so
that it doesn’t fit anymore,youdon’twantthattoallofasuddenforceeverysingleelementon a new line. Just putting the added overflow on a new line is good enough in those cases.Funny charactersThe Unicode in the messages might not display in the font
you’re using (they did not for me with Inconsolata in my Gnome Terminal). Do you
know what those code-points should show?  If not, are you sure that when
usingBlackon a different computer, while the person who pays you
for your work looks over your shoulder, that you’ll not be embarrassed (or get into
trouble if e.g. they were code-points U+5350 or U+0FD5)?You might find seeing the SLEEPING FACE (U+1F634), SHORTCAKE (U+1F370),
COLLISION SYMBOL (U+1F4A5), BROKEN HEART (U+1F494), SPARKLES (U+2728)
interesting for a while. But especially when using a small font in order not to scroll too much the details become blurry and no-fun.Little configurabilityThe configurability of Black consists inserting lines in Yet Another
Markup Format that adds nothing to the existing spectrum in Yet
Another Config File cluttering your project directory.