Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

comments get deleted #42

Open
jugmac00 opened this issue Oct 5, 2020 · 12 comments
Open

comments get deleted #42

jugmac00 opened this issue Oct 5, 2020 · 12 comments
Labels
bug Something isn't working

Comments

@jugmac00
Copy link
Member

jugmac00 commented Oct 5, 2020

 [testenv:mypy]
 deps =
     mypy
 commands =
-    # do not lint tests yet; waiting for pytest 6.0 release
     mypy --strict src {posargs}

and

 [pytest]
-# only collect intended test classes, e.g. TestSaving
-# do not collect e.g. TestingFileStorage
 python_classes = Test[A-Z]*

whereas the first "bug" is pretty nice, as pytest 6.0 got released already some time ago :-)

@jugmac00
Copy link
Member Author

jugmac00 commented Oct 6, 2020

ConfigParser strips comments on reading, see https://github.com/python/cpython/blob/2ef5caa58febc8968e670e39e3d37cf8eef3cab8/Lib/configparser.py#L993-L1035

In another project, which uses GPG encrypted ini files for secrets, I also reported deleted comments, they switched from ConfigParser to ConfigUpdater
flyingcircusio/batou@b252f7a

https://pypi.org/project/ConfigUpdater/

While this approach seems ok for updating single values, this does not look like a lot of fun to implement for this project here 😱

That said, it looks like @asottile 's setup-cfg-fmt does not handle comments either.

@jugmac00 jugmac00 mentioned this issue Oct 6, 2020
@jugmac00
Copy link
Member Author

jugmac00 commented Oct 6, 2020

As mentioned in #34, there are some more issues with comments.

What is your intention for comments? Support them? Delete them? Should tox-ini-fmt "cowardly refuse" to change a tox.ini which contains comments?

@gaborbernat
Copy link
Member

Support them. TBD how though.

@hugovk
Copy link
Contributor

hugovk commented Oct 7, 2020

Maybe also support (maximum one?) blank line?

 commands =
-    # Unit tests
     {envpython} -m pytest --cov tinytext --cov tests --cov-report xml {posargs}
-
-    # Test runs
     tinytext --version
     tinytext --help
     tinytext abcdef

@jugmac00
Copy link
Member Author

jugmac00 commented Oct 8, 2020

This will be pretty interesting!

@gaborbernat maybe this is something for your next Twitch stream? I'd like to know your thoughts about the alternative ways to handle this.

Some random thoughts...

Imho, this problem breaks down into several smaller problems:

  • read config file without stripping the comments
  • parse values into a data structure which is aware of which key / entry goes with which comment
  • re-assemble the values
  • write back config file

I played a bit with ConfigUpdater - and it looks pretty promising...

a config like ...

[section]
# holla

key = value

# comment in section

will result in...

(Pdb++) cu["section"]._structure
[<Comment>, <Space>, <Option: key = value>, <Space>, <Comment>, <Space>]

Pretty nice!

Buuut, it breaks with @hugovk's https://github.com/hugovk/tinytext/blob/master/tox.ini

❯ python main.py 
Traceback (most recent call last):
  File "main.py", line 4, in <module>
    cu.read("tiny-tox.ini")
  File "/tmp/ConfigUpdater/venv/lib/python3.8/site-packages/configupdater/configupdater.py", line 618, in read
    self._read(fp, filename)
  File "/tmp/ConfigUpdater/venv/lib/python3.8/site-packages/configupdater/configupdater.py", line 826, in _read
    raise e
configparser.ParsingError: Source contains parsing errors: 'tiny-tox.ini'
        [line 11]: '    {envpython} -m pytest --cov tinytext --cov tests --cov-report xml {posargs}\n'
        [line 14]: '    tinytext --version\n'
        [line 15]: '    tinytext --help\n'
        [line 16]: '    tinytext abcdef\n'

Looks like ConfigUpdater fails when comments are between keys and values :-/

