Skip to content

Commit

Permalink
Merge pull request #107 from neutrinoceros/hotfix105-bis
Browse files Browse the repository at this point in the history
BUG: fix formatting and parsing bugs for quoted strings constaining whitespace
  • Loading branch information
neutrinoceros authored Apr 28, 2022
2 parents e03a751 + 668e971 commit bf3b827
Show file tree
Hide file tree
Showing 8 changed files with 57 additions and 18 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,14 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [2.1.2] - 2022-04-28

- BUG: fix a bug where formatting would affect spacing within quoted str values
- BUG: fix a bug where strings containing spacing would be dumped without correct quotes,
making them appear as multiple separate values
- BUG: fix a bug where special strings 'true', 't', 'false' and 'f' would decay to boolean after two parsing cycles
- BUG: fix import * for inifix.io (add loads and dumps)

## [2.1.1] - 2022-04-27

BUG: fix a bug where string values containing whitespaces would incorrectly be splitted
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# `inifix`

[![PyPI](https://img.shields.io/pypi/v/inifix.svg?logo=pypi&logoColor=white&label=PyPI)](https://pypi.org/project/inifix/)
[![PyPI](https://img.shields.io/pypi/pyversions/inifix/2.1.1?logo=python&logoColor=white&label=Python)](https://pypi.org/project/inifix/)
[![PyPI](https://img.shields.io/pypi/pyversions/inifix/2.1.2?logo=python&logoColor=white&label=Python)](https://pypi.org/project/inifix/)
[![codecov](https://codecov.io/gh/neutrinoceros/inifix/branch/main/graph/badge.svg)](https://codecov.io/gh/neutrinoceros/inifix)
[![pre-commit.ci status](https://results.pre-commit.ci/badge/github/neutrinoceros/inifix/main.svg)](https://results.pre-commit.ci/badge/github/neutrinoceros/inifix/main.svg)
[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
Expand Down Expand Up @@ -153,7 +153,7 @@ This simple validator can be used as a hook for `pre-commit`. Simply add the
following to your project's `.pre-commit-config.yaml`
```yaml
- repo: https://github.com/neutrinoceros/inifix.git
rev: v2.1.1
rev: v2.1.2
hooks:
- id: inifix-validate
```
Expand All @@ -178,7 +178,7 @@ $ inifix-format pluto.ini --diff
This program also doubles as `pre-commit` hook
```yaml
- repo: https://github.com/neutrinoceros/inifix.git
rev: v2.1.1
rev: v2.1.2
hooks:
- id: inifix-format
```
Expand Down
2 changes: 1 addition & 1 deletion inifix/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@
from .io import loads
from .validation import validate_inifile_schema

__version__ = "2.1.1"
__version__ = "2.1.2"
11 changes: 4 additions & 7 deletions inifix/format.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,12 @@
from typing import TextIO
from typing import Union

from inifix.io import _split_tokens
from inifix.io import load

PADDING_SIZE = 2


def _normalize_whitespace(s: str) -> str:
return re.sub(r"\s", " ", s).strip()


def _format_section(data: str) -> str:
lines = data.splitlines()
contents = []
Expand All @@ -28,14 +25,14 @@ def _format_section(data: str) -> str:
values = []
for line in lines:
content, _, comment = line.partition("#")
content = _normalize_whitespace(content)
content = content.strip()
if not content and not comment:
continue
contents.append(content)
comments.append(_normalize_whitespace(comment))
comments.append(comment.strip())
if content.startswith("[") or not content:
continue
parameter, *value = content.split()
parameter, *value = _split_tokens(content)
parameters.append(parameter)
values.append(value)

Expand Down
9 changes: 7 additions & 2 deletions inifix/io.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
from inifix.validation import SCALAR_TYPES
from inifix.validation import validate_inifile_schema

__all__ = ["load", "dump"]
__all__ = ["load", "loads", "dump", "dumps"]

SECTION_REGEXP = re.compile(r"\[(?P<title>[^(){}\[\]]+)\]\s*")

Expand Down Expand Up @@ -208,7 +208,12 @@ def _from_path(file: PathLike) -> InifixConfT:
def _encode(v: Scalar) -> str:
if isinstance(v, float):
return ENotationIO.encode_preferential(v)
return str(v)
elif isinstance(v, str) and (
re.search(r"\s", v) is not None or v in ("true", "t", "false", "f")
):
return repr(v)
else:
return str(v)


def _write_line(key: str, values: IterableOrSingle[Scalar], buffer: TextIO) -> None:
Expand Down
2 changes: 1 addition & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[metadata]
name = inifix
version = 2.1.1
version = 2.1.2
description = I/O facility for Idefix/Pluto configuration files
long_description = file: README.md
long_description_content_type = text/markdown
Expand Down
14 changes: 13 additions & 1 deletion tests/test_format.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ def test_exact_format_inplace(capsys, tmp_path):
assert res == expected


def test_no_parameters(capsys, tmp_path):
def test_no_parameters(tmp_path):
target = tmp_path / "no_params.ini"
target.write_text(
" # comment 1\n"
Expand Down Expand Up @@ -154,3 +154,15 @@ def test_report_noop(capsys, tmp_path):

assert out == ""
assert err == f"{target} is already formatted\n"


def test_format_quoted_strings_with_whitespaces(tmp_path):
target = tmp_path / "spaces.ini"

inserted = '''Eggs 'Bacon Saussage' "spam"'''
expected = """Eggs 'Bacon Saussage' "spam"\n"""
target.write_text(inserted)
ret = main([str(target)])
assert ret != 0

assert target.read_text() == expected
23 changes: 20 additions & 3 deletions tests/test_io.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,9 @@ def test_idempotent_io(inifile):
("""val 1e2\n""", {"val": 100}),
("""val "1e2"\n""", {"val": "1e2"}),
("""val '1e2'\n""", {"val": "1e2"}),
('''[Spam]\nEggs "Bacon Saussage"''', {"Spam": {"Eggs": "Bacon Saussage"}}),
(
"name true 'true' 'steven bacon' ",
{"name": [True, "true", "steven bacon"]},
"name true 'true' 'steven bacon' 1",
{"name": [True, "true", "steven bacon", 1]},
),
],
)
Expand All @@ -78,6 +77,24 @@ def test_string_casting(data, expected):
assert mapping == expected


@pytest.mark.parametrize(
"data, expected",
[
('''[Spam]\nEggs "Bacon Saussage"''', {"Spam": {"Eggs": "Bacon Saussage"}}),
(
"name true 'true' 'steven bacon' 1",
{"name": [True, "true", "steven bacon", 1]},
),
],
)
def test_idempotent_string_parsing(data, expected):
initial_mapping = loads(data)
assert initial_mapping == expected
round_str = dumps(initial_mapping)
round_mapping = loads(round_str)
assert round_mapping == initial_mapping


def test_section_init():
data = {
"dummy": [0.0001, True],
Expand Down

0 comments on commit bf3b827

Please sign in to comment.