FourCIPP 1.2.0__tar.gz → 1.3.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. {fourcipp-1.2.0/src/FourCIPP.egg-info → fourcipp-1.3.0}/PKG-INFO +2 -2
  2. {fourcipp-1.2.0 → fourcipp-1.3.0}/README.md +1 -1
  3. {fourcipp-1.2.0 → fourcipp-1.3.0/src/FourCIPP.egg-info}/PKG-INFO +2 -2
  4. {fourcipp-1.2.0 → fourcipp-1.3.0}/src/fourcipp/fourc_input.py +77 -5
  5. {fourcipp-1.2.0 → fourcipp-1.3.0}/src/fourcipp/utils/configuration.py +4 -3
  6. {fourcipp-1.2.0 → fourcipp-1.3.0}/src/fourcipp/utils/dict_utils.py +32 -0
  7. {fourcipp-1.2.0 → fourcipp-1.3.0}/src/fourcipp/utils/yaml_io.py +18 -8
  8. {fourcipp-1.2.0 → fourcipp-1.3.0}/src/fourcipp/version.py +3 -3
  9. {fourcipp-1.2.0 → fourcipp-1.3.0}/tests/fourcipp/test_fourc_input.py +49 -0
  10. {fourcipp-1.2.0 → fourcipp-1.3.0}/tests/fourcipp/utils/test_dict_utils.py +29 -0
  11. {fourcipp-1.2.0 → fourcipp-1.3.0}/tests/fourcipp/utils/test_yaml_io.py +5 -2
  12. {fourcipp-1.2.0 → fourcipp-1.3.0}/.coveragerc +0 -0
  13. {fourcipp-1.2.0 → fourcipp-1.3.0}/.github/workflows/check_code.yaml +0 -0
  14. {fourcipp-1.2.0 → fourcipp-1.3.0}/.github/workflows/publish_pypi.yaml +0 -0
  15. {fourcipp-1.2.0 → fourcipp-1.3.0}/.github/workflows/run_testsuite.yaml +0 -0
  16. {fourcipp-1.2.0 → fourcipp-1.3.0}/.github/workflows/tag_version.yaml +0 -0
  17. {fourcipp-1.2.0 → fourcipp-1.3.0}/.github/workflows/update_4C_metadata_schema_file.yaml +0 -0
  18. {fourcipp-1.2.0 → fourcipp-1.3.0}/.gitignore +0 -0
  19. {fourcipp-1.2.0 → fourcipp-1.3.0}/.pre-commit-config.yaml +0 -0
  20. {fourcipp-1.2.0 → fourcipp-1.3.0}/LICENSE +0 -0
  21. {fourcipp-1.2.0 → fourcipp-1.3.0}/docs/assets/fourcipp_logo_black.svg +0 -0
  22. {fourcipp-1.2.0 → fourcipp-1.3.0}/docs/assets/fourcipp_logo_white.svg +0 -0
  23. {fourcipp-1.2.0 → fourcipp-1.3.0}/pyproject.toml +0 -0
  24. {fourcipp-1.2.0 → fourcipp-1.3.0}/requirements.in +0 -0
  25. {fourcipp-1.2.0 → fourcipp-1.3.0}/requirements.txt +0 -0
  26. {fourcipp-1.2.0 → fourcipp-1.3.0}/setup.cfg +0 -0
  27. {fourcipp-1.2.0 → fourcipp-1.3.0}/src/FourCIPP.egg-info/SOURCES.txt +0 -0
  28. {fourcipp-1.2.0 → fourcipp-1.3.0}/src/FourCIPP.egg-info/dependency_links.txt +0 -0
  29. {fourcipp-1.2.0 → fourcipp-1.3.0}/src/FourCIPP.egg-info/entry_points.txt +0 -0
  30. {fourcipp-1.2.0 → fourcipp-1.3.0}/src/FourCIPP.egg-info/requires.txt +0 -0
  31. {fourcipp-1.2.0 → fourcipp-1.3.0}/src/FourCIPP.egg-info/top_level.txt +0 -0
  32. {fourcipp-1.2.0 → fourcipp-1.3.0}/src/fourcipp/__init__.py +0 -0
  33. {fourcipp-1.2.0 → fourcipp-1.3.0}/src/fourcipp/config/4C_metadata.yaml +0 -0
  34. {fourcipp-1.2.0 → fourcipp-1.3.0}/src/fourcipp/config/4C_schema.json +0 -0
  35. {fourcipp-1.2.0 → fourcipp-1.3.0}/src/fourcipp/config/config.yaml +0 -0
  36. {fourcipp-1.2.0 → fourcipp-1.3.0}/src/fourcipp/legacy_io/__init__.py +0 -0
  37. {fourcipp-1.2.0 → fourcipp-1.3.0}/src/fourcipp/legacy_io/element.py +0 -0
  38. {fourcipp-1.2.0 → fourcipp-1.3.0}/src/fourcipp/legacy_io/inline_dat.py +0 -0
  39. {fourcipp-1.2.0 → fourcipp-1.3.0}/src/fourcipp/legacy_io/node.py +0 -0
  40. {fourcipp-1.2.0 → fourcipp-1.3.0}/src/fourcipp/legacy_io/node_topology.py +0 -0
  41. {fourcipp-1.2.0 → fourcipp-1.3.0}/src/fourcipp/legacy_io/particle.py +0 -0
  42. {fourcipp-1.2.0 → fourcipp-1.3.0}/src/fourcipp/utils/__init__.py +0 -0
  43. {fourcipp-1.2.0 → fourcipp-1.3.0}/src/fourcipp/utils/cli.py +0 -0
  44. {fourcipp-1.2.0 → fourcipp-1.3.0}/src/fourcipp/utils/converter.py +0 -0
  45. {fourcipp-1.2.0 → fourcipp-1.3.0}/src/fourcipp/utils/metadata.py +0 -0
  46. {fourcipp-1.2.0 → fourcipp-1.3.0}/src/fourcipp/utils/not_set.py +0 -0
  47. {fourcipp-1.2.0 → fourcipp-1.3.0}/src/fourcipp/utils/typing.py +0 -0
  48. {fourcipp-1.2.0 → fourcipp-1.3.0}/src/fourcipp/utils/validation.py +0 -0
  49. {fourcipp-1.2.0 → fourcipp-1.3.0}/tests/__init__.py +0 -0
  50. {fourcipp-1.2.0 → fourcipp-1.3.0}/tests/conftest.py +0 -0
  51. {fourcipp-1.2.0 → fourcipp-1.3.0}/tests/fourcipp/__init__.py +0 -0
  52. {fourcipp-1.2.0 → fourcipp-1.3.0}/tests/fourcipp/legacy_io/__init__.py +0 -0
  53. {fourcipp-1.2.0 → fourcipp-1.3.0}/tests/fourcipp/legacy_io/test_element.py +0 -0
  54. {fourcipp-1.2.0 → fourcipp-1.3.0}/tests/fourcipp/legacy_io/test_inline_dat.py +0 -0
  55. {fourcipp-1.2.0 → fourcipp-1.3.0}/tests/fourcipp/legacy_io/test_legacy_io.py +0 -0
  56. {fourcipp-1.2.0 → fourcipp-1.3.0}/tests/fourcipp/legacy_io/test_node.py +0 -0
  57. {fourcipp-1.2.0 → fourcipp-1.3.0}/tests/fourcipp/legacy_io/test_node_topology.py +0 -0
  58. {fourcipp-1.2.0 → fourcipp-1.3.0}/tests/fourcipp/legacy_io/test_particle.py +0 -0
  59. {fourcipp-1.2.0 → fourcipp-1.3.0}/tests/fourcipp/legacy_io/utils.py +0 -0
  60. {fourcipp-1.2.0 → fourcipp-1.3.0}/tests/fourcipp/test_readme_quickstart_example.py +0 -0
  61. {fourcipp-1.2.0 → fourcipp-1.3.0}/tests/fourcipp/utils/__init__.py +0 -0
  62. {fourcipp-1.2.0 → fourcipp-1.3.0}/tests/fourcipp/utils/test_configuration.py +0 -0
  63. {fourcipp-1.2.0 → fourcipp-1.3.0}/tests/fourcipp/utils/test_converter.py +0 -0
  64. {fourcipp-1.2.0 → fourcipp-1.3.0}/tests/fourcipp/utils/test_not_set.py +0 -0
  65. {fourcipp-1.2.0 → fourcipp-1.3.0}/tests/fourcipp/utils/test_validation.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: FourCIPP
