Skip to content

c108.formatters

Robust formatting utilities for development and debugging.

Type-aware formatters for debugging, logging, and exception messages. All formatters handle broken repr, recursive objects, and edge cases gracefully with consistent styling across ASCII/Unicode output. The fmt_any() function intelligently dispatches to specialized formatters.

Preset = Literal['cli', 'compact', 'debug', 'logging', 'repr', 'stdlib'] module-attribute

Style = Literal['angle', 'arrow', 'braces', 'colon', 'equal', 'paren', 'repr', 'unicode-angle'] module-attribute

PRIMITIVE_TYPES = (type(None), bool, int, float, complex, str, bytes, type(Ellipsis), type(NotImplemented), array.array, bytearray) module-attribute

FmtOptions dataclass

Formatting options for fmt_* functions.

Controls display style, repr behavior, and formatting preferences. Immutable for safe sharing across recursive calls.

Attributes:

Name Type Description
fully_qualified bool

Whether to include FQN type names.

include_traceback bool

Include exception traceback info.

label_classes bool

Whether to add 'class' prefix for types (e.g. vs ).

label_primitives bool

Whether to show type labels for int, float, str, bytes, etc.

repr Repr

reprlib.Repr instance controlling collection formatting and limits. Used both for truncation (maxlist, maxdict, maxlevel) and for delegating built-in collection formatting when appropriate.

style Style

Display style for type-value pairs: "angle" | "arrow" | "braces" | "colon" | "equal" | "paren" | "repr" | "unicode-angle"

Note

While FmtOptions itself is frozen, the 'repr' field is not. Avoid mutating 'repr' attributes directly. Prefer to use merge() or factory methods to create new instances with updated configuration.

Examples:

>>> # Use defaults
>>> fmt_any(1)
'1'
>>> # Custom config
>>> configure(label_primitives=True, style="angle")
>>> fmt_any(2)
'<int: 2>'
>>> # Create variants with custom params
>>> fmt_any(3)
'<int: 3>'
>>> configure(label_primitives=False)
>>> fmt_any(4)
'4'
Source code in c108/formatters.py
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
@dataclass(frozen=True)
class FmtOptions:
    """Formatting options for fmt_* functions.

    Controls display style, repr behavior, and formatting preferences.
    Immutable for safe sharing across recursive calls.

    Attributes:
        fully_qualified: Whether to include FQN type names.
        include_traceback: Include exception traceback info.
        label_classes: Whether to add 'class' prefix for types (e.g. <class 'int'> vs <int>).
        label_primitives: Whether to show type labels for int, float, str, bytes, etc.
        repr: reprlib.Repr instance controlling collection formatting and limits.
            Used both for truncation (maxlist, maxdict, maxlevel) and for
            delegating built-in collection formatting when appropriate.
        style: Display style for type-value pairs:
            "angle" | "arrow" | "braces" | "colon" | "equal" | "paren" | "repr" | "unicode-angle"

    Note:
        While FmtOptions itself is frozen, the 'repr' field is not. Avoid mutating 'repr' attributes directly.
        Prefer to use merge() or factory methods to create new instances with updated configuration.

    Examples:
        >>> # Use defaults
        >>> fmt_any(1)
        '1'

        >>> # Custom config
        >>> configure(label_primitives=True, style="angle")
        >>> fmt_any(2)
        '<int: 2>'

        >>> # Create variants with custom params
        >>> fmt_any(3)
        '<int: 3>'
        >>> configure(label_primitives=False)
        >>> fmt_any(4)
        '4'
    """

    fully_qualified: bool = False
    include_traceback: bool = False
    label_classes: bool = False
    label_primitives: bool = False
    repr: reprlib.Repr = field(default_factory=lambda: _repr_factory())
    style: Style = "repr"

    def __post_init__(self):
        object.__setattr__(self, "fully_qualified", bool(self.fully_qualified))
        object.__setattr__(self, "include_traceback", bool(self.include_traceback))
        object.__setattr__(self, "label_classes", bool(self.label_classes))
        object.__setattr__(self, "label_primitives", bool(self.label_primitives))

        if isinstance(self.repr, reprlib.Repr):
            _clean_repr(self.repr)
        else:
            object.__setattr__(self, "repr", _repr_factory())

        if self.style not in {
            "angle",
            "arrow",
            "braces",
            "colon",
            "equal",
            "paren",
            "repr",
            "unicode-angle",
        }:
            object.__setattr__(self, "style", "repr")

    def merge(
        self,
        *,
        fully_qualified: bool = UNSET,
        include_traceback: bool = UNSET,
        label_classes: bool = UNSET,
        label_primitives: bool = UNSET,
        max_depth: int = UNSET,
        max_items: int = UNSET,
        max_str: int = UNSET,
        repr: reprlib.Repr = UNSET,
        style: Style = UNSET,
    ) -> Self:
        """
        Create a new FmtOptions instance with selectively updated fields.

        If a parameter value is UNSET, no update is applied to the field.

        Args:
            fully_qualified: Whether to include FQN type names.
            include_traceback: Include exception traceback info.
            label_classes: Whether to add 'class' prefix for types (e.g. <class 'int'> vs <int>).
            label_primitives: Whether to show type labels for int, float, str, bytes, etc.
            max_depth: Maximum depth for nested structures; overrides repr.maxlevel.
            max_items: Maximum number of elements in collections; overrides repr config.
            max_str (int): The maximum length for strings and other representations; overrides repr config.
            repr: reprlib.Repr instance controlling collection formatting and limits.
            style: Display style for type-value pairs: "angle" | "colon" | "equal" | "paren" | "repr" | "unicode-angle"

        Returns:
            New FmtOptions instance with merged configuration
        """
        fully_qualified = ifnotunset(fully_qualified, default=self.fully_qualified)
        include_traceback = ifnotunset(include_traceback, default=self.include_traceback)
        label_classes = ifnotunset(label_classes, default=self.label_classes)
        label_primitives = ifnotunset(label_primitives, default=self.label_primitives)

        if not isinstance(repr, (reprlib.Repr, type(None), type(UNSET))):
            raise ValueError(f"reprlib.Repr or None expected, but got {type(repr).__name__}")

        r = ifnotunset(repr, default=self.repr)
        r = _repr_factory(max_depth=max_depth, max_items=max_items, max_str=max_str, default=r)

        style = ifnotunset(style, default=self.style)

        return FmtOptions(
            fully_qualified=fully_qualified,
            include_traceback=include_traceback,
            label_classes=label_classes,
            label_primitives=label_primitives,
            repr=r,
            style=style,
        )

    def __eq__(self, other: object) -> bool:
        if not isinstance(other, FmtOptions):
            return NotImplemented

        # 1. Compare simple dataclass fields
        if (
            self.fully_qualified != other.fully_qualified
            or self.include_traceback != other.include_traceback
            or self.label_primitives != other.label_primitives
            or self.style != other.style
        ):
            return False

        # 2. Compare Repr objects
        # Optimization: if they are the exact same object, we are good
        if self.repr is other.repr:
            return True

        # Otherwise, compare the functional configuration of the Repr engine
        repr_attrs = (
            "maxlevel",
            "maxdict",
            "maxlist",
            "maxtuple",
            "maxset",
            "maxfrozenset",
            "maxdeque",
            "maxarray",
            "maxlong",
            "maxstring",
            "maxother",
            "fillvalue",
        )
        for attr in repr_attrs:
            if getattr(self.repr, attr) != getattr(other.repr, attr):
                return False

        return True

    def __hash__(self) -> int:
        # Since we overrode __eq__, we must override __hash__ to maintain contract.
        # We assume repr attributes are effectively immutable for FmtOptions.
        repr_attrs = (
            "maxlevel",
            "maxdict",
            "maxlist",
            "maxtuple",
            "maxset",
            "maxfrozenset",
            "maxdeque",
            "maxarray",
            "maxlong",
            "maxstring",
            "maxother",
            "fillvalue",
        )
        repr_state = tuple(getattr(self.repr, attr) for attr in repr_attrs)

        return hash(
            (
                self.fully_qualified,
                self.include_traceback,
                self.label_classes,
                self.label_primitives,
                self.style,
                repr_state,
            )
        )

    @classmethod
    def cli(cls, max_depth: int = 3, max_items: int = 16, max_str: int = 80) -> Self:
        """
        Optimized for command-line interfaces.

        Uses 'equal' style (key=value) and constrains output to typical terminal width.
        """
        r = _repr_factory(max_depth=max_depth, max_items=max_items, max_str=max_str)
        return cls(
            fully_qualified=False,
            include_traceback=False,
            label_classes=False,
            label_primitives=False,
            repr=r,
            style="equal",
        )

    @classmethod
    def compact(cls, max_depth: int = 2, max_items: int = 6, max_str: int = 32) -> Self:
        """Concise output for readability."""
        r = _repr_factory(max_depth=max_depth, max_items=max_items, max_str=max_str)
        return cls(
            fully_qualified=False,
            include_traceback=False,
            label_classes=False,
            label_primitives=False,
            repr=r,
            style="repr",
        )

    @classmethod
    def debug(cls, max_depth: int = 6, max_items: int = 256, max_str=1024) -> Self:
        """Verbose output for debugging."""
        r = _repr_factory(max_depth=max_depth, max_items=max_items, max_str=max_str)
        return cls(
            fully_qualified=False,
            include_traceback=True,
            label_classes=False,
            label_primitives=True,
            repr=r,
            style="repr",
        )

    @classmethod
    def logging(cls, max_depth: int = 3, max_items: int = 16, max_str: int = 128) -> Self:
        """Balanced output for production logging."""
        r = _repr_factory(max_depth=max_depth, max_items=max_items, max_str=max_str)
        return cls(
            fully_qualified=False,
            include_traceback=False,
            label_classes=False,
            label_primitives=False,
            repr=r,
            style="repr",
        )

    @classmethod
    def reprlib(cls, max_depth: int = None, max_items: int = None, max_str: int = None) -> Self:
        """
        Mimics the default behavior of the standard library 'reprlib' module.

        By default enforces standard safety limits (depth=6, items=6, str=30) generally used
        by 'reprlib.Repr' to prevent large output.
        """
        # Get reprlib defaults: maxlevel=6, maxlist/tuple/dict=6, maxstring=30
        r_reprlib = reprlib.Repr()

        # Override defaults if provided params are int
        repr_ = _repr_factory(
            max_depth=max_depth, max_items=max_items, max_str=max_str, default=r_reprlib
        )

        return cls(
            fully_qualified=False,
            include_traceback=False,
            label_classes=False,
            label_primitives=False,
            repr=repr_,
            style="repr",
        )

    @classmethod
    def stdlib(cls) -> Self:
        """
        Mimics the stdlib 'repr()' behavior with unlimited output.

        Removes truncation limits (sets them to maxsize) and ensures 'repr' style.
        Use with caution on large structures.
        """
        r = _repr_factory(max_depth=sys.maxsize, max_items=sys.maxsize, max_str=sys.maxsize)
        return cls(
            fully_qualified=False,
            include_traceback=False,
            label_classes=False,
            label_primitives=False,
            repr=r,
            style="repr",
        )

    @property
    def ellipsis(self) -> str:
        return self.repr.fillvalue

    @property
    def max_depth(self) -> int:
        """Maximum nesting depth."""
        return self.repr.maxlevel

    @property
    def max_items(self) -> int:
        """Maximum items number in repr (uses maxlist as canonical value)."""
        return self.repr.maxlist

    @property
    def max_str(self) -> int:
        """Maximum string length in repr (uses maxstring as canonical value)."""
        return self.repr.maxstring

