Package: indenter
IndenterIndenter is a Python package that assists with programmatically indenting text to
arbitrary levels usingwithblocks and+/-operators. It has zero dependencies.Use Indenter to get easy structured output, even as your control flow weaves through
multiple functions:fromindenterimportIndenterdefvalidate_email(ind,email):print(ind+'Validating email...')# ...defparse_date(ind,date):print(ind+f'Parsing date{date}')# ...withind:print(ind+'Checking components')y,m,d=date.split('-')print(ind+'Date is valid!')defget_user_record(ind):print(ind+'Fetching user from database...')validate_email(ind+1,'ben@twos.dev')birthday=parse_date(ind+1,'1990-08-21')print(ind+'Fetched user!')# ...ind=Indenter(symbol='→ ')get_user_record(ind)Output:Fetching user from database...
→ Validating email...
→ Parsing date 1990-08-21
→ → Checking components
→ Date is valid!
Fetched user!Getting startedRequirementsPython 3.6+InstallingpipinstallindenterUsagefromindenterimportIndenterwithIndenter()asind:print(ind+"Text to be indented")# Output:#   Text to be indentedYou can nest an arbitrary number ofwithcalls:fromindenterimportIndenterind=Indenter()withind:print(ind+"I'm one level deep")withind:print(ind+"I'm two levels deep")print(ind+"I'm one level deep again")# Output:#   I'm one level deep#     I'm two levels deep#   I'm one level deep againYou can manually adjust the indentation level using+/-. Use this to indent output
by nested function calls correctly:importloggingfromindenterimportIndenterind=Indenter()funcdo_work(ind):logging.debug(ind+"Doing some work")funcdo_business_logic():ind=Indenter()logging.debug(ind+"Doing some business logic")do_work(ind+1)logging.debug(ind+"Finishing some busines logic")do_some_business_logic()# Output:# Doing some business logic#   Doing some work# Finishing some busines logicCustomizationThe default indentation symbol is two spaces. You can override this by passingsymbol:fromindenterimportIndenter# Indent with arrowswithIndenter(symbol="→ ")asind:print(ind+"I'm indented with an arrow")withind:print(ind+"I'm indented with two arrows")# Indent with 4 spaces per levelwithIndenter(symbol="    ")asind:print(ind+"I'm indented by four spaces")# Indent with tabswithIndenter(symbol="\t")asind:print(ind+"I'm indented by one tab")# Output:# → I'm indented by an arrow# → → I'm indented by two arrows#     I'm indented by four spaces# 	I'm indented by one tabWhen using custom symbols, nestedwiths will inherit the symbol of
their parent. If you need more than one type of indentation at once,
you must make and manage multipleIndenters.The indenter starts at zero levels of indentation by default, and
increases by one level for eachwithblock. This can be overridden
to start at other levels, such as 1:fromindenterimportIndenterind=Indenter(start=1)print(ind+"First-level indentation")withind:print(ind+"Second-level indentation")# Output:#   First-level indentation#     Second-level indentationContributingI welcome contributions and foster an inclusive environment.TestingTesting requirespytest(pip install pytest).pytestReleasing(mostly notes for myself)To release, first bump the version number insetup.cfg, commit the result, then run:rm-rfdist
pipinstallbuildtwine
python-mbuild--wheel
twinecheckdist/*# optional; check for common issuestwineuploaddist/*For ease of browsing by users, you should also cut a release on GitHub.