Anatomy of a snippet

There is a block of text within a configuration file which would like to replace.

The only requirement is the file format should recognize pound symbol # as a comment.

snippet code

A snippet is a dynamic block in an otherwise static file.

The snippet code identifies each snippet. If there is only one snippet, it’s optional. To future proof it, best practice is to set a snippet code. There is no down side besides …

i’m going to make you watch really horrible movies!

The snippet code should be a cringe cultural reference. Will also see this in the changelog.

In a changelog, an entry line seldomly uses - style:. Especially not as the first line.

And it’s sorta awkward seeing it in a changelog.

Heh! Changelogs aren’t supposed to be for entertainment

A snippet without a snippet_co

before snippet
# @@@ editable
code block
# @@@ end
after snippet

A snippet with a snippet_co

before snippet
# @@@ i_am_a_snippet_co
code block
# @@@ end
after snippet

Multiple snippets in one file

before snippet
# @@@ i_am_a_snippet_co
code block
# @@@ end
some more content
# @@@ i_am_another_snippet_co
code block
# @@@ end
after snippet
Don’t nest snippets
Don’t mismatch begin/end tags
markdown not supported

replace example

Replace the text within the snippet

>>> import tempfile
>>> import textwrap
>>> from pathlib import Path
>>>
>>> from drain_swamp_snippet import Snip, ReplaceResult
>>>
>>> # prepare
>>> text = (
...     "before snippet\n"
...     "# @@@ editable i_am_a_snippet_co\n"
...     "code block\n"
...     "# @@@ end\n"
...     "after snippet\n"
... )
>>> contents_existing = textwrap.dedent(text)
>>>
>>> contents_new = """new\ncontents\nhere"""
>>>
>>> text_expected = (
...     "before snippet\n"
...     "# @@@ editable i_am_a_snippet_co\n"
...     "new\n"
...     "contents\n"
...     "here\n"
...     "# @@@ end\n"
...     "after snippet\n"
... )
>>> expected = textwrap.dedent(text_expected)
>>>
>>> with tempfile.TemporaryDirectory() as f_path:
...     path_f = Path(f_path)
...
...     # prepare
...     path_some_conf = path_f / "some.conf"
...     chars_written = path_some_conf.write_text(contents_existing)
...
...     # act
...     snip = Snip(path_some_conf)
...     is_success = snip.replace(contents_new, id_="i_am_a_snippet_co")
...
...     actual = path_some_conf.read_text()
...     assert is_success == ReplaceResult.REPLACED
...     assert actual == expected
...
>>>

In a temporary folder, created a file, some.conf with contents, contents_existing.

The snippet, with id i_am_a_snippet_co, replace the contents with contents_new.

textwrap.dedent("""\ would normally be used to:

  • remove indention

  • ignores the preceding newline

Snip constructor parameter, is_quiet, turns off logging

Validation

validation occurs at the beginning of Snip.replace. Failing validation, replace will not proceed; file contents will be unaffected.

Validation checks:

  • nesting

  • mismatching or out of order start / end tags

Where to use

Python package authors rarely write and publish just one python package.

We write lots of packages!

In each package, there is boilerplate code, not covered by unittests, that is almost an exact copy as found in other packages.

After a few published packages, this boilerplate code becomes a liability and an eye sore.

Code within Makefile or igor.py needs to brought under control. Like a cancer, waiting to be exploited, less is more.

Ideally cut out in its entirely; preferably, as much as reasonable.

File formats – supported

Lines starting with pound sign # are considered comments:

  • python

  • bash

  • pyproject.toml

  • Linux config files

File formats – tricky:

  • yaml

    Indention would need to be supplied with the content. There is no indent=8 option

File formats – ill-suited (for now):

  • html

    Comment begin/end tokens are <!-- -->

  • RestructuredText

    Comment token (period)(period)(space)

  • markdown

    Platform-independent comment

    (empty line)
    [comment]: # (This actually is the most platform independent comment)
    

    The blank line before the comment line and maybe one afterwards would be tricky

  • Makefile

    Makefile contains two languages: Makefile and bash (or whatever shell is set). So there are two distinct languages in one file. Intertwined!

    Isn’t autotools meant to build Makefiles? Isn’t this also a sewer targetted by hackers?

    The entire point is to reduce Makefile and igor.py code to the minimum.