max_depth property

Maximum nesting depth.

max_items property

Maximum items number in repr (uses maxlist as canonical value).

max_str property

Maximum string length in repr (uses maxstring as canonical value).

cli(max_depth=3, max_items=16, max_str=80) classmethod

Optimized for command-line interfaces.

Uses 'equal' style (key=value) and constrains output to typical terminal width.

Source code in c108/formatters.py
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
@classmethod
def cli(cls, max_depth: int = 3, max_items: int = 16, max_str: int = 80) -> Self:
    """
    Optimized for command-line interfaces.

    Uses 'equal' style (key=value) and constrains output to typical terminal width.
    """
    r = _repr_factory(max_depth=max_depth, max_items=max_items, max_str=max_str)
    return cls(
        fully_qualified=False,
        include_traceback=False,
        label_classes=False,
        label_primitives=False,
        repr=r,
        style="equal",
    )

compact(max_depth=2, max_items=6, max_str=32) classmethod

Concise output for readability.

Source code in c108/formatters.py
295
296
297
298
299
300
301
302
303
304
305
306
@classmethod
def compact(cls, max_depth: int = 2, max_items: int = 6, max_str: int = 32) -> Self:
    """Concise output for readability."""
    r = _repr_factory(max_depth=max_depth, max_items=max_items, max_str=max_str)
    return cls(
        fully_qualified=False,
        include_traceback=False,
        label_classes=False,
        label_primitives=False,
        repr=r,
        style="repr",
    )

debug(max_depth=6, max_items=256, max_str=1024) classmethod

Verbose output for debugging.

Source code in c108/formatters.py
308
309
310
311
312
313
314
315
316
317
318
319
@classmethod
def debug(cls, max_depth: int = 6, max_items: int = 256, max_str=1024) -> Self:
    """Verbose output for debugging."""
    r = _repr_factory(max_depth=max_depth, max_items=max_items, max_str=max_str)
    return cls(
        fully_qualified=False,
        include_traceback=True,
        label_classes=False,
        label_primitives=True,
        repr=r,
        style="repr",
    )

logging(max_depth=3, max_items=16, max_str=128) classmethod

Balanced output for production logging.

Source code in c108/formatters.py
321
322
323
324
325
326
327
328
329
330
331
332
@classmethod
def logging(cls, max_depth: int = 3, max_items: int = 16, max_str: int = 128) -> Self:
    """Balanced output for production logging."""
    r = _repr_factory(max_depth=max_depth, max_items=max_items, max_str=max_str)
    return cls(
        fully_qualified=False,
        include_traceback=False,
        label_classes=False,
        label_primitives=False,
        repr=r,
        style="repr",
    )

merge(*, fully_qualified=UNSET, include_traceback=UNSET, label_classes=UNSET, label_primitives=UNSET, max_depth=UNSET, max_items=UNSET, max_str=UNSET, repr=UNSET, style=UNSET)

Create a new FmtOptions instance with selectively updated fields.

If a parameter value is UNSET, no update is applied to the field.

Parameters:

Name Type Description Default
fully_qualified bool

Whether to include FQN type names.

UNSET
include_traceback bool

Include exception traceback info.

UNSET
label_classes bool

