Skip to content

Commit f337dd8

Browse files
committed
settings.print_toml_config(): Represent sets as sorted lists
In our --json output, we customize pydantic's JSON encoder to represent sets as sorted lists (thus yielding stable output). Do the same for when we generate TOML config output (which goes via a JSON encoding step, and thus is subject to the same issue with how sets are encoded). This was discovered while attempting to test how multiple 'pyenvs' were represented in our TOML output.
1 parent abf6fdc commit f337dd8

File tree

2 files changed

+29
-2
lines changed

2 files changed

+29
-2
lines changed

fawltydeps/settings.py

+5-2
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,13 @@
44
import logging
55
import sys
66
from enum import Enum
7-
from functools import total_ordering
7+
from functools import partial, total_ordering
88
from pathlib import Path
99
from typing import ClassVar, List, Optional, Set, TextIO, Tuple, Type, Union
1010

1111
from pydantic import BaseSettings
1212
from pydantic.env_settings import SettingsSourceCallable # pylint: disable=E0611
13+
from pydantic.json import custom_pydantic_encoder # pylint: disable=no-name-in-module
1314

1415
from fawltydeps.types import CustomMapping, ParserChoice, PathOrSpecial, TomlData
1516

@@ -211,7 +212,9 @@ def print_toml_config(settings: Settings, out: TextIO = sys.stdout) -> None:
211212
"""Serialize the given Settings object into a TOML config section."""
212213
# Use JSON serialization as a basis for TOML output. Load that back into
213214
# Python and then use Python's repr() representation below
214-
simple_settings = json.loads(settings.json())
215+
set_sort = partial(sorted, key=str)
216+
encoder = partial(custom_pydantic_encoder, {frozenset: set_sort, set: set_sort})
217+
simple_settings = json.loads(json.dumps(settings, default=encoder))
215218
defaults = {
216219
name: field.default for name, field in settings.__class__.__fields__.items()
217220
}

tests/test_cmdline.py

+24
Original file line numberDiff line numberDiff line change
@@ -902,6 +902,30 @@ def test_cmdline_on_ignored_undeclared_option(
902902
).splitlines(),
903903
id="generate_toml_config_with_a_setting_set_to_str_None",
904904
),
905+
pytest.param(
906+
{"pyenvs": ["foo", "bar"]},
907+
["--pyenv", "baz", "xyzzy", "--generate-toml-config"],
908+
dedent(
909+
"""\
910+
# Copy this TOML section into your pyproject.toml to configure FawltyDeps
911+
# (default values are commented)
912+
[tool.fawltydeps]
913+
# actions = ['check_undeclared', 'check_unused']
914+
# output_format = 'human_summary'
915+
# code = ['.']
916+
# deps = ['.']
917+
pyenvs = ['baz', 'xyzzy']
918+
# custom_mapping_file = []
919+
# ignore_undeclared = []
920+
# ignore_unused = []
921+
# deps_parser_choice = ...
922+
# install_deps = false
923+
# verbosity = 0
924+
# [tool.fawltydeps.custom_mapping]
925+
"""
926+
).splitlines(),
927+
id="generate_toml_config_with_multiple_pyenvs",
928+
),
905929
],
906930
)
907931
def test_cmdline_args_in_combination_with_config_file(

0 commit comments

Comments
 (0)