Which brings me back to the good ole ConfigParser- which - by default - strips comments (starting with # and ;).

But there is a workaround. When initializing ConfigParser, we could pass in an arbitrary comment-prefix - like "//" - then real comments, starting with # do not get stripped (or just pass in an empty list of prefixes).

e.g.

>>> list(list(cu.items())[2][1].items())
[('passenv', '\nFORCE_COLOR'), ('commands', '\n# Unit tests\n{envpython} -m pytest --cov tinytext --cov tests --cov-report xml {posargs}\n\n# Test runs\ntinytext --version\ntinytext --help\ntinytext abcdef'), ('commands_pre', '\n{envpython} -m pip install -r requirements.txt')]

Another problem

comments before the first section

# This is a simple example with comments.
[bug_tracker]
url = http://localhost:8080/bugs/
username = dhellmann
; You should not store passwords in plain text
; configuration files.
password = SECRET

When we fake the comment_prefixes to keep comments...

>>> c.read("motw.ini")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3.8/configparser.py", line 697, in read
    self._read(fp, filename)
  File "/usr/lib/python3.8/configparser.py", line 1082, in _read
    raise MissingSectionHeaderError(fpname, lineno, line)
configparser.MissingSectionHeaderError: File contains no section headers.
file: 'motw.ini', line: 1
'# This is a simple example with comments.\n'

If comments before the first section need to be supported, that could mean e.g. that we need to read the file with e.g. open, memorize the comments before the first section, strip them, and pass the rest to the ConfigParser :-/

@gaborbernat
Copy link
Member

But there is a workaround. When initializing ConfigParser, we could pass in an arbitrary comment-prefix - like "//" - then real comments, starting with # do not get stripped (or just pass in an empty list of prefixes).

This is promising. Can play around with something like this on my next stream. Thanks a ton for the in-depth research.

@hugovk
Copy link
Contributor

hugovk commented Oct 8, 2020

Here's another example. First bit the same as before, second bit slightly different:

--- tox.ini

+++ tox.ini

@@ -10,10 +10,7 @@

     pandas
     tests
 commands =
-    # Unit tests
     {envpython} -m pytest --cov pypistats --cov tests --cov-report xml {posargs}
-
-    # Test runs
     pypistats --version
     pypistats --help
     pypistats recent --help
@@ -34,6 +31,5 @@

     {envpython} -m pip install -r requirements.txt

 [testenv:py39]
-# NumPy and pandas' dependency Cython doesn't yet support Python 3.9
 extras =
     tests

https://github.com/hugovk/pypistats/blob/master/tox.ini

@gaborbernat gaborbernat added the bug Something isn't working label Jun 24, 2021
@ssbarnea
Copy link
Member

ssbarnea commented Dec 9, 2021

I was extremely happy to find this formatter until I observed that comments gets stripped, this being a deal breaker for most projects. I even doubt that I know a project without comments inside tox.ini, some of them extremely valuable. I really hope someone comes with a solution for this.

@gaborbernat
Copy link
Member

I personally don't have comments in any of my projects, but that's probably just me. That being said PR's are very welcome to address this shortcoming 👍

@ssbarnea
Copy link
Member

ssbarnea commented Dec 9, 2021

I bet you don't need comments because you know tox better than anyone else. Still, for bigger teams we often find the need to explain why we decided to use a specific option, so we avoid having someone else undo it by mistake. One recent example that I remember is using the trick of disabling tox install and use deps = --editable . in order to make the project that does not have setup.py work.

I wish I would have the time to do a PR on this but I am afraid that is not easy to implement or to find some free cycles. BTW, thanks again for pointing me to this project.

@pdecat
Copy link
Contributor

pdecat commented Jan 5, 2023

One workaround that fits me is to put comment at the end of otherwise non empty lines, e.g.:

# tox-ini-fmt tox.ini
--- tox.ini

+++ tox.ini

@@ -26,7 +26,7 @@

     .venv,
     .virtualenv,
     __pycache__
-ignore= # See https://black.readthedocs.io/en/stable/faq.html#why-are-flake8-s-e203-and-w503-violated
+ignore = # See https://black.readthedocs.io/en/stable/faq.html#why-are-flake8-s-e203-and-w503-violated
     E203,
     W503
 enable-extensions =

Edit: this does not work as it breaks flake8 in this case, as comments must be on their own line as per configparser specification.

@ssbarnea
Copy link
Member

Considering the age of this issue and the very limited time of all involved, I believe that is unlikely to be ever fixed, especially as we are more likely to switch config to pyproject.toml anyway.

I searched for other generic ini formatters but none is usable. The prettier plugin for ini files is far worse as it crashes on list entries from tox.ini.

sbrudenell added a commit to sbrudenell/btrfs2s3 that referenced this issue Jun 24, 2024
I noticed tox-dev/tox-ini-fmt#42, which makes
it hard to use comments in tox.ini. Auto-formatting tox.ini was the main
motivation to use a separate tox.ini at all, so just keep everything in
pyproject.toml.

Maybe tox will eventually have first-party support for pyproject.toml;
this will make the transition that much simpler.
sbrudenell added a commit to sbrudenell/btrfs2s3 that referenced this issue Jun 25, 2024
I noticed tox-dev/tox-ini-fmt#42, which makes
it hard to use comments in tox.ini. Auto-formatting tox.ini was the main
motivation to use a separate tox.ini at all, so just keep everything in
pyproject.toml.

Maybe tox will eventually have first-party support for pyproject.toml;
this will make the transition that much simpler.

It appears that tox==3.21.4 (appears on on ubuntu-22.04) can't actually
parse the legacy_tox_ini option, and so does not get to the point of
provisioning a tox environment for the approrpiate version. We now do
proper provisioning ourselves in github ci.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

5 participants