Whether to add 'class' prefix for types (e.g. vs ).

UNSET
label_primitives bool

Whether to show type labels for int, float, str, bytes, etc.

UNSET
max_depth int

Maximum depth for nested structures; overrides repr.maxlevel.

UNSET
max_items int

Maximum number of elements in collections; overrides repr config.

UNSET
max_str int

The maximum length for strings and other representations; overrides repr config.

UNSET
repr Repr

reprlib.Repr instance controlling collection formatting and limits.

UNSET
style Style

Display style for type-value pairs: "angle" | "colon" | "equal" | "paren" | "repr" | "unicode-angle"

UNSET

Returns:

Type Description
Self

New FmtOptions instance with merged configuration

Source code in c108/formatters.py
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
def merge(
    self,
    *,
    fully_qualified: bool = UNSET,
    include_traceback: bool = UNSET,
    label_classes: bool = UNSET,
    label_primitives: bool = UNSET,
    max_depth: int = UNSET,
    max_items: int = UNSET,
    max_str: int = UNSET,
    repr: reprlib.Repr = UNSET,
    style: Style = UNSET,
) -> Self:
    """
    Create a new FmtOptions instance with selectively updated fields.

    If a parameter value is UNSET, no update is applied to the field.

    Args:
        fully_qualified: Whether to include FQN type names.
        include_traceback: Include exception traceback info.
        label_classes: Whether to add 'class' prefix for types (e.g. <class 'int'> vs <int>).
        label_primitives: Whether to show type labels for int, float, str, bytes, etc.
        max_depth: Maximum depth for nested structures; overrides repr.maxlevel.
        max_items: Maximum number of elements in collections; overrides repr config.
        max_str (int): The maximum length for strings and other representations; overrides repr config.
        repr: reprlib.Repr instance controlling collection formatting and limits.
        style: Display style for type-value pairs: "angle" | "colon" | "equal" | "paren" | "repr" | "unicode-angle"

    Returns:
        New FmtOptions instance with merged configuration
    """
    fully_qualified = ifnotunset(fully_qualified, default=self.fully_qualified)
    include_traceback = ifnotunset(include_traceback, default=self.include_traceback)
    label_classes = ifnotunset(label_classes, default=self.label_classes)
    label_primitives = ifnotunset(label_primitives, default=self.label_primitives)

    if not isinstance(repr, (reprlib.Repr, type(None), type(UNSET))):
        raise ValueError(f"reprlib.Repr or None expected, but got {type(repr).__name__}")

    r = ifnotunset(repr, default=self.repr)
    r = _repr_factory(max_depth=max_depth, max_items=max_items, max_str=max_str, default=r)

    style = ifnotunset(style, default=self.style)

    return FmtOptions(
        fully_qualified=fully_qualified,
        include_traceback=include_traceback,
        label_classes=label_classes,
        label_primitives=label_primitives,
        repr=r,
        style=style,
    )

reprlib(max_depth=None, max_items=None, max_str=None) classmethod

Mimics the default behavior of the standard library 'reprlib' module.

By default enforces standard safety limits (depth=6, items=6, str=30) generally used by 'reprlib.Repr' to prevent large output.

Source code in c108/formatters.py
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
@classmethod
def reprlib(cls, max_depth: int = None, max_items: int = None, max_str: int = None) -> Self:
    """
    Mimics the default behavior of the standard library 'reprlib' module.

    By default enforces standard safety limits (depth=6, items=6, str=30) generally used
    by 'reprlib.Repr' to prevent large output.
    """
    # Get reprlib defaults: maxlevel=6, maxlist/tuple/dict=6, maxstring=30
    r_reprlib = reprlib.Repr()

    # Override defaults if provided params are int
    repr_ = _repr_factory(
        max_depth=max_depth, max_items=max_items, max_str=max_str, default=r_reprlib
    )

    return cls(
        fully_qualified=False,
        include_traceback=False,
        label_classes=False,
        label_primitives=False,
        repr=repr_,
        style="repr",
    )

stdlib() classmethod

Mimics the stdlib 'repr()' behavior with unlimited output.

Removes truncation limits (sets them to maxsize) and ensures 'repr' style. Use with caution on large structures.

Source code in c108/formatters.py
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
@classmethod
def stdlib(cls) -> Self:
    """
    Mimics the stdlib 'repr()' behavior with unlimited output.

    Removes truncation limits (sets them to maxsize) and ensures 'repr' style.
    Use with caution on large structures.
    """
    r = _repr_factory(max_depth=sys.maxsize, max_items=sys.maxsize, max_str=sys.maxsize)
    return cls(
        fully_qualified=False,
        include_traceback=False,
        label_classes=False,
        label_primitives=False,
        repr=r,
        style="repr",
    )

configure(*, fully_qualified=UNSET, include_traceback=UNSET, label_classes=UNSET, label_primitives=UNSET, max_depth=UNSET, max_items=UNSET, max_str=UNSET, repr=UNSET, style=UNSET, preset=None)

Configure default formatting options for all fmt_* functions.

Sets module-level defaults that apply when opts=None is passed to any fmt_* function. Call without arguments to set defaults from FmtOptions().

Parameters:

Name Type Description Default
fully_qualified bool

Whether to include FQN type names.

UNSET
include_traceback bool

Include exception traceback info.

UNSET
label_primitives bool

Whether to show type labels for primitives.

UNSET
max_depth int

Maximum depth for nested structures.

UNSET
max_items int

Maximum number of elements in collections.

UNSET
max_str int

Maximum length for string representations.

UNSET
repr Repr

Custom reprlib.Repr instance.

UNSET
style Style

Display style for type-value pairs.

UNSET
preset Preset | None

Configuration mode: - None: Start from the current preset, apply params; start from factory defaults if current not set. - "cli": optimize for command-line interfaces. - "compact": concise output for readability. - "debug": verbose output for debugging. - "logging": balanced output for production logging. - "repr": use safe, truncated defaults (standard 'reprlib' behavior). - "stdlib": use unlimited output (standard 'repr()' behavior).

None

Examples:

