• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

emcek / dcspy / 9231915424

25 May 2024 01:35AM UTC coverage: 96.349% (+0.02%) from 96.326%
9231915424

Pull #313

github

emcek
upate chnagelog
Pull Request #313: F-4E Phantom II

37 of 39 new or added lines in 6 files covered. (94.87%)

12 existing lines in 1 file now uncovered.

2032 of 2109 relevant lines covered (96.35%)

0.96 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

87.0
/dcspy/migration.py
1
import re
1✔
2
from collections.abc import Iterator
1✔
3
from logging import getLogger
1✔
4
from os import makedirs
1✔
5
from pathlib import Path
1✔
6
from pprint import pformat
1✔
7
from shutil import SameFileError, copy
1✔
8
from typing import Callable, Union
1✔
9

10
from packaging import version
1✔
11

12
from dcspy.models import DcspyConfigYaml
1✔
13
from dcspy.utils import DEFAULT_YAML_FILE, defaults_cfg, get_config_yaml_location
1✔
14

15
LOG = getLogger(__name__)
1✔
16
__version__ = '3.4.2'
1✔
17

18

19
def migrate(cfg: DcspyConfigYaml) -> DcspyConfigYaml:
1✔
20
    """
21
    Perform migration of configuration based on API version.
22

23
    If api_ver key do not exist, it is set to 2.3.3.
24

25
    :param cfg: configuration dict
26
    :return: Full migrated dict
27
    """
28
    LOG.debug(f'Starting configuration:\n{pformat(cfg)}')
1✔
29
    src_ver = cfg.get('api_ver', '2.3.3')  # do not touch this api_ver!
1✔
30
    LOG.debug(f'Current API version: {src_ver}')
1✔
31
    for migration_func in _filter_api_ver_func(str(src_ver)):
1✔
32
        migration_func(cfg)
1✔
33
        LOG.debug(f'Migration done: {migration_func.__name__}')
1✔
34
    cfg['api_ver'] = __version__
1✔
35
    cfg_with_defaults = {key: cfg.get(key, value) for key, value in defaults_cfg.items()}
1✔
36
    if 'UNKNOWN' in str(cfg_with_defaults['dcsbios']):
1✔
37
        cfg_with_defaults['dcsbios'] = defaults_cfg['dcsbios']
×
38
    final_cfg = {**cfg_with_defaults, **cfg}
1✔
39
    LOG.debug(f'Final configuration:\n{pformat(final_cfg)}')
1✔
40
    return final_cfg
1✔
41

42

43
def _filter_api_ver_func(cfg_ver: str) -> Iterator[Callable[[DcspyConfigYaml], None]]:
1✔
44
    """
45
    Filter migration function to call.
46

47
    :param cfg_ver: Current version of configuration
48
    :return: yield list of migration functions
49
    """
50
    api_ver_list = sorted([func_name.strip('_api_ver_').replace('_', '.')
1✔
51
                           for func_name in globals()
52
                           if func_name.startswith('_api_ver_')],
53
                          key=version.Version)
54
    for api_ver in api_ver_list:
1✔
55
        if version.Version(api_ver) > version.Version(cfg_ver) <= version.Version(__version__):
1✔
56
            yield globals()['_api_ver_{}'.format(api_ver.replace('.', '_'))]
1✔
57

58

59
def _api_ver_3_4_0(cfg: DcspyConfigYaml) -> None:
1✔
60
    """
61
    Migrate to version 3.4.0.
62

63
    :param cfg: Configuration dictionary
64
    """
65
    user_appdata = get_config_yaml_location()
1✔
66
    makedirs(name=user_appdata, exist_ok=True)
1✔
67
    _rename_key_keep_value(cfg, 'keyboard', 'device', 'G13')
1✔
68
    cfg['device'] = str(cfg['device']).replace(' ', '')
1✔
69

70

71
def _api_ver_3_1_3(cfg: DcspyConfigYaml) -> None:
1✔
72
    """
73
    Migrate to version 3.1.3.
74

75
    :param cfg: Configuration dictionary
76
    """
77
    user_appdata = get_config_yaml_location()
1✔
78
    makedirs(name=user_appdata, exist_ok=True)
1✔
79
    _remove_key(cfg, 'font_mono_xs')
1✔
80
    _remove_key(cfg, 'font_color_xs')
1✔
81

82

83
def _api_ver_3_1_1(cfg: DcspyConfigYaml) -> None:
1✔
84
    """
85
    Migrate to version 3.1.1.
86

87
    :param cfg: Configuration dictionary
88
    """
89
    user_appdata = get_config_yaml_location()
1✔
90
    makedirs(name=user_appdata, exist_ok=True)
1✔
91
    _copy_file(filename='AH-64D_BLK_II.yaml', to_path=user_appdata, force=True)
1✔
92

93

94
def _api_ver_3_1_0(cfg: DcspyConfigYaml) -> None:
1✔
95
    """
96
    Migrate to version 3.1.0.
97

98
    :param cfg: Configuration dictionary
99
    """
100
    user_appdata = get_config_yaml_location()
1✔
101
    makedirs(name=user_appdata, exist_ok=True)
