Skip to content

Commit 5a3661e

Browse files
Ken KundertKen Kundert
authored andcommitted
fix inline_count for object that do not support len()
1 parent 1aa193c commit 5a3661e

3 files changed

Lines changed: 90 additions & 42 deletions

File tree

doc/releases.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ Latest development version
2929
the keymaps passed to a dumper in order to add comments and spacing rules.
3030
- Removed *get_value_from_keys()*, *get_lines_from_keys()*,
3131
*get_original_keys()*, and *join_keys()*.
32+
- Adds *inline_count* argument to :func:`dump` and :func:`dumps`.
3233

3334

3435
| Version: 3.8

nestedtext/nestedtext.py

Lines changed: 59 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -2063,24 +2063,26 @@ class NestedTextDumper:
20632063
# constructor {{{3
20642064
def __init__(
20652065
self,
2066-
width,
2067-
inline_level,
2068-
sort_keys,
20692066
indent,
2067+
sort_keys,
20702068
converters,
20712069
default,
2070+
spacing,
20722071
map_keys,
2072+
width,
2073+
inline_level,
2074+
inline_count,
20732075
dialect,
2074-
spacing,
20752076
):
20762077
assert indent > 0
2077-
self.width = width
2078-
self.inline_level = inline_level
20792078
self.indent = indent
20802079
self.converters = converters
20812080
self.map_keys = map_keys
20822081
self.default = default
20832082
self.spacing = spacing or {}
2083+
self.width = width
2084+
self.inline_level = inline_level
2085+
self.inline_count = inline_count
20842086
self.support_inlines = True
20852087
if dialect and "i" in dialect:
20862088
self.support_inlines = False
@@ -2443,10 +2445,15 @@ def render_value(self, obj, keys, values):
24432445
try:
24442446
if not self.support_inlines:
24452447
raise NotSuitableForInline from None
2446-
if level < self.inline_level:
2447-
raise NotSuitableForInline from None
2448-
if obj and (self.width <= 0 or len(obj) > self.width/5):
2448+
if obj and (self.width <= 0 or level < self.inline_level):
24492449
raise NotSuitableForInline from None
2450+
try:
2451+
if 0 < len(obj) < self.inline_count:
2452+
raise NotSuitableForInline from None
2453+
if obj and len(obj) > self.width/5:
2454+
raise NotSuitableForInline from None
2455+
except TypeError:
2456+
pass # does not have len()
24502457
content = self.render_inline_dict(obj, keys, values)
24512458
if obj and (len(content) > self.width):
24522459
raise NotSuitableForInline from None
@@ -2470,10 +2477,15 @@ def render_value(self, obj, keys, values):
24702477
try:
24712478
if not self.support_inlines:
24722479
raise NotSuitableForInline from None
2473-
if level < self.inline_level:
2474-
raise NotSuitableForInline from None
2475-
if obj and (self.width <= 0 or len(obj) > self.width/3):
2480+
if obj and (self.width <= 0 or level < self.inline_level):
24762481
raise NotSuitableForInline from None
2482+
try:
2483+
if 0 < len(obj) < self.inline_count:
2484+
raise NotSuitableForInline from None
2485+
if obj and (self.width <= 0 or len(obj) > self.width/3):
2486+
raise NotSuitableForInline from None
2487+
except TypeError:
2488+
pass # does not have len()
24772489
content = self.render_inline_list(obj, keys, values)
24782490
if obj and (len(content) > self.width):
24792491
raise NotSuitableForInline from None
@@ -2579,15 +2591,16 @@ def map_key(self, key, keys):
25792591
def dumps(
25802592
obj,
25812593
*,
2582-
width = 0,
2583-
inline_level = 0,
2584-
sort_keys = False,
25852594
indent = 4,
2595+
sort_keys = False,
25862596
converters = None,
2587-
map_keys = None,
25882597
default = None,
2589-
dialect = None,
25902598
spacing = None,
2599+
map_keys = None,
2600+
width = 0,
2601+
inline_level = 0,
2602+
inline_count = 1,
2603+
dialect = None,
25912604
):
25922605
# description {{{3
25932606
'''Recursively convert object to *NestedText* string.
@@ -2596,13 +2609,9 @@ def dumps(
25962609
obj:
25972610
The object to convert to *NestedText*.
25982611
2599-
width (int):
2600-
Enables inline lists and dictionaries if greater than zero and if
2601-
resulting line would be less than or equal to given width.
2602-
2603-
inline_level (int):
2604-
Recursion depth must be equal to this value or greater to be
2605-
eligible for inlining.
2612+
indent (int):
2613+
The number of spaces to use to represent a single level of
2614+
indentation. Must be one or greater.
26062615
26072616
sort_keys (bool or func):
26082617
Dictionary items are sorted by their key if *sort_keys* is *True*.
@@ -2619,10 +2628,6 @@ def dumps(
26192628
26202629
The second contains the keys of the parent.
26212630
2622-
indent (int):
2623-
The number of spaces to use to represent a single level of
2624-
indentation. Must be one or greater.
2625-
26262631
converters (dict):
26272632
A dictionary where the keys are types and the values are converter
26282633
functions (functions that take an object and return it in a form
@@ -2649,6 +2654,21 @@ def dumps(
26492654
it raises a TypeError, the value is reported as an
26502655
unsupported type.
26512656
2657+
spacing (dict):
2658+
A mapping that controls vertical spacing in the rendered output.
2659+
2660+
Integer keys specify the minimum number of blank lines between
2661+
sibling items at that depth. ``spacing={0: 1}`` requests one blank
2662+
line between top-level items; ``spacing={0: 2, 1: 1}`` requests two
2663+
blank lines between top-level items and one between items at the
2664+
first nested level. Depths not present in the mapping default to
2665+
zero.
2666+
2667+
The special key ``"edges"`` is the number of blank lines between
2668+
the document's header comments and the first data item, and
2669+
between the last data item and the document's footer comments.
2670+
One number applies to both. Defaults to zero.
2671+
26522672
map_keys (func or keymap):
26532673
This argument is used to modify the way keys are rendered, and,
26542674
when it is a keymap, to preserve comments and blank-line spacing
@@ -2668,20 +2688,17 @@ def dumps(
26682688
keys. The value returned is used as the key and so must be a
26692689
string. If no value is returned, the key is not modified.
26702690
2671-
spacing (dict):
2672-
A mapping that controls vertical spacing in the rendered output.
2691+
width (int):
2692+
Enables inline lists and dictionaries if greater than zero and if
2693+
resulting line would be less than or equal to given width.
26732694
2674-
Integer keys specify the minimum number of blank lines between
2675-
sibling items at that depth. ``spacing={0: 1}`` requests one blank
2676-
line between top-level items; ``spacing={0: 2, 1: 1}`` requests two
2677-
blank lines between top-level items and one between items at the
2678-
first nested level. Depths not present in the mapping default to
2679-
zero.
2695+
inline_level (int):
2696+
Recursion depth must be equal to this value or greater to be
2697+
eligible for inlining.
26802698
2681-
The special key ``"edges"`` is the number of blank lines between
2682-
the document's header comments and the first data item, and
2683-
between the last data item and the document's footer comments.
2684-
One number applies to both. Defaults to zero.
2699+
inline_count (int):
2700+
The minimum number of items required of a dictionary or list to be
2701+
eligible for inlining.
26852702
26862703
dialect (str):
26872704
Specifies support for particular variations in *NestedText*.
@@ -2953,8 +2970,8 @@ def dumps(
29532970

29542971
# code {{{3
29552972
dumper = NestedTextDumper(
2956-
width, inline_level, sort_keys, indent, converters, default,
2957-
map_keys, dialect, spacing
2973+
indent, sort_keys, converters, default, spacing,
2974+
map_keys, width, inline_level, inline_count, dialect
29582975
)
29592976
content = dumper.render_value(obj, (), ())
29602977

tests/test_misc.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1448,6 +1448,36 @@ def test_dump_converters_err(data, culprit, kind, kwargs):
14481448
def test_dump_width(given, expected, kwargs):
14491449
assert nt.dumps(given, **kwargs) == expected
14501450

1451+
# test_dump_inline_count {{{2
1452+
@parametrize(
1453+
'given, expected, kwargs', [
1454+
({}, '{}', dict()),
1455+
({}, '{}', dict(width=80)),
1456+
({}, '{}', dict(width=80, inline_count=0)),
1457+
({}, '{}', dict(width=80, inline_count=1)),
1458+
1459+
({0:0}, '0: 0', dict()),
1460+
({0:0}, '{0: 0}', dict(width=80)),
1461+
({0:0}, '{0: 0}', dict(width=80, inline_count=1)),
1462+
({0:0}, '0: 0', dict(width=80, inline_count=2)),
1463+
1464+
({0:0, 1:1}, '0: 0\n1: 1', dict()),
1465+
({0:0, 1:1}, '{0: 0, 1: 1}', dict(width=80)),
1466+
({0:0, 1:1}, '{0: 0, 1: 1}', dict(width=80, inline_count=1)),
1467+
({0:0, 1:1}, '{0: 0, 1: 1}', dict(width=80, inline_count=2)),
1468+
({0:0, 1:1}, '0: 0\n1: 1', dict(width=80, inline_count=3)),
1469+
1470+
({0:0, 1:1, 2:2}, '0: 0\n1: 1\n2: 2', dict()),
1471+
({0:0, 1:1, 2:2}, '{0: 0, 1: 1, 2: 2}', dict(width=80)),
1472+
({0:0, 1:1, 2:2}, '{0: 0, 1: 1, 2: 2}', dict(width=80, inline_count=1)),
1473+
({0:0, 1:1, 2:2}, '{0: 0, 1: 1, 2: 2}', dict(width=80, inline_count=2)),
1474+
({0:0, 1:1, 2:2}, '{0: 0, 1: 1, 2: 2}', dict(width=80, inline_count=3)),
1475+
({0:0, 1:1, 2:2}, '0: 0\n1: 1\n2: 2', dict(width=80, inline_count=4)),
1476+
]
1477+
)
1478+
def test_dump_inline_count(given, expected, kwargs):
1479+
assert nt.dumps(given, **kwargs) == expected
1480+
14511481
# test_dump_nones {{{2
14521482
@parametrize(
14531483
'given, expected, kwargs', [

0 commit comments

Comments
 (0)