>>> # Configure once at application startup
>>> configure(preset="debug", style="angle")
>>> fmt_value(42)
'<int: 42>'
>>> # Incremental update (merge with current preset)
>>> configure(max_depth=5)  # Override max_depth only
>>> # Explicit reset to reprlib defaults
>>> configure(preset="reprlib")
Source code in c108/formatters.py
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
def configure(
    *,
    fully_qualified: bool = UNSET,
    include_traceback: bool = UNSET,
    label_classes: bool = UNSET,
    label_primitives: bool = UNSET,
    max_depth: int = UNSET,
    max_items: int = UNSET,
    max_str: int = UNSET,
    repr: reprlib.Repr = UNSET,
    style: Style = UNSET,
    preset: Preset | None = None,
) -> None:
    """
    Configure default formatting options for all fmt_* functions.

    Sets module-level defaults that apply when opts=None is passed to any
    fmt_* function. Call without arguments to set defaults from FmtOptions().

    Args:
        fully_qualified: Whether to include FQN type names.
        include_traceback: Include exception traceback info.
        label_primitives: Whether to show type labels for primitives.
        max_depth: Maximum depth for nested structures.
        max_items: Maximum number of elements in collections.
        max_str: Maximum length for string representations.
        repr: Custom reprlib.Repr instance.
        style: Display style for type-value pairs.
        preset: Configuration mode:
            - None: Start from the current preset, apply params; start from factory defaults if current not set.
            - "cli": optimize for command-line interfaces.
            - "compact": concise output for readability.
            - "debug": verbose output for debugging.
            - "logging": balanced output for production logging.
            - "repr": use safe, truncated defaults (standard 'reprlib' behavior).
            - "stdlib": use unlimited output (standard 'repr()' behavior).

    Examples:
        >>> # Configure once at application startup
        >>> configure(preset="debug", style="angle")
        >>> fmt_value(42)
        '<int: 42>'

        >>> # Incremental update (merge with current preset)
        >>> configure(max_depth=5)  # Override max_depth only

        >>> # Explicit reset to reprlib defaults
        >>> configure(preset="reprlib")
    """
    global _default_fmt_options

    # Determine options
    if preset is None:
        # Should get preset from module-level default or create from factory defaults
        opts = (
            _default_fmt_options if isinstance(_default_fmt_options, FmtOptions) else FmtOptions()
        )
    elif preset == "cli":
        opts = FmtOptions.cli()
    elif preset == "compact":
        opts = FmtOptions.compact()
    elif preset == "debug":
        opts = FmtOptions.debug()
    elif preset == "logging":
        opts = FmtOptions.logging()
    elif preset == "repr":
        opts = FmtOptions.reprlib()
    elif preset == "stdlib":
        opts = FmtOptions.stdlib()
    else:
        # Fallback to factory defaults
        opts = FmtOptions()

    # Merge with provided options
    _default_fmt_options = opts.merge(
        fully_qualified=fully_qualified,
        include_traceback=include_traceback,
        label_classes=label_classes,
        label_primitives=label_primitives,
        max_depth=max_depth,
        max_items=max_items,
        max_str=max_str,
        repr=repr,
        style=style,
    )

fmt_any(obj, *, opts=None)

Format any object for debugging, logging, and exception messages.

Main entry point for formatting arbitrary Python objects with robust handling of edge cases like broken repr, recursive objects, and chained exceptions. Intelligently routes to specialized formatters based on object type while maintaining consistent styling and graceful error handling.

Parameters:

Name Type Description Default
obj Any

Any Python object to format.

required
opts FmtOptions | None

Formatting options controlling style, truncation, and type labeling. If None, uses default FmtOptions().

None

Returns:

Type Description
str

Formatted string with appropriate structure for the object type.

Dispatch Logic
  • BaseException → fmt_exception() (with optional traceback)
  • Mapping → fmt_mapping() (dicts, OrderedDict, etc.)
  • Sequence (non-text) → fmt_sequence() (lists, tuples, etc.)
  • Set → fmt_set()
  • Type/class → fmt_type()
  • All others → fmt_value() (atomic values, custom objects)

Examples:

>>> configure(preset="compact")
>>>
>>> fmt_any([1, 2, 3])
'[1, 2, 3]'
>>> fmt_any(42, opts=FmtOptions(label_primitives=True, style="angle"))
'<int: 42>'
>>> fmt_any({"key": "value"}, opts=FmtOptions(label_primitives=True, style="angle"))
"{<str: 'key'>: <str: 'value'>}"
>>> fmt_any(ValueError("bad input"))
"ValueError('bad input')"
Notes
  • Text-like sequences (str, bytes) are treated as atomic values
  • Safe for unknown object types in error handling contexts
  • Preserves specialized behavior of each formatter
See Also

fmt_exception, fmt_mapping, fmt_sequence, fmt_value: Specialized formatters

Source code in c108/formatters.py
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
def fmt_any(obj: Any, *, opts: FmtOptions | None = None) -> str:
    """Format any object for debugging, logging, and exception messages.

    Main entry point for formatting arbitrary Python objects with robust handling
    of edge cases like broken __repr__, recursive objects, and chained exceptions.
    Intelligently routes to specialized formatters based on object type while
    maintaining consistent styling and graceful error handling.

    Args:
        obj: Any Python object to format.
        opts: Formatting options controlling style, truncation, and type labeling.
            If None, uses default FmtOptions().

    Returns:
        Formatted string with appropriate structure for the object type.

    Dispatch Logic:
        - BaseException → fmt_exception() (with optional traceback)
        - Mapping → fmt_mapping() (dicts, OrderedDict, etc.)
        - Sequence (non-text) → fmt_sequence() (lists, tuples, etc.)
        - Set → fmt_set()
        - Type/class → fmt_type()
        - All others → fmt_value() (atomic values, custom objects)

    Examples:
        >>> configure(preset="compact")
        >>>
        >>> fmt_any([1, 2, 3])
        '[1, 2, 3]'

        >>> fmt_any(42, opts=FmtOptions(label_primitives=True, style="angle"))
        '<int: 42>'

        >>> fmt_any({"key": "value"}, opts=FmtOptions(label_primitives=True, style="angle"))
        "{<str: 'key'>: <str: 'value'>}"

        >>> fmt_any(ValueError("bad input"))
        "ValueError('bad input')"

    Notes:
        - Text-like sequences (str, bytes) are treated as atomic values
        - Safe for unknown object types in error handling contexts
        - Preserves specialized behavior of each formatter

    See Also:
        fmt_exception, fmt_mapping, fmt_sequence, fmt_value: Specialized formatters
    """
    # Provide valid FmtOptions instance
    opts = _fmt_opts(opts)

    # Priority 0: Primitives use fmt_value
    if type(obj) in PRIMITIVE_TYPES:
        return fmt_value(obj, opts=opts)

    # Priority 1: Exceptions get special handling
    if _is_exception_instance(obj):
        return fmt_exception(obj, opts=opts)

    # Priority 2: Check if obj is a type/class
    if isinstance(obj, type):
        return _fmt_class(obj, opts=opts)

    # Priority 3: Mappings (dict, OrderedDict, etc.)
    if isinstance(obj, abc.Mapping):
        return fmt_mapping(obj, opts=opts)

    # Priority 4: Sets
    if isinstance(obj, abc.Set):
        return fmt_set(obj, opts=opts)

    # Priority 5: Sequences (but not text-like ones)
    if isinstance(obj, abc.Sequence) and not _is_textual(obj):
        return fmt_sequence(obj, opts=opts)

    # Priority 6: Everything else (atomic values, text, custom objects)
    return fmt_value(obj, opts=opts)

fmt_exception(exc, *, opts=None)

Format exceptions representation with automatic fallback for non-exception types.

Provides robust formatting of exception objects with type-message pairs, optional traceback location info, and consistent styling. Non-exception inputs are gracefully handled by delegating to fmt_value, making this function safe to use in error contexts where object types may be uncertain.

Parameters:

Name Type Description Default
exc Any

The object to format. Exceptions are formatted as type-message pairs, while all other types delegate to fmt_value.

required
style

Display style - "angle", "equal", "colon", etc.

required
max_repr

Maximum length before truncation (only applies to message, not type).

required
include_traceback

Whether to include traceback location info (exceptions only).

required
ellipsis

Custom truncation marker (defaults based on style).

required

Returns:

Type Description
str

Formatted string. For exceptions: "" with type always preserved.

str

For non-exceptions: delegated to fmt_value.

Notes
  • Non-exception types automatically fall back to fmt_value (no exceptions raised)
  • Exception type name is NEVER truncated for reliability
  • Only the message portion is subject to max_repr truncation
  • Broken str methods are handled with fallback formatting
  • Traceback info shows function name and line number when requested
  • Handles edge cases: empty messages, chained exceptions, broken str

Examples:

>>> # Standard exception formatting
>>> fmt_exception(ValueError("bad input"))
"ValueError('bad input')"
>>> # Empty message
>>> fmt_exception(RuntimeError())
'RuntimeError()'
>>> # Message truncation (type preserved)
>>> configure(max_str=35)
>>> fmt_exception(ValueError("very long message"*3))
"ValueError('ver...y long message')"
>>> # Automatic fallback for non-exceptions (no error)
>>> fmt_exception(52)
'52'
See Also

fmt_value: The underlying formatter for non-exception types. fmt_any: Main dispatcher that routes exceptions to this function.

Source code in c108/formatters.py
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
def fmt_exception(
    exc: Any,
    *,
    opts: FmtOptions | None = None,
) -> str:
    """Format exceptions representation with automatic fallback for non-exception types.

    Provides robust formatting of exception objects with type-message pairs,
    optional traceback location info, and consistent styling. Non-exception
    inputs are gracefully handled by delegating to `fmt_value`, making this
    function safe to use in error contexts where object types may be uncertain.

    Args:
        exc: The object to format. Exceptions are formatted as type-message pairs,
            while all other types delegate to `fmt_value`.
        style: Display style - "angle", "equal", "colon", etc.
        max_repr: Maximum length before truncation (only applies to message, not type).
        include_traceback: Whether to include traceback location info (exceptions only).
        ellipsis: Custom truncation marker (defaults based on style).

    Returns:
        Formatted string. For exceptions: "<ValueError: message>" with type always preserved.
        For non-exceptions: delegated to `fmt_value`.

    Notes:
        - Non-exception types automatically fall back to `fmt_value` (no exceptions raised)
        - Exception type name is NEVER truncated for reliability
        - Only the message portion is subject to max_repr truncation
        - Broken __str__ methods are handled with fallback formatting
        - Traceback info shows function name and line number when requested
        - Handles edge cases: empty messages, chained exceptions, broken __str__

    Examples:
        >>> # Standard exception formatting
        >>> fmt_exception(ValueError("bad input"))
        "ValueError('bad input')"

        >>> # Empty message
        >>> fmt_exception(RuntimeError())
        'RuntimeError()'

        >>> # Message truncation (type preserved)
        >>> configure(max_str=35)
        >>> fmt_exception(ValueError("very long message"*3))
        "ValueError('ver...y long message')"

        >>> # Automatic fallback for non-exceptions (no error)
        >>> fmt_exception(52)
        '52'

    See Also:
        fmt_value: The underlying formatter for non-exception types.
        fmt_any: Main dispatcher that routes exceptions to this function.
    """

    # Provide valid FmtOptions instance
    opts = _fmt_opts(opts)

    if _is_exception_instance(exc):
        # Instance should follow fmt_value formatting
        repr_ = fmt_value(exc, opts=opts)
    elif _is_exception_class(exc):
        # Class should follow fmt_type formatting
        repr_ = fmt_type(exc, opts=opts)
    else:
        # Fail-safe fallback to fmt_value otherwise
        return fmt_value(exc, opts=opts)

    # Add traceback location optionally
    repr_ += _fmt_exception_location(exc) if opts.include_traceback else ""

    return repr_

fmt_mapping(mp, *, opts=None)

Format mapping for display with automatic fallback for non-mapping types.

Formats mapping objects (dicts, OrderedDict, defaultdict, etc.) for debugging or logging. Non-mapping inputs are gracefully handled by delegating to fmt_value, making this function safe to use in error contexts where object types may be uncertain.

Parameters:

Name Type Description Default
mp Any

The object to format. Mappings are formatted as {key: value} pairs, while all other types delegate to fmt_value.

required
opts FmtOptions | None

Formatting options controlling style, truncation, and type labeling.

None

Returns:

Type Description
str

Formatted string like "{: ...}" (dict) or

str

"OrderedDict({: })" (custom mapping). Empty dict

str

formats as "{}".

Notes
  • Non-mapping types automatically fall back to fmt_value (no exceptions)
  • Built-in types use standard braces: {} for dict
  • Custom types show with type name wrapper: OrderedDict({...})
  • For sized mappings over max_items, shows head...only pattern (dicts preserve insertion order)
  • Nested sequences/mappings are recursively formatted up to max_depth levels
  • Broken repr methods in keys/values are handled gracefully
  • Preserves insertion order for modern dicts

Examples:

>>> configure(label_primitives=True, style="angle")
>>> fmt_mapping({"name": "Alice", "age": 30})
"{<str: 'name'>: <str: 'Alice'>, <str: 'age'>: <int: 30>}"
>>> configure(max_items=3)
>>> fmt_mapping({i: i**2 for i in range(10)})
'{<int: 0>: <int: 0>, <int: 1>: <int: 1>, <int: 2>: <int: 4>...}'
>>> from collections import OrderedDict
>>> fmt_mapping(OrderedDict([('x', 1), ('y', 2)]))
"OrderedDict({<str: 'x'>: <int: 1>, <str: 'y'>: <int: 2>})"
>>> fmt_mapping({})
'{}'
>>> fmt_mapping("a simple string")
"<str: 'a simple string'>"
>>> fmt_mapping(42)
'<int: 42>'
See Also

fmt_any: Format object based on its type. fmt_sequence: Format sequences with elementwise formatting and nesting support. fmt_set: Format sets with elementwise formatting and nesting support. fmt_repr: Format object using reprlib with custom options. fmt_value: Format individual elements with the robustness guarantees.

Source code in c108/formatters.py
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
def fmt_mapping(
    mp: Any,
    *,
    opts: FmtOptions | None = None,
) -> str:
    """Format mapping for display with automatic fallback for non-mapping types.

    Formats mapping objects (dicts, OrderedDict, defaultdict, etc.) for debugging
    or logging. Non-mapping inputs are gracefully handled by delegating to `fmt_value`,
    making this function safe to use in error contexts where object types may be
    uncertain.

    Args:
        mp: The object to format. Mappings are formatted as `{key: value}`
            pairs, while all other types delegate to `fmt_value`.
        opts: Formatting options controlling style, truncation, and type labeling.

    Returns:
        Formatted string like "{<str: 'name'>: <str: 'Alice'>...}" (dict) or
        "OrderedDict({<str: 'x'>: <int: 1>})" (custom mapping). Empty dict
        formats as "{}".

    Notes:
        - Non-mapping types automatically fall back to `fmt_value` (no exceptions)
        - Built-in types use standard braces: {} for dict
        - Custom types show with type name wrapper: OrderedDict({...})
        - For sized mappings over max_items, shows head...only pattern (dicts preserve insertion order)
        - Nested sequences/mappings are recursively formatted up to max_depth levels
        - Broken __repr__ methods in keys/values are handled gracefully
        - Preserves insertion order for modern dicts

    Examples:
        >>> configure(label_primitives=True, style="angle")
        >>> fmt_mapping({"name": "Alice", "age": 30})
        "{<str: 'name'>: <str: 'Alice'>, <str: 'age'>: <int: 30>}"

        >>> configure(max_items=3)
        >>> fmt_mapping({i: i**2 for i in range(10)})
        '{<int: 0>: <int: 0>, <int: 1>: <int: 1>, <int: 2>: <int: 4>...}'

        >>> from collections import OrderedDict
        >>> fmt_mapping(OrderedDict([('x', 1), ('y', 2)]))
        "OrderedDict({<str: 'x'>: <int: 1>, <str: 'y'>: <int: 2>})"

        >>> fmt_mapping({})
        '{}'

        >>> fmt_mapping("a simple string")
        "<str: 'a simple string'>"

        >>> fmt_mapping(42)
        '<int: 42>'

    See Also:
        fmt_any: Format object based on its type.
        fmt_sequence: Format sequences with elementwise formatting and nesting support.
        fmt_set: Format sets with elementwise formatting and nesting support.
        fmt_repr: Format object using reprlib with custom options.
        fmt_value: Format individual elements with the robustness guarantees.
    """
    # Process Mapping, delegate to fmt_value all the rest
    if not isinstance(mp, abc.Mapping):
        return fmt_value(mp, opts=opts)

    # Provide valid FmtOptions instance
    opts = _fmt_opts(opts)

    # Determine if this is a built-in or custom type
    mp_type = type(mp)
    if mp_type is dict:
        return _fmt_map_builtin(mp, opts)
    else:
        return _fmt_map_custom(mp, mp_type, opts)

fmt_repr(obj, *, opts=None)

Format the object's representation safely and robustly.

A wrapper around repr() that guarantees: 1. No crashes (catches exceptions in broken repr methods). 2. Syntactic correctness (restores quotes/brackets even when truncated). 3. Configurable limits (via opts).

Parameters:

Name Type Description Default
obj Any

The object to represent.

required
opts FmtOptions | None

Formatting options. If None, uses defaults.

None

Returns:

Type Description
str

A string resembling the standard repr(), but safe and truncated.

Source code in c108/formatters.py
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
def fmt_repr(obj: Any, *, opts: FmtOptions | None = None) -> str:
    """
    Format the object's representation safely and robustly.

    A wrapper around repr() that guarantees:
        1. No crashes (catches exceptions in broken __repr__ methods).
        2. Syntactic correctness (restores quotes/brackets even when truncated).
        3. Configurable limits (via opts).

    Args:
        obj: The object to represent.
        opts: Formatting options. If None, uses defaults.

    Returns:
        A string resembling the standard repr(), but safe and truncated.
    """
    # Provide valid FmtOptions instance
    opts = _fmt_opts(opts)

    # Get formatted representation (fail-safe)
    return _fmt_repr(obj, opts)

fmt_sequence(seq, *, opts=None)

Format sequence for display with automatic fallback for non-iterable types.

Formats iterables (lists, tuples, sets, generators) for debugging or logging. Non-iterable inputs and text-like sequences (str, bytes, bytearray) are gracefully handled by delegating to fmt_value, making this function safe to use in error contexts where object types may be uncertain.

Parameters:

Name Type Description Default
seq Iterable[Any]

The object to format. Iterables are formatted elementwise, while non-iterables and text types delegate to fmt_value.

required
opts FmtOptions | None

Formatting options controlling style, truncation, and type labeling.

None

Returns:

Type Description
str

Formatted string like "[, ...]" (list) or

str

"(,)" (singleton tuple). Custom types show as "CustomList([...])".

Notes
  • Non-iterable types automatically fall back to fmt_value (no exceptions)
  • str/bytes/bytearray are treated as atomic (not decomposed into characters)
  • Built-in types use standard brackets: [] for lists, () for tuples
  • Custom types show with type name wrapper: CustomList([...])
  • For sized sequences over max_items, shows head...tail pattern (reprlib-style)
  • For generators/iterators, shows head...only pattern (can't peek tail)
  • Nested sequences/mappings are recursively formatted up to max_depth levels
  • Singleton tuples show trailing comma for Python literal accuracy
  • Broken repr methods in elements are handled gracefully

Examples:

>>> configure(label_primitives=True, max_items=6, style="angle")
>>>
>>> fmt_sequence([1, "hello", [2, 3]])
"[<int: 1>, <str: 'hello'>, [<int: 2>, <int: 3>]]"
>>> fmt_sequence([i for i in range(100)])
'[<int: 0>, <int: 1>, <int: 2>, ..., <int: 97>, <int: 98>, <int: 99>]'
>>> class CustomList(list): pass
>>> fmt_sequence(CustomList([1, 2, 3]))
'CustomList([<int: 1>, <int: 2>, <int: 3>])'
>>> fmt_sequence("text")
"<str: 'text'>"
>>> fmt_sequence(42)
'<int: 42>'
See Also

fmt_any: Format object based on its type. fmt_mapping: Format mappings with element-wise values formatting and nesting support. fmt_repr: Format object using reprlib with custom options. fmt_set: Format sets with elementwise formatting and nesting support. fmt_value: Format individual elements with the robustness guarantees.

Source code in c108/formatters.py
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
def fmt_sequence(
    seq: Iterable[Any],
    *,
    opts: FmtOptions | None = None,
) -> str:
    """Format sequence for display with automatic fallback for non-iterable types.

    Formats iterables (lists, tuples, sets, generators) for debugging or logging.
    Non-iterable inputs and text-like sequences (str, bytes, bytearray) are
    gracefully handled by delegating to `fmt_value`, making this function safe
    to use in error contexts where object types may be uncertain.

    Args:
        seq: The object to format. Iterables are formatted elementwise,
            while non-iterables and text types delegate to `fmt_value`.
        opts: Formatting options controlling style, truncation, and type labeling.

    Returns:
        Formatted string like "[<int: 1>, <str: 'hello'>...]" (list) or
        "(<int: 1>,)" (singleton tuple). Custom types show as "CustomList([...])".

    Notes:
        - Non-iterable types automatically fall back to `fmt_value` (no exceptions)
        - str/bytes/bytearray are treated as atomic (not decomposed into characters)
        - Built-in types use standard brackets: [] for lists, () for tuples
        - Custom types show with type name wrapper: CustomList([...])
        - For sized sequences over max_items, shows head...tail pattern (reprlib-style)
        - For generators/iterators, shows head...only pattern (can't peek tail)
        - Nested sequences/mappings are recursively formatted up to max_depth levels
        - Singleton tuples show trailing comma for Python literal accuracy
        - Broken __repr__ methods in elements are handled gracefully

    Examples:
        >>> configure(label_primitives=True, max_items=6, style="angle")
        >>>
        >>> fmt_sequence([1, "hello", [2, 3]])
        "[<int: 1>, <str: 'hello'>, [<int: 2>, <int: 3>]]"

        >>> fmt_sequence([i for i in range(100)])
        '[<int: 0>, <int: 1>, <int: 2>, ..., <int: 97>, <int: 98>, <int: 99>]'

        >>> class CustomList(list): pass
        >>> fmt_sequence(CustomList([1, 2, 3]))
        'CustomList([<int: 1>, <int: 2>, <int: 3>])'

        >>> fmt_sequence("text")
        "<str: 'text'>"

        >>> fmt_sequence(42)
        '<int: 42>'

    See Also:
        fmt_any: Format object based on its type.
        fmt_mapping: Format mappings with element-wise values formatting and nesting support.
        fmt_repr: Format object using reprlib with custom options.
        fmt_set: Format sets with elementwise formatting and nesting support.
        fmt_value: Format individual elements with the robustness guarantees.
    """
    # Process Iterable, delegate to fmt_value all the rest
    if not isinstance(seq, abc.Iterable):
        return fmt_value(seq, opts=opts)

    if _is_textual(seq):
        # Treat text-like as a scalar value, not a sequence of characters
        return fmt_value(seq, opts=opts)

    # Provide valid FmtOptions instance
    opts = _fmt_opts(opts)

    # Determine if this is a built-in or custom type
    seq_type = type(seq)
    if seq_type in (list, tuple, set, frozenset, range, collections.deque):
        return _fmt_seq_builtin(seq, opts)
    else:
        return _fmt_seq_custom(seq, seq_type, opts)

fmt_set(st, *, opts=None)

Format set for display with automatic fallback for non-set types.

Formats set-based objects (set, frozenset, custom set types) for debugging or logging. Non-set inputs are gracefully handled by delegating to fmt_value, making this function safe to use in error contexts where object types may be uncertain.

Parameters:

Name Type Description Default
st AbstractSet[Any]

The object to format. Sets are formatted elementwise, while non-sets delegate to fmt_value.

required
opts FmtOptions | None

Formatting options controlling style, truncation, and type labeling.

None

Returns:

Type Description
str

Formatted string like "{, ...}" (set) or

str

"frozenset({, })" (frozenset). Custom types show as

str

"CustomSet({...})".

Notes
  • Non-set types automatically fall back to fmt_value (no exceptions)
  • Built-in types use standard braces: {} for sets, frozenset({}) wrapper
  • Custom types show with type name wrapper: CustomSet({...})
  • For sized sets over max_items, shows head...only pattern (sets are unordered)
  • Set elements are shown in iteration order (insertion order for modern Python)
  • Nested sequences/mappings/sets are recursively formatted up to max_depth levels
  • Broken repr methods in elements are handled gracefully
  • Empty sets format as "set()" to avoid confusion with empty dict "{}"

Examples:

>>> configure(label_primitives=True, style="angle", max_items=3)
>>>
>>> fmt_set({"hello"})
"{<str: 'hello'>}"
>>> fmt_set(frozenset(range(100)))
'frozenset({<int: 0>, <int: 1>, <int: 2>...})'
>>> class CustomSet(set): pass
>>> fmt_set(CustomSet({1, 2, 3}))
'CustomSet({<int: 1>, <int: 2>, <int: 3>})'
>>> fmt_set(set())
'set()'
>>> # Non-set types
>>> fmt_set("text")
"<str: 'text'>"
>>> fmt_set(42)
'<int: 42>'
See Also

fmt_any: Format object based on its type. fmt_mapping: Format mappings with element-wise values formatting and nesting support. fmt_sequence: Format sequences with elementwise formatting and nesting support. fmt_repr: Format object using reprlib with custom options. fmt_value: Format individual elements with the robustness guarantees.

Source code in c108/formatters.py
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
def fmt_set(
    st: AbstractSet[Any],
    *,
    opts: FmtOptions | None = None,
) -> str:
    """Format set for display with automatic fallback for non-set types.

    Formats set-based objects (set, frozenset, custom set types) for debugging
    or logging. Non-set inputs are gracefully handled by delegating to `fmt_value`,
    making this function safe to use in error contexts where object types may be
    uncertain.

    Args:
        st: The object to format. Sets are formatted elementwise, while non-sets
            delegate to `fmt_value`.
        opts: Formatting options controlling style, truncation, and type labeling.

    Returns:
        Formatted string like "{<int: 1>, <str: 'hello'>...}" (set) or
        "frozenset({<int: 1>, <int: 2>})" (frozenset). Custom types show as
        "CustomSet({...})".

    Notes:
        - Non-set types automatically fall back to `fmt_value` (no exceptions)
        - Built-in types use standard braces: {} for sets, frozenset({}) wrapper
        - Custom types show with type name wrapper: CustomSet({...})
        - For sized sets over max_items, shows head...only pattern (sets are unordered)
        - Set elements are shown in iteration order (insertion order for modern Python)
        - Nested sequences/mappings/sets are recursively formatted up to max_depth levels
        - Broken __repr__ methods in elements are handled gracefully
        - Empty sets format as "set()" to avoid confusion with empty dict "{}"

    Examples:
        >>> configure(label_primitives=True, style="angle", max_items=3)
        >>>
        >>> fmt_set({"hello"})
        "{<str: 'hello'>}"

        >>> fmt_set(frozenset(range(100)))
        'frozenset({<int: 0>, <int: 1>, <int: 2>...})'

        >>> class CustomSet(set): pass
        >>> fmt_set(CustomSet({1, 2, 3}))
        'CustomSet({<int: 1>, <int: 2>, <int: 3>})'

        >>> fmt_set(set())
        'set()'

        >>> # Non-set types

        >>> fmt_set("text")
        "<str: 'text'>"

        >>> fmt_set(42)
        '<int: 42>'

    See Also:
        fmt_any: Format object based on its type.
        fmt_mapping: Format mappings with element-wise values formatting and nesting support.
        fmt_sequence: Format sequences with elementwise formatting and nesting support.
        fmt_repr: Format object using reprlib with custom options.
        fmt_value: Format individual elements with the robustness guarantees.
    """
    # Process Set, delegate to fmt_value all the rest
    if not isinstance(st, abc.Set):
        return fmt_value(st, opts=opts)

    # Provide valid FmtOptions instance
    opts = _fmt_opts(opts)

    # Determine if this is a built-in or custom type
    st_type = type(st)
    if st_type in (set, frozenset):
        return _fmt_set_builtin(st, opts)
    else:
        return _fmt_set_custom(st, st_type, opts)

fmt_type(obj, *, opts=None)

Format type information for debugging, logging, and exception messages.

Provides consistent formatting of type information for both type objects and instances. Complements the other fmt_* functions by focusing specifically on type display with optional module qualification and the same robust error handling.

Parameters:

Name Type Description Default
obj Any

Any Python object or type to extract type information from.

required
opts FmtOptions | None

Formatting options (style, max_repr, ellipsis, fully_qualified).

None

Returns:

Type Description
str

Formatted type string like "" for instances or "" for types.

Logic
  • If obj is an instance → format as "", "", etc.
  • If obj is a type object → format as "", etc. when label_classes is True; format as , etc otherwise
  • Module qualification controlled by fully_qualified parameter
  • Graceful handling of broken name attributes

Examples:

>>> configure(preset="reprlib", label_classes=True)
>>> fmt_type(42)
'<int>'
>>> fmt_type(int)
"<class 'int'>"
>>> fmt_type(ValueError("test"))
'<ValueError>'
>>> configure(style="unicode-angle")
>>>
>>> class CustomClass:
...     pass
>>> fmt_type(CustomClass())
'⟨CustomClass⟩'
>>> fmt_type(CustomClass)
'⟨class: CustomClass⟩'
Notes
  • Consistent with other fmt_* functions in style and error handling
  • Type name truncation preserves readability in error contexts
  • Module information helps distinguish between similarly named types
Source code in c108/formatters.py
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
def fmt_type(obj: Any, *, opts: FmtOptions | None = None) -> str:
    """Format type information for debugging, logging, and exception messages.

    Provides consistent formatting of type information for both type objects and
    instances. Complements the other fmt_* functions by focusing specifically on
    type display with optional module qualification and the same robust error handling.

    Args:
        obj: Any Python object or type to extract type information from.
        opts: Formatting options (style, max_repr, ellipsis, fully_qualified).

    Returns:
        Formatted type string like "<int>" for instances or "<class int>" for types.

    Logic:
        - If obj is an instance → format as "<int>", "<str>", etc.
        - If obj is a type object → format as "<class: int>", etc. when label_classes is True;
          format as <int>, etc otherwise
        - Module qualification controlled by fully_qualified parameter
        - Graceful handling of broken __name__ attributes

    Examples:
        >>> configure(preset="reprlib", label_classes=True)

        >>> fmt_type(42)
        '<int>'

        >>> fmt_type(int)
        "<class 'int'>"

        >>> fmt_type(ValueError("test"))
        '<ValueError>'

        >>> configure(style="unicode-angle")
        >>>
        >>> class CustomClass:
        ...     pass

        >>> fmt_type(CustomClass())
        '⟨CustomClass⟩'

        >>> fmt_type(CustomClass)
        '⟨class: CustomClass⟩'

    Notes:
        - Consistent with other fmt_* functions in style and error handling
        - Type name truncation preserves readability in error contexts
        - Module information helps distinguish between similarly named types
    """

    # Provide valid FmtOptions instance
    opts = _fmt_opts(opts)

    # Check if obj is a type/class
    if isinstance(obj, type):
        return _fmt_class(obj, opts=opts)

    # Get type name with robust edge cases
    type_name = class_name(
        obj, fully_qualified=opts.fully_qualified, fully_qualified_builtins=False, as_instance=False
    )

    # Format INSTANCE's type based on style
    style = opts.style or "repr"
    if style == "angle":
        return f"<{type_name}>"
    if style == "arrow":
        return type_name
    if style == "braces":
        return f"{{{type_name}}}"
    if style == "colon":
        return type_name
    if style == "equal":
        return type_name
    if style == "paren":
        # Special case: class(int) looks better than class int for paren style
        return type_name
    if style == "repr":
        return f"<{type_name}>"
    if style == "unicode-angle":
        return f"⟨{type_name}⟩"

    # Fallback to stdlib-like format
    return f"<{type_name}>"

fmt_value(obj, *, opts=None)

Format a single value as a type–value pair for debugging, logging, and exception messages.

Intended for robust display of arbitrary values in error contexts where safety and readability matter more than perfect fidelity. Handles edge cases like broken repr, recursive objects, and extremely long representations gracefully.

Parameters:

Name Type Description Default
obj Any

Any Python object to format.

required
opts FmtOptions | None

Formatting options controlling style, truncation, and type labeling. If None, uses default FmtOptions().

None

Returns:

Type Description
str

Formatted string like "int=42" (equal style) or "⟨str: 'hello'⟩" (unicode-angle style).

Notes
  • Truncation is handled by reprlib.Repr (respects maxstring, maxother, maxlevel).
  • ASCII style escapes inner ">" to avoid conflicts with wrapper brackets.
  • Broken repr methods are handled gracefully with fallback formatting.
  • Designed for exception messages and logs where robustness trumps perfect formatting.

Examples:

>>> configure(label_primitives=True, style="equal")
>>> fmt_value(42)
'int=42'
>>> configure(max_str=10)
>>> fmt_value("hello world")
"str='he...rld'"
>>> configure(preset="repr")
>>> fmt_value([1, 2, 3])
'[1, 2, 3]'
See Also

fmt_any: Format object based on its type. fmt_mapping: Format mappings with element-wise values formatting and nesting support. fmt_repr: Format object using reprlib with custom options. fmt_sequence: Format sequences/iterables elementwise with nesting support. fmt_set: Format sets with elementwise formatting and nesting support.

Source code in c108/formatters.py
 989
 990
 991
 992
 993
 994
 995
 996
 997
 998
 999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
def fmt_value(obj: Any, *, opts: FmtOptions | None = None) -> str:
    """
    Format a single value as a type–value pair for debugging, logging, and exception messages.

    Intended for robust display of arbitrary values in error contexts where safety and
    readability matter more than perfect fidelity. Handles edge cases like broken __repr__,
    recursive objects, and extremely long representations gracefully.

    Args:
        obj: Any Python object to format.
        opts: Formatting options controlling style, truncation, and type labeling.
            If None, uses default FmtOptions().

    Returns:
        Formatted string like "int=42" (equal style) or "⟨str: 'hello'⟩" (unicode-angle style).

    Notes:
        - Truncation is handled by reprlib.Repr (respects maxstring, maxother, maxlevel).
        - ASCII style escapes inner ">" to avoid conflicts with wrapper brackets.
        - Broken __repr__ methods are handled gracefully with fallback formatting.
        - Designed for exception messages and logs where robustness trumps perfect formatting.

    Examples:
        >>> configure(label_primitives=True, style="equal")

        >>> fmt_value(42)
        'int=42'

        >>> configure(max_str=10)
        >>> fmt_value("hello world")
        "str='he...rld'"

        >>> configure(preset="repr")
        >>> fmt_value([1, 2, 3])
        '[1, 2, 3]'

    See Also:
        fmt_any: Format object based on its type.
        fmt_mapping: Format mappings with element-wise values formatting and nesting support.
        fmt_repr: Format object using reprlib with custom options.
        fmt_sequence: Format sequences/iterables elementwise with nesting support.
        fmt_set: Format sets with elementwise formatting and nesting support.
    """
    # Provide valid FmtOptions instance
    opts = _fmt_opts(opts)

    # Check if obj is a type/class, use the same unified formatting
    # for fmt_value and fmt_type
    if isinstance(obj, type):
        # Should always label classes
        if opts.label_classes:
            # Short path if opts already label classes
            return _fmt_class(obj, opts=opts)
        else:
            # New opts instance if original opts do NOT label classes
            return _fmt_class(obj, opts=opts.merge(label_classes=True))

    # Generate repr using reprlib for consistent truncation and recursion handling
    repr_ = _fmt_repr(obj, opts)

    # Unlabeled primitives case: should show repr as is
    if (type(obj) in PRIMITIVE_TYPES) and not opts.label_primitives:
        return repr_

    # Formatted type-value pair case; if obj is `int` we should get `type` as its type_name
    type_name = _fmt_class_name(obj, fully_qualified=opts.fully_qualified)

    style = opts.style or "repr"

    # Should remove extra '<>' wrappers if any i.e. in case of
    # objects with broken or unimplemented __repr__
    start, end = _BROKEN_DELIMITERS
    clean_repr = repr_.removeprefix(start).removesuffix(end)
    full_repr = repr_

    if style == "angle":
        return f"<{type_name}: {clean_repr}>"
    if style == "arrow":
        return f"{type_name} -> {full_repr}"
    if style == "braces":
        return "{" + f"{type_name}: {clean_repr}" + "}"
    if style == "colon":
        return f"{type_name}: {full_repr}"
    if style == "equal":
        return f"{type_name}={full_repr}"
    if style == "paren":
        # If repr already starts with "ClassName(", use it as-is
        if clean_repr.startswith(f"{type_name}("):
            return clean_repr
        else:
            return f"{type_name}({clean_repr})"
    if style == "repr":
        return full_repr
    if style == "unicode-angle":
        return f"⟨{type_name}: {clean_repr}⟩"
    else:
        # Gracefull fallback if provided invalid style
        return repr_

get_options()

Get the current default formatting options.

Returns the global FmtOptions instance used by fmt_* functions when the 'opts' argument is omitted. This instance reflects the current configuration state.

Source code in c108/formatters.py
1089
1090
1091
1092
1093
1094
1095
1096
1097
def get_options() -> FmtOptions:
    """
    Get the current default formatting options.

    Returns the global FmtOptions instance used by fmt_* functions when
    the 'opts' argument is omitted. This instance reflects the current
    configuration state.
    """
    return _fmt_opts(_default_fmt_options)