3
- Version: 1.2.0
3
+ Version: 1.3.0
4
4
  Summary: A streamlined Python Parser for 4C input files
5
5
  Author: FourCIPP Authors
6
6
  License: The MIT License (MIT)
@@ -168,7 +168,7 @@ input_4C["PROBLEM SIZE"]["NODES"] = 10_000_000
168
168
  removed_section = input_4C.pop("PROBLEM SIZE")
169
169
 
170
170
  # Dump to file
171
- input_4C.dump(input_file_path, sort_sections=True, validate=True)
171
+ input_4C.dump(input_file_path, validate=True)
172
172
  ```
173
173
  <!--example, do not remove this comment-->
174
174
 
@@ -124,7 +124,7 @@ input_4C["PROBLEM SIZE"]["NODES"] = 10_000_000
124
124
  removed_section = input_4C.pop("PROBLEM SIZE")
125
125
 
126
126
  # Dump to file
127
- input_4C.dump(input_file_path, sort_sections=True, validate=True)
127
+ input_4C.dump(input_file_path, validate=True)
128
128
  ```
129
129
  <!--example, do not remove this comment-->
130
130
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: FourCIPP
3
- Version: 1.2.0
3
+ Version: 1.3.0
4
4
  Summary: A streamlined Python Parser for 4C input files