1✔
102
    for filename in ('AH-64D_BLK_II.yaml', 'AV8BNA.yaml', 'F-14A-135-GR.yaml', 'F-14B.yaml', 'F-15ESE.yaml',
1✔
103
                     'F-16C_50.yaml', 'FA-18C_hornet.yaml', 'Ka-50.yaml', 'Ka-50_3.yaml'):
104
        _copy_file(filename=filename, to_path=user_appdata)
1✔
105

106

107
def _api_ver_3_0_0(cfg: DcspyConfigYaml) -> None:
1✔
108
    """
109
    Migrate to version 3.0.0.
110

111
    :param cfg: Configuration dictionary
112
    """
113
    _add_key(cfg, 'completer_items', 20)
1✔
114
    _add_key(cfg, 'current_plane', 'A-10C')
1✔
115
    _add_key(cfg, 'gkeys_area', 2)
1✔
116
    _add_key(cfg, 'gkeys_float', False)
1✔
117
    _add_key(cfg, 'toolbar_area', 4)
1✔
118
    _add_key(cfg, 'toolbar_style', 0)
1✔
119

120
    _remove_key(cfg, 'theme_color')
1✔
121
    _remove_key(cfg, 'theme_mode')
1✔
122

123
    _rename_key_keep_value(cfg, 'font_color_s', 'font_color_m', 22)
1✔
124
    _rename_key_keep_value(cfg, 'font_color_xs', 'font_color_s', 18)
1✔
125
    _rename_key_keep_value(cfg, 'font_mono_s', 'font_mono_m', 11)
1✔
126
    _rename_key_keep_value(cfg, 'font_mono_xs', 'font_mono_s', 9)
1✔
127

128

129
def _add_key(cfg: DcspyConfigYaml, key: str, default_value: Union[str, int, bool]) -> None:
1✔
130
    """
131
    Add key to dictionary if not exists.
132

133
    :param cfg: Configuration dictionary
134
    :param key: key name
135
    :param default_value: value to set
136
    """
137
    if key not in cfg:
1✔
138
        cfg[key] = default_value
1✔
139
        LOG.debug(f'Added key: {key} with: {default_value}')
1✔
140

141

142
def _remove_key(cfg: DcspyConfigYaml, key: str) -> None:
1✔
143
    """
144
    Remove key from dictionary.
145

146
    :param cfg: Configuration dictionary
147
    :param key: key name
148
    """
149
    try:
1✔
150
        del cfg[key]
1✔
151
        LOG.debug(f'Remove key: {key}')
1✔
152
    except KeyError:
1✔
153
        pass
1✔
154

155

156
def _rename_key_keep_value(cfg: DcspyConfigYaml, old_name: str, new_name: str, default_value: Union[str, int, bool]) -> None:
1✔
157
    """
158
    Rename key in dictionary and keep value.
159

160
    :param cfg: Configuration dictionary
161
    :param old_name: Old key name
162
    :param new_name: New key name
163
    :param default_value: default value if old key do not exist
164
    """
165
    value = cfg.get(old_name, default_value)
1✔
166
    try:
1✔
167
        del cfg[old_name]
1✔
168
    except KeyError:
1✔
169
        pass
1✔
170
    cfg[new_name] = value
1✔
171
    LOG.debug(f'Rename key {old_name} -> {new_name} with: {value}')
1✔
172

173

174
def _copy_file(filename: str, to_path: Path, force=False) -> None:
1✔
175
    """
176
    Copy a file from one location to another, only when the file doesn't exist.
177

178
    :param filename: The name of the file to be copied.
179
    :param to_path: The full path where the file should be copied to.
180
    :param force: force to overwrite existing file
181
    """
182
    if not Path(to_path / filename).is_file() or force:
1✔
183
        try:
1✔
184
            copy(src=DEFAULT_YAML_FILE.parent / filename, dst=to_path)
1✔
185
            LOG.debug(f'Copy file: {filename} to {to_path}')
1✔
UNCOV
186
        except SameFileError:
×
UNCOV
187
            pass
×
188

189

190
def _replace_line_in_file(filename: str, dir_path: Path, pattern: re.Pattern, new_text: str) -> None:
1✔
191
    """
192
    Replace a line in a file based on a given pattern.
193

194
    :param filename: The name of the file to replace the line in.
195
    :param dir_path: The directory path where the file is located.
196
    :param pattern: The regular expression pattern to search for in the file.
197
    :param new_text: The text to replace the line matching the pattern with.
198
    """
UNCOV
199
    yaml_filename = dir_path / filename
×
UNCOV
200
    try:
×
UNCOV
201
        with open(yaml_filename) as yaml_file:
×
UNCOV
202
            file_content = yaml_file.read()
×
UNCOV
203
        LOG.debug(yaml_filename)
×
UNCOV
204
        updated_content = re.sub(pattern, new_text, file_content)
×
UNCOV
205
        with open(yaml_filename, 'w') as yaml_file:
×
UNCOV
206
            yaml_file.write(updated_content)
×
UNCOV
207
    except FileNotFoundError:
×
UNCOV
208
        pass
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc