Skip to content

Commit

Permalink
Fix inline table conversion
Browse files Browse the repository at this point in the history
the function responsible for converting outline tables to inline was
faulty.
  • Loading branch information
Naofal-Helal authored and oz123 committed Sep 20, 2024
1 parent d983c19 commit 472b118
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 18 deletions.
22 changes: 17 additions & 5 deletions pipenv/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
from urllib.parse import unquote, urljoin

from pipenv.utils.constants import VCS_LIST
from pipenv.vendor.tomlkit.items import SingleKey, Table

try:
import tomllib as toml
Expand Down Expand Up @@ -1107,12 +1108,23 @@ def get_package_name_in_pipfile(self, package_name, category):
return name
return None

def _sort_category(self, category):
# toml tables won't maintain sorted dictionary order
# so construct the table in the order that we need
def _sort_category(self, category) -> Table:
# copy table or create table from dict-like object
table = tomlkit.table()
for key, value in sorted(category.items()):
table.add(key, value)
if isinstance(category, Table):
table.update(category.value)
else:
table.update(category)

# sort the table internally
table._value._body.sort(key=lambda t: t[0] and t[0].key or "")
for index, (key, _) in enumerate(table._value._body):
assert isinstance(key, SingleKey)
indices = table._value._map[key]
if isinstance(indices, tuple):
table._value._map[key] = (index,) + indices[1:]
else:
table._value._map[key] = index

return table

Expand Down
33 changes: 20 additions & 13 deletions pipenv/utils/toml.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
from typing import Union

from pipenv.vendor.plette.models import Package, PackageCollection
from pipenv.vendor.tomlkit.container import Container
from pipenv.vendor.tomlkit.container import Container, OutOfOrderTableProxy
from pipenv.vendor.tomlkit.items import AoT, Array, Bool, InlineTable, Item, String, Table
from pipenv.vendor.tomlkit.toml_document import TOMLDocument

try:
import tomllib as toml
Expand Down Expand Up @@ -33,26 +34,32 @@ def cleanup_toml(tml):
return toml


def convert_toml_outline_tables(parsed, project):
def convert_toml_outline_tables(parsed: TOMLDocument, project) -> TOMLDocument:
"""Converts all outline tables to inline tables."""

def convert_tomlkit_table(section):
result = section.copy()
if isinstance(section, tomlkit.items.Table):
result: Table = tomlkit.table()
if isinstance(section, Table):
body = section.value._body
elif isinstance(section, tomlkit.container.OutOfOrderTableProxy):
elif isinstance(section, OutOfOrderTableProxy):
body = section._internal_container._body
else:
body = section._body
for index, (key, value) in enumerate(body):
assert not hasattr(section, "_body")
body = section

index: int = 0
for key, value in body:
if not key:
continue
if hasattr(value, "keys") and not isinstance(
value, tomlkit.items.InlineTable
):
if hasattr(value, "keys") and not isinstance(value, InlineTable):
table = tomlkit.inline_table()
table.update(value.value)
result.value._body[index] = (key, table.value)
key.sep = " = " # add separator because it did not exist before
result.append(key, table)
else:
result.append(key, value)
index += 1

return result

def convert_toml_table(section):
Expand All @@ -66,10 +73,10 @@ def convert_toml_table(section):
result[package] = table
return result

is_tomlkit_parsed = isinstance(parsed, tomlkit.container.Container)
is_tomlkit_parsed = isinstance(parsed, Container)
for section in project.get_package_categories():
table_data = parsed.get(section, {})
if not table_data:
if table_data is None:
continue
if is_tomlkit_parsed:
result = convert_tomlkit_table(table_data)
Expand Down

0 comments on commit 472b118

Please sign in to comment.