python-poetry / tomlkit

Style-preserving TOML library for Python
MIT License
699 stars 100 forks source link

rewrite new toml-data will has a new whitespace line #352

Open yanquer opened 6 months ago

yanquer commented 6 months ago

rewrite toml data will has a new whitespace line.

eg toml:

toml

# xxx test

[env.pro1.rst]
    name = "x7"

[env2]
    name = 2

[env3]
    name = 3

modified with rewrite new tool data, like this

file_ = "test.toml"

def update_toml():
    with open(file_, "r") as f:
        t = tomlkit.load(f)

    t = merge_dicts(
        t,
        {'env': {'pro1': {'rst': {'name': "x7"}}}}
    )

    with open(file_, "w") as f:
        tomlkit.dump(t, f)

def merge_dicts(a: dict, b: dict):
    # ret = a.copy()
    ret = a

    for k, v in b.items():
        if k in a and isinstance(a[k], (dict, OrderedDict, Container)):
            ret[k] = merge_dicts(a[k], v)

    return ret

the result (has a new line after name = "x7")

# xxx test

[env.pro1.rst]
    name = "x7"

[env2]
    name = 2

[env3]
    name = 3

and if I edit in local with code


def merge_dicts(a: dict, b: dict):
    # ret = a.copy()
    return merge_dict_to_toml_local(a, b)

def merge_dict_to_toml_local(a: tomlkit.TOMLDocument, b: dict):

    for k, v in b.items():
        if k in a and isinstance(a[k], (dict, OrderedDict, Container)):
            merge_dict_to_toml_local(a[k], v)
        else:
            a[k] = v

There will be no more line.

I'm not sure if this is a bug, so I checked the source code. in file tomlkit/container.py, line 703 with function _replace_at , it will add a whitespace-line where there is not has whitespace-line. how check ? the end of tomlkit/container.py


def ends_with_whitespace(it: Any) -> bool:
    """Returns ``True`` if the given item ``it`` is a ``Table`` or ``AoT`` object
    ending with a ``Whitespace``.
    """
    return (
        isinstance(it, Table) and isinstance(it.value._previous_item(), Whitespace)
    ) or (isinstance(it, AoT) and len(it) > 0 and isinstance(it[-1], Whitespace))

ends_with_whitespace only check last and current without sub-tree.
Should subdata be checked ?