5
5
  Author: FourCIPP Authors
6
6
  License: The MIT License (MIT)
@@ -168,7 +168,7 @@ input_4C["PROBLEM SIZE"]["NODES"] = 10_000_000
168
168
  removed_section = input_4C.pop("PROBLEM SIZE")
169
169
 
170
170
  # Dump to file
171
- input_4C.dump(input_file_path, sort_sections=True, validate=True)
171
+ input_4C.dump(input_file_path, validate=True)
172
172
  ```
173
173
  <!--example, do not remove this comment-->
174
174
 
@@ -27,7 +27,7 @@ import copy
27
27
  import difflib
28
28
  import pathlib
29
29
  from collections.abc import Sequence
30
- from typing import Any
30
+ from typing import Any, Callable
31
31
 
32
32
  from loguru import logger
33
33
 
@@ -37,7 +37,10 @@ from fourcipp.legacy_io import (
37
37
  interpret_legacy_section,
38
38
  )
39
39
  from fourcipp.utils.converter import Converter
40
- from fourcipp.utils.dict_utils import compare_nested_dicts_or_lists
40
+ from fourcipp.utils.dict_utils import (
41
+ compare_nested_dicts_or_lists,
42
+ sort_by_key_order,
43
+ )
41
44
  from fourcipp.utils.not_set import NotSet, check_if_set
42
45
  from fourcipp.utils.typing import Path
43
46
  from fourcipp.utils.validation import ValidationError, validate_using_json_schema
@@ -66,6 +69,75 @@ def is_section_known(section_name: str, known_section_names: list[str]) -> bool:
66
69
  return section_name in known_section_names or section_name.startswith("FUNCT")
67
70
 
68
71
 
72
+ def _sort_by_section_names(data: dict) -> dict:
73
+ """Sort a dictionary by its 4C sections.
74
+
75
+ This sorts the dictionary in the following style:
76
+
77
+ 1. "TITLE" section
78
+ 2. Alphabetically sorted sections
79
+ 3. Alphabetically sorted legacy sections
80
+
81
+ Args:
82
+ data: Dictionary to sort.
83
+ section_names: List of all section names in the 4C style order.
84
+
85
+ Returns:
86
+ Dict sorted in 4C fashion
87
+ """
88
+
89
+ required_sections = CONFIG.fourc_json_schema["required"]
90
+ n_sections_splitter = len(CONFIG.sections.all_sections) * 1000
91
+
92
+ # collect typed sections + numeric FUNCT sections
93
+ typed_and_funct = sorted(
94
+ sorted(CONFIG.sections.typed_sections, key=str.lower)
95
+ + [s for s in data.keys() if s.startswith("FUNCT") and s[5:].isdigit()],
96
+ key=lambda s: (
97
+ s.lower() if not s.startswith("FUNCT") else f"funct{s[5:].zfill(10)}"
98
+ ),
99
+ )
100
+
101
+ def ordering_score(section: str) -> int:
102
+ """Get ordering score, small score comes first, larger comes later.
103
+
104
+ We offset the score by the number of sections multiplied by 1000. This way a score is guaranteed to never appear twice.
105
+
106
+ Args:
107
+ section: Section name to score
108
+
109
+ Returns:
110
+ ordering score
111
+ """
112
+ # Title sections
113
+ if section == CONFIG.fourc_metadata["metadata"]["description_section_name"]:
114
+ return 0
115
+ # Required sections
116
+ elif section in required_sections:
117
+ return 1 * n_sections_splitter + required_sections.index(section)
118
+ # Typed + FUNCT sections (alphabetical + case insensitive)
119
+ elif section in typed_and_funct:
120
+ return 2 * n_sections_splitter + typed_and_funct.index(section)
121
+ # Legacy sections
122
+ elif section in CONFIG.sections.legacy_sections:
123
+ return 3 * n_sections_splitter + CONFIG.sections.legacy_sections.index(
124
+ section
125
+ )
126
+ # Unknown section
127
+ else:
128
+ raise KeyError(f"Unknown section {section}")
129
+
130
+ unknown_sections = set(data.keys()) - set(CONFIG.sections.all_sections)
131
+
132
+ # Remove functions, these are a special case
133
+ if [section for section in unknown_sections if not section.startswith("FUNCT")]:
134
+ raise ValueError(
135
+ f"Sections {list(unknown_sections)} are not known in 'section_names'"
136
+ )
137
+
138
+ return sort_by_key_order(data, sorted(data.keys(), key=ordering_score))
139
+
140
+
69
141
  class FourCInput:
70
142
  """4C inout file object."""
71
143
 
@@ -420,20 +492,20 @@ class FourCInput:
420
492
  def dump(
421
493
  self,
422
494
  input_file_path: Path,
423
- sort_sections: bool = False,
424
495
  validate: bool = False,
425
496
  validate_sections_only: bool = False,
426
497
  convert_to_native_types: bool = True,
498
+ sort_function: Callable[[dict], dict] | None = _sort_by_section_names,
427
499
  ) -> None:
428
500
  """Dump object to yaml.
429
501
 
430
502
  Args:
431
503
  input_file_path: Path to dump the data to
432
- sort_sections: Sort the sections alphabetically
433
504
  validate: Validate input data before dumping
434
505
  validate_sections_only: Validate each section independently.
435
506
  Requiredness of the sections themselves is ignored.
436
507
  convert_to_native_types: Convert all sections to native Python types
508
+ sort_function: Function to sort the sections.
437
509
  """
438
510
 
439
511
  if validate or validate_sections_only:
@@ -448,7 +520,7 @@ class FourCInput:
448
520
  if convert_to_native_types:
449
521
  self.convert_to_native_types()
450
522
 
451
- dump_yaml(self.inlined, input_file_path, sort_sections)
523
+ dump_yaml(self.inlined, input_file_path, sort_function)
452
524
 
453
525
  def validate(
454
526
  self,
@@ -45,7 +45,7 @@ class Sections:
45
45
  """
46
46
  self.legacy_sections: list[str] = legacy_sections
47
47
  self.typed_sections: list[str] = typed_sections
48
- self.all_sections: list[str] = legacy_sections + typed_sections
48
+ self.all_sections: list[str] = typed_sections + legacy_sections
49
49
 
50
50
  @classmethod
51
51
  def from_metadata(cls, fourc_metadata: dict) -> Sections:
@@ -58,9 +58,10 @@ class Sections:
58
58
  Sections: sections object
59
59
  """
60
60
  description_section = fourc_metadata["metadata"]["description_section_name"]
61
- sections = [
61
+ sections = [description_section] + [
62
62
  section["name"] for section in fourc_metadata["sections"]["specs"]
63
- ] + [description_section]
63
+ ]
64
+
64
65
  legacy_sections = list(fourc_metadata["legacy_string_sections"])
65
66
 
66
67
  return cls(legacy_sections, sections)
@@ -373,3 +373,35 @@ def rename_parameter(
373
373
 
374
374
  for entry, last_key in _split_off_last_key(nested_dict, keys):
375
375
  entry[new_name] = entry.pop(last_key)
376
+
377
+
378
+ def sort_by_key_order(data: dict, key_order: list[str]) -> dict:
379
+ """Sort a dictionary by a specific key order.
380
+
381
+ Args:
382
+ data: Dictionary to sort.
383
+ key_order: List of keys in the desired order.
384
+
385
+ Returns:
386
+ Sorted dictionary.
387
+ """
388
+ if set(key_order) != set(data.keys()):
389
+ raise ValueError("'key_order' must include all keys in the dictionary!")
390
+
391
+ return {key: data[key] for key in key_order if key in data}
392
+
393
+
394
+ def sort_alphabetically(
395
+ data: dict,
396
+ ) -> dict:
397
+ """Sort a dictionary alphabetically.
398
+
399
+ Args:
400
+ data: Dictionary to sort.
401
+
402
+ Returns:
403
+ Sorted dictionary.
404
+ """
405
+ return sort_by_key_order(
406
+ data, sorted(data.keys(), key=lambda s: (s.lower(), 0 if s.islower() else 1))
407
+ )
@@ -24,6 +24,7 @@
24
24
  import json
25
25
  import pathlib
26
26
  import re
27
+ from typing import Callable
27
28
 
28
29
  import ryml
29
30
 
@@ -61,17 +62,21 @@ def load_yaml(path_to_yaml_file: Path) -> dict:
61
62
  return data
62
63
 
63
64
 
64
- def dict_to_yaml_string(data: dict, sort_keys: bool = False) -> str:
65
+ def dict_to_yaml_string(
66
+ data: dict, sort_function: Callable[[dict], dict] | None = None
67
+ ) -> str:
65
68
  """Dump dict as yaml.
66
69
 
67
70
  Args:
68
71
  data: Data to dump.
69
- sort_keys: If true sort the sections by section name
72
+ sort_function: Function to sort the data.
73
+
74
+ Returns:
75
+ YAML string representation of the data
70
76
  """
71
77
 
72
- # Sort keys
73
- if sort_keys:
74
- data = {key: data[key] for key in sorted(data.keys())}
78
+ if sort_function is not None:
79
+ data = sort_function(data)
75
80
 
76
81
  # Convert dictionary into a ryml tree
77
82
  tree = ryml.parse_in_arena(bytearray(json.dumps(data).encode("utf8")))
@@ -88,14 +93,19 @@ def dict_to_yaml_string(data: dict, sort_keys: bool = False) -> str:
88
93
  return ryml.emit_yaml(tree)
89
94
 
90
95
 
91
- def dump_yaml(data: dict, path_to_yaml_file: Path, sort_keys: bool = False) -> None:
96
+ def dump_yaml(
97
+ data: dict,
98
+ path_to_yaml_file: Path,
99
+ sort_function: Callable[[dict], dict] | None = None,
100
+ ) -> None:
92
101
  """Dump yaml to file.
93
102
 
94
103
  Args:
95
104
  data: Data to dump.
96
105
  path_to_yaml_file: Yaml file path
97
- sort_keys: If true sort the sections by section name
106
+ sort_function: Function to sort the data.
98
107
  """
99
108
  pathlib.Path(path_to_yaml_file).write_text(
100
- dict_to_yaml_string(data, sort_keys), encoding="utf-8"
109
+ dict_to_yaml_string(data, sort_function),
110
+ encoding="utf-8",
101
111
  )
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
28
28
  commit_id: COMMIT_ID
29
29
  __commit_id__: COMMIT_ID
30
30
 
31
- __version__ = version = '1.2.0'
32
- __version_tuple__ = version_tuple = (1, 2, 0)
31
+ __version__ = version = '1.3.0'
32
+ __version_tuple__ = version_tuple = (1, 3, 0)
33
33
 
34
- __commit_id__ = commit_id = 'g979d1f40a'
34
+ __commit_id__ = commit_id = 'gdf724552b'
@@ -23,6 +23,7 @@
23
23
 
24
24
  import contextlib
25
25
  import pathlib
26
+ import random
26
27
  import subprocess
27
28
  import time
28
29
  from collections.abc import Callable
@@ -33,6 +34,7 @@ from fourcipp import CONFIG
33
34
  from fourcipp.fourc_input import (
34
35
  FourCInput,
35
36
  UnknownSectionException,
37
+ _sort_by_section_names,
36
38
  )
37
39
  from fourcipp.utils.cli import modify_input_with_defaults
38
40
  from fourcipp.utils.validation import ValidationError
@@ -552,6 +554,53 @@ def test_validation(fourc_input, error_context, sections_only):
552
554
  fourc_input.validate(sections_only=sections_only)
553
555
 
554
556
 
557
+ def test_sort_by_section_names():
558
+ """Test sorting by section names."""
559
+
560
+ # create list of typed sections without title and required sections
561
+ typed_sections = [
562
+ sec
563
+ for sec in CONFIG.sections.typed_sections
564
+ if sec != CONFIG.fourc_metadata["metadata"]["description_section_name"]
565
+ and sec not in set(CONFIG.fourc_json_schema["required"])
566
+ ]
567
+
568
+ # also use end subset to also add some lowercase sections
569
+ typed_and_functions = (
570
+ typed_sections[:15]
571
+ + typed_sections[-15:]
572
+ + [f"FUNCT{i}" for i in [1, 2, 9, 10, 33]]
573
+ )
574
+
575
+ # sort with proper key: alphabetically for typed, numerically for FUNCT
576
+ typed_and_functions = sorted(
577
+ typed_and_functions,
578
+ key=lambda s: (
579
+ s.lower() if not s.startswith("FUNCT") else f"funct{s[5:].zfill(10)}"
580
+ ),
581
+ )
582
+
583
+ correct_section_order = (
584
+ [CONFIG.fourc_metadata["metadata"]["description_section_name"]]
585
+ + CONFIG.fourc_json_schema["required"]
586
+ + typed_and_functions
587
+ + CONFIG.sections.legacy_sections
588
+ )
589
+
590
+ shuffled_section_order = correct_section_order.copy()
591
+ random.seed(42)
592
+ random.shuffle(shuffled_section_order)
593
+
594
+ shuffled_data = {k: 1 for k in shuffled_section_order}
595
+
596
+ sorted_data = _sort_by_section_names(shuffled_data)
597
+
598
+ assert list(sorted_data.keys()) == correct_section_order
599
+
600
+
601
+ ## performance tests
602
+
603
+
555
604
  def create_dummy_elements() -> dict:
556
605
  """Create dummy elements for the performance test.
557
606
 
@@ -34,6 +34,8 @@ from fourcipp.utils.dict_utils import (
34
34
  remove,
35
35
  rename_parameter,
36
36
  replace_value,
37
+ sort_alphabetically,
38
+ sort_by_key_order,
37
39
  )
38
40
 
39
41
 
@@ -664,3 +666,30 @@ def test_get_dict_optional(nested_input_dict):
664
666
  result = entry
665
667
  # assert if nothing changed
666
668
  assert result == "some value"
669
+
670
+
671
+ def test_sort_by_key_order_basic():
672
+ """Test sorting by key order."""
673
+
674
+ data = {"b": 2, "a": 1, "c": 3}
675
+
676
+ assert sort_by_key_order(data, ["a", "b", "c"]) == {"a": 1, "b": 2, "c": 3}
677
+
678
+
679
+ def test_sort_by_key_order_error_mismatched_keys():
680
+ """Test sorting by key order with mismatched keys."""
681
+
682
+ data = {"b": 2, "a": 1, "c": 3}
683
+
684
+ with pytest.raises(
685
+ ValueError, match="'key_order' must include all keys in the dictionary!"
686
+ ):
687
+ sort_by_key_order(data, ["a", "b"])
688
+
689
+
690
+ def test_sort_alphabetically():
691
+ """Test alphabetical sorting."""
692
+
693
+ data = {"A": 1, "b": 2, "a": 0, "B": 3, "c": 4, "C": 5}
694
+
695
+ assert sort_alphabetically(data) == {"a": 0, "A": 1, "b": 2, "B": 3, "c": 4, "C": 5}
@@ -21,6 +21,7 @@
21
21
  # THE SOFTWARE.
22
22
  """Test yaml io utils."""
23
23
 
24
+ from fourcipp.utils.dict_utils import sort_alphabetically
24
25
  from fourcipp.utils.yaml_io import dump_yaml, load_yaml
25
26
 
26
27
 
@@ -33,10 +34,12 @@ def test_dump_not_sorted(tmp_path):
33
34
  assert reloaded_data == data
34
35
 
35
36
 
36
- def test_dump_sorted(tmp_path):
37
+ def test_dump_sorted_alphabetically(tmp_path):
37
38
  """Test if key order is sorted."""
38
39
  data = {"c": 1, "b": 2, "a": 3}
39
40
  sorted_file_path = tmp_path / "sorted.yaml"
40
- dump_yaml(data, path_to_yaml_file=sorted_file_path, sort_keys=True)
41
+ dump_yaml(
42
+ data, path_to_yaml_file=sorted_file_path, sort_function=sort_alphabetically
43
+ )
41
44
  reloaded_data = load_yaml(sorted_file_path)
42
45
  assert list(reloaded_data.keys()) == sorted(data.keys())
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes