backlogops 1.0__tar.gz → 1.2__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.
- {backlogops-1.0 → backlogops-1.2}/PKG-INFO +7 -7
- {backlogops-1.0 → backlogops-1.2}/README_pypi.md +2 -2
- {backlogops-1.0 → backlogops-1.2}/backlogops.egg-info/PKG-INFO +7 -7
- {backlogops-1.0 → backlogops-1.2}/backlogops.egg-info/requires.txt +4 -4
- {backlogops-1.0 → backlogops-1.2}/setup.py +5 -5
- {backlogops-1.0 → backlogops-1.2}/src/backlogops/available_teams_config.py +28 -17
- {backlogops-1.0 → backlogops-1.2}/src/backlogops/backlog_ops_config.py +62 -17
- {backlogops-1.0 → backlogops-1.2}/src/backlogops/config_editing.py +30 -10
- {backlogops-1.0 → backlogops-1.2}/src/backlogops/io_config.py +34 -18
- {backlogops-1.0 → backlogops-1.2}/src/backlogops/jira_io_config.py +12 -6
- {backlogops-1.0 → backlogops-1.2}/LICENSE.txt +0 -0
- {backlogops-1.0 → backlogops-1.2}/backlogops.egg-info/SOURCES.txt +0 -0
- {backlogops-1.0 → backlogops-1.2}/backlogops.egg-info/dependency_links.txt +0 -0
- {backlogops-1.0 → backlogops-1.2}/backlogops.egg-info/top_level.txt +0 -0
- {backlogops-1.0 → backlogops-1.2}/pyproject.toml +0 -0
- {backlogops-1.0 → backlogops-1.2}/setup.cfg +0 -0
- {backlogops-1.0 → backlogops-1.2}/src/backlogops/__init__.py +0 -0
- {backlogops-1.0 → backlogops-1.2}/src/backlogops/apply_format_rules.py +0 -0
- {backlogops-1.0 → backlogops-1.2}/src/backlogops/available_teams.py +0 -0
- {backlogops-1.0 → backlogops-1.2}/src/backlogops/backlog.py +0 -0
- {backlogops-1.0 → backlogops-1.2}/src/backlogops/backlog_helpers.py +0 -0
- {backlogops-1.0 → backlogops-1.2}/src/backlogops/backlog_in_release_order.py +0 -0
- {backlogops-1.0 → backlogops-1.2}/src/backlogops/backlog_ops_wizard.py +0 -0
- {backlogops-1.0 → backlogops-1.2}/src/backlogops/backlog_releases.py +0 -0
- {backlogops-1.0 → backlogops-1.2}/src/backlogops/backlog_releases_io.py +0 -0
- {backlogops-1.0 → backlogops-1.2}/src/backlogops/blo_version_reporter.py +0 -0
- {backlogops-1.0 → backlogops-1.2}/src/backlogops/config_descriptions.py +0 -0
- {backlogops-1.0 → backlogops-1.2}/src/backlogops/config_file_io.py +0 -0
- {backlogops-1.0 → backlogops-1.2}/src/backlogops/date_ranges.py +0 -0
- {backlogops-1.0 → backlogops-1.2}/src/backlogops/demo_backlog.py +0 -0
- {backlogops-1.0 → backlogops-1.2}/src/backlogops/estimate_ready_date.py +0 -0
- {backlogops-1.0 → backlogops-1.2}/src/backlogops/format_rules.py +0 -0
- {backlogops-1.0 → backlogops-1.2}/src/backlogops/io_preset_wizard.py +0 -0
- {backlogops-1.0 → backlogops-1.2}/src/backlogops/jira_connect.py +0 -0
- {backlogops-1.0 → backlogops-1.2}/src/backlogops/jira_order_releases.py +0 -0
- {backlogops-1.0 → backlogops-1.2}/src/backlogops/jira_rank_backlog.py +0 -0
- {backlogops-1.0 → backlogops-1.2}/src/backlogops/jira_rank_by_keys.py +0 -0
- {backlogops-1.0 → backlogops-1.2}/src/backlogops/jira_rank_move_keys.py +0 -0
- {backlogops-1.0 → backlogops-1.2}/src/backlogops/jira_read.py +0 -0
- {backlogops-1.0 → backlogops-1.2}/src/backlogops/jira_rename_releases.py +0 -0
- {backlogops-1.0 → backlogops-1.2}/src/backlogops/jira_search.py +0 -0
- {backlogops-1.0 → backlogops-1.2}/src/backlogops/jira_token.py +0 -0
- {backlogops-1.0 → backlogops-1.2}/src/backlogops/jira_update_backlog.py +0 -0
- {backlogops-1.0 → backlogops-1.2}/src/backlogops/jira_update_releases.py +0 -0
- {backlogops-1.0 → backlogops-1.2}/src/backlogops/jira_wizard.py +0 -0
- {backlogops-1.0 → backlogops-1.2}/src/backlogops/jira_write.py +0 -0
- {backlogops-1.0 → backlogops-1.2}/src/backlogops/jira_write_fields.py +0 -0
- {backlogops-1.0 → backlogops-1.2}/src/backlogops/jira_write_format.py +0 -0
- {backlogops-1.0 → backlogops-1.2}/src/backlogops/jira_write_releases.py +0 -0
- {backlogops-1.0 → backlogops-1.2}/src/backlogops/key_list_io.py +0 -0
- {backlogops-1.0 → backlogops-1.2}/src/backlogops/levels.py +0 -0
- {backlogops-1.0 → backlogops-1.2}/src/backlogops/move_keys_first.py +0 -0
- {backlogops-1.0 → backlogops-1.2}/src/backlogops/name_list_io.py +0 -0
- {backlogops-1.0 → backlogops-1.2}/src/backlogops/no_text_io.py +0 -0
- {backlogops-1.0 → backlogops-1.2}/src/backlogops/order_by_dependencies.py +0 -0
- {backlogops-1.0 → backlogops-1.2}/src/backlogops/person.py +0 -0
- {backlogops-1.0 → backlogops-1.2}/src/backlogops/py.typed +0 -0
- {backlogops-1.0 → backlogops-1.2}/src/backlogops/release_backlog_updates.py +0 -0
- {backlogops-1.0 → backlogops-1.2}/src/backlogops/release_change_io.py +0 -0
- {backlogops-1.0 → backlogops-1.2}/src/backlogops/releases.py +0 -0
- {backlogops-1.0 → backlogops-1.2}/src/backlogops/rename_list_io.py +0 -0
- {backlogops-1.0 → backlogops-1.2}/src/backlogops/table_create.py +0 -0
- {backlogops-1.0 → backlogops-1.2}/src/backlogops/table_rows.py +0 -0
- {backlogops-1.0 → backlogops-1.2}/src/backlogops/team.py +0 -0
- {backlogops-1.0 → backlogops-1.2}/src/backlogops/wizard_forms.py +0 -0
- {backlogops-1.0 → backlogops-1.2}/src/backlogops/wizard_helpers.py +0 -0
- {backlogops-1.0 → backlogops-1.2}/src/backlogops/wizard_navigator.py +0 -0
- {backlogops-1.0 → backlogops-1.2}/src/backlogops/work_hours.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: backlogops
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.2
|
|
4
4
|
Summary: Library with backlog operations.
|
|
5
5
|
Author: Tom Björkholm
|
|
6
6
|
Author-email: Tom Björkholm <klausuler_linnet0q@icloud.com>
|
|
@@ -21,14 +21,14 @@ Classifier: Typing :: Typed
|
|
|
21
21
|
Requires-Python: >=3.12
|
|
22
22
|
Description-Content-Type: text/markdown
|
|
23
23
|
License-File: LICENSE.txt
|
|
24
|
-
Requires-Dist: config-as-json>=1.
|
|
25
|
-
Requires-Dist: cryptography>=50.0.
|
|
24
|
+
Requires-Dist: config-as-json>=1.7
|
|
25
|
+
Requires-Dist: cryptography>=50.0.1
|
|
26
26
|
Requires-Dist: jira[cli,opt]>=3.10.5
|
|
27
27
|
Requires-Dist: tableio>=1.1
|
|
28
|
-
Requires-Dist: tableio-cfg-json>=1.
|
|
28
|
+
Requires-Dist: tableio-cfg-json>=1.4
|
|
29
29
|
Requires-Dist: wizard-ui-bridge[textual]>=1.3
|
|
30
30
|
Requires-Dist: versionreporter>=0.4
|
|
31
|
-
Requires-Dist: edit-cfg-json
|
|
31
|
+
Requires-Dist: edit-cfg-json>=0.2.0
|
|
32
32
|
Dynamic: author
|
|
33
33
|
Dynamic: license-file
|
|
34
34
|
Dynamic: requires-dist
|
|
@@ -325,10 +325,10 @@ For the full set of public names see the API documentation linked above.
|
|
|
325
325
|
|
|
326
326
|
## Test summary
|
|
327
327
|
|
|
328
|
-
- Test result:
|
|
328
|
+
- Test result: 2309 passed, 1 deselected in 58s
|
|
329
329
|
- No flake8 warnings.
|
|
330
330
|
- No mypy errors found.
|
|
331
331
|
- No pylint warnings.
|
|
332
332
|
- No python layout warnings.
|
|
333
|
-
- Built version(s): 1.
|
|
333
|
+
- Built version(s): 1.2
|
|
334
334
|
- Build and test using Python 3.14.7
|
|
@@ -289,10 +289,10 @@ For the full set of public names see the API documentation linked above.
|
|
|
289
289
|
|
|
290
290
|
## Test summary
|
|
291
291
|
|
|
292
|
-
- Test result:
|
|
292
|
+
- Test result: 2309 passed, 1 deselected in 58s
|
|
293
293
|
- No flake8 warnings.
|
|
294
294
|
- No mypy errors found.
|
|
295
295
|
- No pylint warnings.
|
|
296
296
|
- No python layout warnings.
|
|
297
|
-
- Built version(s): 1.
|
|
297
|
+
- Built version(s): 1.2
|
|
298
298
|
- Build and test using Python 3.14.7
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: backlogops
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.2
|
|
4
4
|
Summary: Library with backlog operations.
|
|
5
5
|
Author: Tom Björkholm
|
|
6
6
|
Author-email: Tom Björkholm <klausuler_linnet0q@icloud.com>
|
|
@@ -21,14 +21,14 @@ Classifier: Typing :: Typed
|
|
|
21
21
|
Requires-Python: >=3.12
|
|
22
22
|
Description-Content-Type: text/markdown
|
|
23
23
|
License-File: LICENSE.txt
|
|
24
|
-
Requires-Dist: config-as-json>=1.
|
|
25
|
-
Requires-Dist: cryptography>=50.0.
|
|
24
|
+
Requires-Dist: config-as-json>=1.7
|
|
25
|
+
Requires-Dist: cryptography>=50.0.1
|
|
26
26
|
Requires-Dist: jira[cli,opt]>=3.10.5
|
|
27
27
|
Requires-Dist: tableio>=1.1
|
|
28
|
-
Requires-Dist: tableio-cfg-json>=1.
|
|
28
|
+
Requires-Dist: tableio-cfg-json>=1.4
|
|
29
29
|
Requires-Dist: wizard-ui-bridge[textual]>=1.3
|
|
30
30
|
Requires-Dist: versionreporter>=0.4
|
|
31
|
-
Requires-Dist: edit-cfg-json
|
|
31
|
+
Requires-Dist: edit-cfg-json>=0.2.0
|
|
32
32
|
Dynamic: author
|
|
33
33
|
Dynamic: license-file
|
|
34
34
|
Dynamic: requires-dist
|
|
@@ -325,10 +325,10 @@ For the full set of public names see the API documentation linked above.
|
|
|
325
325
|
|
|
326
326
|
## Test summary
|
|
327
327
|
|
|
328
|
-
- Test result:
|
|
328
|
+
- Test result: 2309 passed, 1 deselected in 58s
|
|
329
329
|
- No flake8 warnings.
|
|
330
330
|
- No mypy errors found.
|
|
331
331
|
- No pylint warnings.
|
|
332
332
|
- No python layout warnings.
|
|
333
|
-
- Built version(s): 1.
|
|
333
|
+
- Built version(s): 1.2
|
|
334
334
|
- Build and test using Python 3.14.7
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
config-as-json>=1.
|
|
2
|
-
cryptography>=50.0.
|
|
1
|
+
config-as-json>=1.7
|
|
2
|
+
cryptography>=50.0.1
|
|
3
3
|
jira[cli,opt]>=3.10.5
|
|
4
4
|
tableio>=1.1
|
|
5
|
-
tableio-cfg-json>=1.
|
|
5
|
+
tableio-cfg-json>=1.4
|
|
6
6
|
wizard-ui-bridge[textual]>=1.3
|
|
7
7
|
versionreporter>=0.4
|
|
8
|
-
edit-cfg-json
|
|
8
|
+
edit-cfg-json>=0.2.0
|
|
@@ -5,7 +5,7 @@ from setuptools import setup
|
|
|
5
5
|
|
|
6
6
|
setup(
|
|
7
7
|
name='backlogops',
|
|
8
|
-
version='1.
|
|
8
|
+
version='1.2',
|
|
9
9
|
description='Library with backlog operations.',
|
|
10
10
|
author='Tom Björkholm',
|
|
11
11
|
author_email='klausuler_linnet0q@icloud.com',
|
|
@@ -14,13 +14,13 @@ setup(
|
|
|
14
14
|
package_dir={'backlogops': 'src/backlogops'},
|
|
15
15
|
package_data={'backlogops': ['src/py.typed']},
|
|
16
16
|
install_requires=[
|
|
17
|
-
'config-as-json >= 1.
|
|
18
|
-
'cryptography >= 50.0.
|
|
17
|
+
'config-as-json >= 1.7',
|
|
18
|
+
'cryptography >= 50.0.1',
|
|
19
19
|
'jira[cli,opt] >= 3.10.5',
|
|
20
20
|
'tableio >= 1.1',
|
|
21
|
-
'tableio-cfg-json >= 1.
|
|
21
|
+
'tableio-cfg-json >= 1.4',
|
|
22
22
|
'wizard-ui-bridge[textual] >= 1.3',
|
|
23
23
|
'versionreporter >= 0.4',
|
|
24
|
-
'edit-cfg-json
|
|
24
|
+
'edit-cfg-json >= 0.2.0',
|
|
25
25
|
]
|
|
26
26
|
)
|
|
@@ -117,16 +117,20 @@ class _BridgeConfig(Config):
|
|
|
117
117
|
return {}
|
|
118
118
|
|
|
119
119
|
def __init__(self, from_json_data_text: Optional[str],
|
|
120
|
-
from_json_filename: Optional[PathOrStr],
|
|
121
|
-
|
|
120
|
+
from_json_filename: Optional[PathOrStr], stderr_file: TextIO,
|
|
121
|
+
*, member_name: Optional[str] = None) -> None:
|
|
122
122
|
"""Run the Config lifecycle for a bridge instance.
|
|
123
123
|
|
|
124
124
|
Each bridge first creates its data class attributes, then calls
|
|
125
125
|
this constructor to read JSON, apply defaults, and validate.
|
|
126
|
+
``member_name`` is the path for reaching this object from the top
|
|
127
|
+
level configuration, so that a diagnostic about a value inside it
|
|
128
|
+
names the whole path; it is None for a bridge that is a whole
|
|
129
|
+
configuration file of its own.
|
|
126
130
|
"""
|
|
127
131
|
Config.__init__(self, from_json_data_text=from_json_data_text,
|
|
128
132
|
from_json_filename=from_json_filename,
|
|
129
|
-
stderr_file=stderr_file)
|
|
133
|
+
stderr_file=stderr_file, member_name=member_name)
|
|
130
134
|
|
|
131
135
|
@staticmethod
|
|
132
136
|
def _consistency() -> WholeConfigValidationStep:
|
|
@@ -154,12 +158,13 @@ class FteExceptionConfig(FteException, _BridgeConfig):
|
|
|
154
158
|
|
|
155
159
|
def __init__(self, from_json_data_text: Optional[str] = None,
|
|
156
160
|
from_json_filename: Optional[PathOrStr] = None,
|
|
157
|
-
stderr_file: TextIO = sys.stderr
|
|
161
|
+
stderr_file: TextIO = sys.stderr, *,
|
|
162
|
+
member_name: Optional[str] = None) -> None:
|
|
158
163
|
"""Create placeholder defaults, then read one FTE exception."""
|
|
159
164
|
FteException.__init__(self, start_date=date(2000, 1, 1),
|
|
160
165
|
end_date=date(2000, 1, 1), fte=1.0)
|
|
161
166
|
_BridgeConfig.__init__(self, from_json_data_text, from_json_filename,
|
|
162
|
-
stderr_file)
|
|
167
|
+
stderr_file, member_name=member_name)
|
|
163
168
|
|
|
164
169
|
@override
|
|
165
170
|
def get_validation_plan(self, stderr_file: TextIO) -> ValidationPlan:
|
|
@@ -179,13 +184,14 @@ class ExceptionWorkHoursConfig(ExceptionWorkHours, _BridgeConfig):
|
|
|
179
184
|
|
|
180
185
|
def __init__(self, from_json_data_text: Optional[str] = None,
|
|
181
186
|
from_json_filename: Optional[PathOrStr] = None,
|
|
182
|
-
stderr_file: TextIO = sys.stderr
|
|
187
|
+
stderr_file: TextIO = sys.stderr, *,
|
|
188
|
+
member_name: Optional[str] = None) -> None:
|
|
183
189
|
"""Create placeholder defaults, then read one work-hours exception."""
|
|
184
190
|
ExceptionWorkHours.__init__(self, start_date=date(2000, 1, 1),
|
|
185
191
|
end_date=date(2000, 1, 1),
|
|
186
192
|
hours_per_day=0.0)
|
|
187
193
|
_BridgeConfig.__init__(self, from_json_data_text, from_json_filename,
|
|
188
|
-
stderr_file)
|
|
194
|
+
stderr_file, member_name=member_name)
|
|
189
195
|
|
|
190
196
|
@override
|
|
191
197
|
def get_validation_plan(self, stderr_file: TextIO) -> ValidationPlan:
|
|
@@ -205,11 +211,12 @@ class MembershipConfig(Membership, _BridgeConfig):
|
|
|
205
211
|
|
|
206
212
|
def __init__(self, from_json_data_text: Optional[str] = None,
|
|
207
213
|
from_json_filename: Optional[PathOrStr] = None,
|
|
208
|
-
stderr_file: TextIO = sys.stderr
|
|
214
|
+
stderr_file: TextIO = sys.stderr, *,
|
|
215
|
+
member_name: Optional[str] = None) -> None:
|
|
209
216
|
"""Create placeholder defaults, then read one membership."""
|
|
210
217
|
Membership.__init__(self, person_name='person')
|
|
211
218
|
_BridgeConfig.__init__(self, from_json_data_text, from_json_filename,
|
|
212
|
-
stderr_file)
|
|
219
|
+
stderr_file, member_name=member_name)
|
|
213
220
|
|
|
214
221
|
@override
|
|
215
222
|
def nested_configs(self) -> NestedConfigs:
|
|
@@ -241,12 +248,13 @@ class TeamConfig(Team, _BridgeConfig):
|
|
|
241
248
|
|
|
242
249
|
def __init__(self, from_json_data_text: Optional[str] = None,
|
|
243
250
|
from_json_filename: Optional[PathOrStr] = None,
|
|
244
|
-
stderr_file: TextIO = sys.stderr
|
|
251
|
+
stderr_file: TextIO = sys.stderr, *,
|
|
252
|
+
member_name: Optional[str] = None) -> None:
|
|
245
253
|
"""Create placeholder defaults, then read one team."""
|
|
246
254
|
Team.__init__(self, name='team', velocity=0.0, sum_fte_at_velocity=1.0,
|
|
247
255
|
sprint_length=1)
|
|
248
256
|
_BridgeConfig.__init__(self, from_json_data_text, from_json_filename,
|
|
249
|
-
stderr_file)
|
|
257
|
+
stderr_file, member_name=member_name)
|
|
250
258
|
|
|
251
259
|
@override
|
|
252
260
|
def nested_configs(self) -> NestedConfigs:
|
|
@@ -266,11 +274,12 @@ class PersonConfig(Person, _BridgeConfig):
|
|
|
266
274
|
|
|
267
275
|
def __init__(self, from_json_data_text: Optional[str] = None,
|
|
268
276
|
from_json_filename: Optional[PathOrStr] = None,
|
|
269
|
-
stderr_file: TextIO = sys.stderr
|
|
277
|
+
stderr_file: TextIO = sys.stderr, *,
|
|
278
|
+
member_name: Optional[str] = None) -> None:
|
|
270
279
|
"""Create placeholder defaults, then read one person."""
|
|
271
280
|
Person.__init__(self, name='person')
|
|
272
281
|
_BridgeConfig.__init__(self, from_json_data_text, from_json_filename,
|
|
273
|
-
stderr_file)
|
|
282
|
+
stderr_file, member_name=member_name)
|
|
274
283
|
|
|
275
284
|
@override
|
|
276
285
|
def nested_configs(self) -> NestedConfigs:
|
|
@@ -291,12 +300,13 @@ class CompanyWorkHoursConfig(CompanyWorkHours, _BridgeConfig):
|
|
|
291
300
|
|
|
292
301
|
def __init__(self, from_json_data_text: Optional[str] = None,
|
|
293
302
|
from_json_filename: Optional[PathOrStr] = None,
|
|
294
|
-
stderr_file: TextIO = sys.stderr
|
|
303
|
+
stderr_file: TextIO = sys.stderr, *,
|
|
304
|
+
member_name: Optional[str] = None) -> None:
|
|
295
305
|
"""Create defaults, then read the company work hours."""
|
|
296
306
|
CompanyWorkHours.__init__(self)
|
|
297
307
|
self._unchecked_dicts = ['work_hours']
|
|
298
308
|
_BridgeConfig.__init__(self, from_json_data_text, from_json_filename,
|
|
299
|
-
stderr_file)
|
|
309
|
+
stderr_file, member_name=member_name)
|
|
300
310
|
|
|
301
311
|
@override
|
|
302
312
|
def nested_configs(self) -> NestedConfigs:
|
|
@@ -328,7 +338,8 @@ class AvailableTeamsConfig(AvailableTeams, _BridgeConfig):
|
|
|
328
338
|
def __init__(self, *, neutral: Optional[AvailableTeams] = None,
|
|
329
339
|
from_json_data_text: Optional[str] = None,
|
|
330
340
|
from_json_filename: Optional[PathOrStr] = None,
|
|
331
|
-
stderr_file: TextIO = sys.stderr
|
|
341
|
+
stderr_file: TextIO = sys.stderr,
|
|
342
|
+
member_name: Optional[str] = None) -> None:
|
|
332
343
|
"""Create the bridge from a neutral workforce or from JSON.
|
|
333
344
|
|
|
334
345
|
``AvailableTeams.__init__`` is intentionally not invoked because
|
|
@@ -340,7 +351,7 @@ class AvailableTeamsConfig(AvailableTeams, _BridgeConfig):
|
|
|
340
351
|
neutral = AvailableTeams(persons={}, teams=[])
|
|
341
352
|
Config.copy_initial_data(neutral, self)
|
|
342
353
|
_BridgeConfig.__init__(self, from_json_data_text, from_json_filename,
|
|
343
|
-
stderr_file)
|
|
354
|
+
stderr_file, member_name=member_name)
|
|
344
355
|
|
|
345
356
|
@override
|
|
346
357
|
def nested_configs(self) -> NestedConfigs:
|
|
@@ -17,7 +17,10 @@ item levels:
|
|
|
17
17
|
:class:`backlogops.jira_io_config.JiraIOConfig`;
|
|
18
18
|
* ``levels`` is the optional list of backlog item levels. It is omitted
|
|
19
19
|
from the file while it is ``None``; :meth:`BacklogOpsConfig.get_levels`
|
|
20
|
-
then falls back to :data:`backlogops.levels.DEFAULT_LEVELS`.
|
|
20
|
+
then falls back to :data:`backlogops.levels.DEFAULT_LEVELS`. An empty
|
|
21
|
+
list is refused, because it would mean no levels at all where the
|
|
22
|
+
omitted member means the built-in ones, and the configuration editor
|
|
23
|
+
offers giving that member an empty list.
|
|
21
24
|
|
|
22
25
|
Earlier file versions stored the workforce members (``persons``,
|
|
23
26
|
``teams`` and ``company_work_hours``) at the top level next to the
|
|
@@ -36,7 +39,8 @@ from config_as_json import CallingWholeConfigValidator, Config, \
|
|
|
36
39
|
ConfigAutoChangeHook, ConfigNesting, ConfigNestingKind, ConfigPath, \
|
|
37
40
|
JsonType, MemberValidationStep, MemberValidator, NestedConfigs, \
|
|
38
41
|
PathOrStr, ReadOldConfiguration, RocfKeyMove, SerializeConverter, \
|
|
39
|
-
SerializeConverters, ValidationPlan, WholeConfigValidationStep
|
|
42
|
+
SerializeConverters, ValidationPlan, WholeConfigValidationStep, \
|
|
43
|
+
member_path
|
|
40
44
|
from backlogops.available_teams import AvailableTeams
|
|
41
45
|
from backlogops.available_teams_config import AvailableTeamsConfig
|
|
42
46
|
from backlogops.backlog import Status
|
|
@@ -72,19 +76,32 @@ def _as_str_list(name: str, value: object, stderr_file: TextIO) -> list[str]:
|
|
|
72
76
|
return result
|
|
73
77
|
|
|
74
78
|
|
|
75
|
-
def _level_from_dict(data: dict[str, object],
|
|
76
|
-
|
|
79
|
+
def _level_from_dict(name: str, data: dict[str, object],
|
|
80
|
+
stderr_file: TextIO) -> Level:
|
|
81
|
+
"""Return one Level from its JSON object, checking the field shape.
|
|
82
|
+
|
|
83
|
+
Args:
|
|
84
|
+
name: Reported path of the level itself, such as ``levels[2]``,
|
|
85
|
+
which each field name is appended to.
|
|
86
|
+
data: The JSON object holding the fields of one level.
|
|
87
|
+
stderr_file: The file to report errors to.
|
|
88
|
+
|
|
89
|
+
Returns:
|
|
90
|
+
The level the JSON object describes.
|
|
91
|
+
"""
|
|
77
92
|
unknown = sorted(set(data) - {'level', 'name', 'aliases'})
|
|
78
93
|
if unknown:
|
|
79
|
-
report_bad_value(
|
|
94
|
+
report_bad_value(name, data, f'unknown level fields {unknown}',
|
|
80
95
|
stderr_file, 'Level')
|
|
81
96
|
if 'level' not in data or 'name' not in data:
|
|
82
|
-
report_bad_value(
|
|
97
|
+
report_bad_value(name, data, 'requires "level" and "name"',
|
|
83
98
|
stderr_file, 'Level')
|
|
84
|
-
return Level(level=_as_int('level', data['level'],
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
99
|
+
return Level(level=_as_int(member_path(name, 'level'), data['level'],
|
|
100
|
+
stderr_file),
|
|
101
|
+
name=_as_str(member_path(name, 'name'), data['name'],
|
|
102
|
+
stderr_file),
|
|
103
|
+
aliases=_as_str_list(member_path(name, 'aliases'),
|
|
104
|
+
data.get('aliases', []), stderr_file))
|
|
88
105
|
|
|
89
106
|
|
|
90
107
|
def _level_from_obj(name: str, value: object, stderr_file: TextIO) -> Level:
|
|
@@ -93,7 +110,13 @@ def _level_from_obj(name: str, value: object, stderr_file: TextIO) -> Level:
|
|
|
93
110
|
return value
|
|
94
111
|
if not isinstance(value, dict):
|
|
95
112
|
report_wrong_type(name, value, dict, stderr_file, 'Level')
|
|
96
|
-
return _level_from_dict(value, stderr_file)
|
|
113
|
+
return _level_from_dict(name, value, stderr_file)
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
_NO_LEVELS = ('no levels at all; a configuration that leaves the levels out '
|
|
117
|
+
'uses the built-in ones, so take the member away rather than '
|
|
118
|
+
'emptying it')
|
|
119
|
+
"""Why an empty list of levels is not a configuration with no levels."""
|
|
97
120
|
|
|
98
121
|
|
|
99
122
|
# pylint: disable-next=too-few-public-methods
|
|
@@ -104,13 +127,23 @@ class _LevelsMember(MemberValidator):
|
|
|
104
127
|
def validate_member(self, config: Config, member_name: str,
|
|
105
128
|
member_value: object,
|
|
106
129
|
stderr_file: TextIO = sys.stderr) -> Optional[object]:
|
|
107
|
-
"""Return the levels as a list of ``Level``, or ``None``.
|
|
130
|
+
"""Return the levels as a list of ``Level``, or ``None``.
|
|
131
|
+
|
|
132
|
+
Raises:
|
|
133
|
+
TypeError: The member holds something that is no list of
|
|
134
|
+
levels.
|
|
135
|
+
ValueError: The member holds an empty list, which is not a
|
|
136
|
+
configuration of the levels; leaving the member out is.
|
|
137
|
+
"""
|
|
108
138
|
_ = config
|
|
109
139
|
if member_value is None:
|
|
110
140
|
return None
|
|
111
141
|
if not isinstance(member_value, list):
|
|
112
142
|
report_wrong_type(member_name, member_value, list, stderr_file,
|
|
113
143
|
'BacklogOps config')
|
|
144
|
+
if not member_value:
|
|
145
|
+
report_bad_value(member_name, member_value, _NO_LEVELS,
|
|
146
|
+
stderr_file, 'BacklogOps config')
|
|
114
147
|
return [_level_from_obj(f'{member_name}[{index}]', element,
|
|
115
148
|
stderr_file)
|
|
116
149
|
for index, element in enumerate(member_value)]
|
|
@@ -173,11 +206,15 @@ DEF_STATUS_INPUT_MAP: dict[str, Status] = {
|
|
|
173
206
|
class BacklogOpsConfig(Config): # pylint: disable=too-many-instance-attributes
|
|
174
207
|
"""Top-level backlog-ops configuration stored as config-as-json."""
|
|
175
208
|
|
|
209
|
+
# The library contract fixes five of these; the workforce is the one
|
|
210
|
+
# argument of this application, and every one of them is keyword only.
|
|
211
|
+
# pylint: disable-next=too-many-arguments
|
|
176
212
|
def __init__(self, *, available_teams: Optional[AvailableTeams] = None,
|
|
177
213
|
from_json_data_text: Optional[str] = None,
|
|
178
214
|
from_json_filename: Optional[PathOrStr] = None,
|
|
179
215
|
auto_ch_hook: Optional[ConfigAutoChangeHook] = None,
|
|
180
|
-
stderr_file: TextIO = sys.stderr
|
|
216
|
+
stderr_file: TextIO = sys.stderr,
|
|
217
|
+
member_name: Optional[str] = None) -> None:
|
|
181
218
|
"""Create defaults, or read the configuration from JSON.
|
|
182
219
|
|
|
183
220
|
The supplied workforce establishes the schema of the nested
|
|
@@ -185,7 +222,11 @@ class BacklogOpsConfig(Config): # pylint: disable=too-many-instance-attributes
|
|
|
185
222
|
into an :class:`AvailableTeamsConfig`. The presets default to
|
|
186
223
|
empty maps and the levels default to ``None`` (use the defaults).
|
|
187
224
|
The ``auto_ch_hook`` is notified when an old file needed
|
|
188
|
-
backward-compatible normalization while reading.
|
|
225
|
+
backward-compatible normalization while reading. The default
|
|
226
|
+
nested sections are created under the path of the member holding
|
|
227
|
+
each of them, so that a diagnostic names the whole path even
|
|
228
|
+
before any file is read; ``member_name`` is None for a whole
|
|
229
|
+
configuration file, which is a member of nothing.
|
|
189
230
|
"""
|
|
190
231
|
self.available_teams: AvailableTeams = (
|
|
191
232
|
AvailableTeams(persons={}, teams=[]) if available_teams is None
|
|
@@ -193,14 +234,18 @@ class BacklogOpsConfig(Config): # pylint: disable=too-many-instance-attributes
|
|
|
193
234
|
self.input_configs: dict[str, InputFormatConfig] = {}
|
|
194
235
|
self.output_configs: dict[str, OutputFormatConfig] = {}
|
|
195
236
|
self.gui_display: GuiDisplayConfig = GuiDisplayConfig(
|
|
196
|
-
stderr_file=stderr_file
|
|
237
|
+
stderr_file=stderr_file,
|
|
238
|
+
member_name=member_path(member_name, 'gui_display'))
|
|
197
239
|
self.status_input_map: dict[str, Status] = DEF_STATUS_INPUT_MAP
|
|
198
|
-
self.jira: JiraIOConfig = JiraIOConfig(
|
|
240
|
+
self.jira: JiraIOConfig = JiraIOConfig(
|
|
241
|
+
stderr_file=stderr_file,
|
|
242
|
+
member_name=member_path(member_name, 'jira'))
|
|
199
243
|
self.levels: Optional[list[Level]] = None
|
|
200
244
|
self._unchecked_dicts = ['status_input_map']
|
|
201
245
|
Config.__init__(self, from_json_data_text=from_json_data_text,
|
|
202
246
|
from_json_filename=from_json_filename,
|
|
203
|
-
auto_ch_hook=auto_ch_hook, stderr_file=stderr_file
|
|
247
|
+
auto_ch_hook=auto_ch_hook, stderr_file=stderr_file,
|
|
248
|
+
member_name=member_name)
|
|
204
249
|
|
|
205
250
|
@override
|
|
206
251
|
def _get_read_old_config(self) -> ReadOldConfiguration:
|
|
@@ -27,19 +27,39 @@ toolkit mounts the editor itself — ``edit_cfg_json_tk.TkEditorPanel`` in a
|
|
|
27
27
|
window of the application, ``edit_cfg_json_textual.edit`` in a terminal of
|
|
28
28
|
its own — and hands those two answers to it.
|
|
29
29
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
30
|
+
How many things a member holds is the editor's to change as well, so a
|
|
31
|
+
named preset, a Jira connection, a person, a team, a membership, an
|
|
32
|
+
exception, a level and an entry of any of the maps can each be added beside
|
|
33
|
+
the ones that are there, taken out again, and moved within a list. A new
|
|
34
|
+
element is never invented: it is an object of the class the declaration
|
|
35
|
+
names, a copy of what the container holds now, or the empty value that the
|
|
36
|
+
declared type of the member says an element is. That is what the first of
|
|
37
|
+
the notes below follows from.
|
|
38
|
+
|
|
39
|
+
Four things are worth knowing before the editor is offered instead of the
|
|
40
|
+
wizard:
|
|
41
|
+
|
|
42
|
+
* One entry of the Jira column maps and of the issue-type maps is a map of
|
|
43
|
+
its own, which the class does not name a type for, so there is no pattern
|
|
44
|
+
for one until the file holds one to copy: an empty map of those offers
|
|
45
|
+
nothing and says why below itself. Every other container can be given its
|
|
46
|
+
first element, because the class names the type of one or its declared
|
|
47
|
+
type says what an element is.
|
|
48
|
+
* The levels keep a row in a configuration that leaves them out, because a
|
|
49
|
+
member the class omits is still a member. What that row offers is an
|
|
50
|
+
empty list, which is not what leaving the levels out means and is
|
|
51
|
+
refused as such: the row's other control puts the member back to holding
|
|
52
|
+
nothing, which is the built-in levels. Writing the levels the first time
|
|
53
|
+
is the wizard's.
|
|
40
54
|
* A person is keyed by their own name in lower case, so renaming one means
|
|
41
55
|
adding an entry under the new key and removing the old one; editing the
|
|
42
56
|
name alone leaves a configuration the class refuses.
|
|
57
|
+
* The editor reads the declarations of a class and not the insides of its
|
|
58
|
+
validators, so it offers a change that this library then refuses where
|
|
59
|
+
only a validator knows better: a week day taken out of the company
|
|
60
|
+
schedule, or a level that loses its name, because a level is a plain
|
|
61
|
+
object in the file rather than a nested configuration class. What the
|
|
62
|
+
class said is shown at the member it is about.
|
|
43
63
|
"""
|
|
44
64
|
|
|
45
65
|
# Copyright (c) 2026, Tom Björkholm
|
|
@@ -48,7 +48,7 @@ from config_as_json import Config, ConfigAutoChangeHook, ConfigNesting, \
|
|
|
48
48
|
ConfigNestingKind, ConfigPath, InvalidConfiguration, \
|
|
49
49
|
MemberValidationStep, MemberValidator, NestedConfigs, ParseConverter, \
|
|
50
50
|
PathOrStr, ReadOldConfiguration, RocfKeyMove, RocfValueMigration, \
|
|
51
|
-
RocfValueWrite, ValidationPlan
|
|
51
|
+
RocfValueWrite, ValidationPlan, member_path
|
|
52
52
|
from tableio import Capabilities, FileAccess, access_capabilities
|
|
53
53
|
from tableio_cfg_json import TioJsonConfig, tio_json_config_default
|
|
54
54
|
from backlogops.backlog import Status
|
|
@@ -195,23 +195,25 @@ def _capabilities(file_access: FileAccess, stderr_file: TextIO
|
|
|
195
195
|
|
|
196
196
|
|
|
197
197
|
def _tio_default(file_access: FileAccess, format_name: Optional[str] = None,
|
|
198
|
-
stderr_file: TextIO = sys.stderr
|
|
198
|
+
stderr_file: TextIO = sys.stderr, *,
|
|
199
|
+
member_name: Optional[str] = None) -> TioJsonConfig:
|
|
199
200
|
"""Return a default TableIO config for a format and file access."""
|
|
200
201
|
return tio_json_config_default(
|
|
201
202
|
capabilities=_capabilities(file_access, stderr_file),
|
|
202
203
|
file_access=file_access, format_name=format_name,
|
|
203
|
-
stderr_file=stderr_file)
|
|
204
|
+
stderr_file=stderr_file, member_name=member_name)
|
|
204
205
|
|
|
205
206
|
|
|
206
207
|
def _tio_from_json(file_access: FileAccess, from_json_data_text: Optional[str],
|
|
207
208
|
from_json_filename: Optional[PathOrStr],
|
|
208
|
-
stderr_file: TextIO
|
|
209
|
+
stderr_file: TextIO,
|
|
210
|
+
member_name: Optional[str]) -> TioJsonConfig:
|
|
209
211
|
"""Return a TableIO config read from JSON for a file access mode."""
|
|
210
212
|
return TioJsonConfig(capabilities=_capabilities(file_access, stderr_file),
|
|
211
213
|
file_access=file_access,
|
|
212
214
|
from_json_data_text=from_json_data_text,
|
|
213
215
|
from_json_filename=from_json_filename,
|
|
214
|
-
stderr_file=stderr_file)
|
|
216
|
+
stderr_file=stderr_file, member_name=member_name)
|
|
215
217
|
|
|
216
218
|
|
|
217
219
|
class _FormatConfig(Config):
|
|
@@ -230,22 +232,31 @@ class _FormatConfig(Config):
|
|
|
230
232
|
def __init__(self, from_json_data_text: Optional[str] = None,
|
|
231
233
|
from_json_filename: Optional[PathOrStr] = None,
|
|
232
234
|
auto_ch_hook: Optional[ConfigAutoChangeHook] = None,
|
|
233
|
-
stderr_file: TextIO = sys.stderr
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
235
|
+
stderr_file: TextIO = sys.stderr, *,
|
|
236
|
+
member_name: Optional[str] = None) -> None:
|
|
237
|
+
"""Create default settings or read them from a JSON source.
|
|
238
|
+
|
|
239
|
+
The default TableIO endpoint is created under the path of the
|
|
240
|
+
``tableio`` member of this endpoint, so that a TableIO diagnostic
|
|
241
|
+
names which preset it is about even before any file is read.
|
|
242
|
+
"""
|
|
243
|
+
self.tableio: TioJsonConfig = _tio_default(
|
|
244
|
+
self._FILE_ACCESS, stderr_file=stderr_file,
|
|
245
|
+
member_name=member_path(member_name, 'tableio'))
|
|
237
246
|
self._unchecked_dicts = list(self._MAP_NAMES) + \
|
|
238
247
|
list(self._UNCHECKED_EXTRA)
|
|
239
248
|
Config.__init__(self, from_json_data_text=from_json_data_text,
|
|
240
249
|
from_json_filename=from_json_filename,
|
|
241
|
-
auto_ch_hook=auto_ch_hook, stderr_file=stderr_file
|
|
250
|
+
auto_ch_hook=auto_ch_hook, stderr_file=stderr_file,
|
|
251
|
+
member_name=member_name)
|
|
242
252
|
|
|
243
253
|
def _tio_factory(self, *, from_json_data_text: Optional[str] = None,
|
|
244
254
|
from_json_filename: Optional[PathOrStr] = None,
|
|
245
|
-
stderr_file: TextIO = sys.stderr
|
|
255
|
+
stderr_file: TextIO = sys.stderr,
|
|
256
|
+
member_name: Optional[str] = None) -> TioJsonConfig:
|
|
246
257
|
"""Construct the nested TableIO config from JSON when reading."""
|
|
247
258
|
return _tio_from_json(self._FILE_ACCESS, from_json_data_text,
|
|
248
|
-
from_json_filename, stderr_file)
|
|
259
|
+
from_json_filename, stderr_file, member_name)
|
|
249
260
|
|
|
250
261
|
def _map_validator(self) -> MemberValidator:
|
|
251
262
|
"""Return the validator applied to each column-name map member."""
|
|
@@ -334,7 +345,8 @@ class InputFormatConfig(_FormatConfig):
|
|
|
334
345
|
def __init__(self, from_json_data_text: Optional[str] = None,
|
|
335
346
|
from_json_filename: Optional[PathOrStr] = None,
|
|
336
347
|
auto_ch_hook: Optional[ConfigAutoChangeHook] = None,
|
|
337
|
-
stderr_file: TextIO = sys.stderr
|
|
348
|
+
stderr_file: TextIO = sys.stderr, *,
|
|
349
|
+
member_name: Optional[str] = None) -> None:
|
|
338
350
|
"""Create the input map defaults, then run the shared constructor."""
|
|
339
351
|
self.backlog_to_internal = {}
|
|
340
352
|
self.release_to_internal = {}
|
|
@@ -342,7 +354,8 @@ class InputFormatConfig(_FormatConfig):
|
|
|
342
354
|
_FormatConfig.__init__(self, from_json_data_text=from_json_data_text,
|
|
343
355
|
from_json_filename=from_json_filename,
|
|
344
356
|
auto_ch_hook=auto_ch_hook,
|
|
345
|
-
stderr_file=stderr_file
|
|
357
|
+
stderr_file=stderr_file,
|
|
358
|
+
member_name=member_name)
|
|
346
359
|
|
|
347
360
|
@override
|
|
348
361
|
def _get_read_old_config(self) -> ReadOldConfiguration:
|
|
@@ -381,7 +394,8 @@ class OutputFormatConfig(_FormatConfig):
|
|
|
381
394
|
def __init__(self, from_json_data_text: Optional[str] = None,
|
|
382
395
|
from_json_filename: Optional[PathOrStr] = None,
|
|
383
396
|
auto_ch_hook: Optional[ConfigAutoChangeHook] = None,
|
|
384
|
-
stderr_file: TextIO = sys.stderr
|
|
397
|
+
stderr_file: TextIO = sys.stderr, *,
|
|
398
|
+
member_name: Optional[str] = None) -> None:
|
|
385
399
|
"""Create the output defaults, then run the shared constructor."""
|
|
386
400
|
self.backlog_to_external = {}
|
|
387
401
|
self.release_to_external = {}
|
|
@@ -389,7 +403,8 @@ class OutputFormatConfig(_FormatConfig):
|
|
|
389
403
|
_FormatConfig.__init__(self, from_json_data_text=from_json_data_text,
|
|
390
404
|
from_json_filename=from_json_filename,
|
|
391
405
|
auto_ch_hook=auto_ch_hook,
|
|
392
|
-
stderr_file=stderr_file
|
|
406
|
+
stderr_file=stderr_file,
|
|
407
|
+
member_name=member_name)
|
|
393
408
|
|
|
394
409
|
@override
|
|
395
410
|
def parse_converters(self) -> dict[str, ParseConverter]:
|
|
@@ -450,7 +465,8 @@ class GuiDisplayConfig(Config):
|
|
|
450
465
|
|
|
451
466
|
def __init__(self, from_json_data_text: Optional[str] = None,
|
|
452
467
|
from_json_filename: Optional[PathOrStr] = None,
|
|
453
|
-
stderr_file: TextIO = sys.stderr
|
|
468
|
+
stderr_file: TextIO = sys.stderr, *,
|
|
469
|
+
member_name: Optional[str] = None) -> None:
|
|
454
470
|
"""Create the display defaults, then read them from JSON."""
|
|
455
471
|
self.backlog_to_external = {}
|
|
456
472
|
self.release_to_external = {}
|
|
@@ -458,7 +474,7 @@ class GuiDisplayConfig(Config):
|
|
|
458
474
|
self._unchecked_dicts = ['backlog_to_external', 'release_to_external']
|
|
459
475
|
Config.__init__(self, from_json_data_text=from_json_data_text,
|
|
460
476
|
from_json_filename=from_json_filename,
|
|
461
|
-
stderr_file=stderr_file)
|
|
477
|
+
stderr_file=stderr_file, member_name=member_name)
|
|
462
478
|
|
|
463
479
|
@override
|
|
464
480
|
def parse_converters(self) -> dict[str, ParseConverter]:
|
|
@@ -420,7 +420,8 @@ class JiraConnectConfig(Config):
|
|
|
420
420
|
def __init__(self, from_json_data_text: Optional[str] = None,
|
|
421
421
|
from_json_filename: Optional[PathOrStr] = None,
|
|
422
422
|
auto_ch_hook: Optional[ConfigAutoChangeHook] = None,
|
|
423
|
-
stderr_file: TextIO = sys.stderr
|
|
423
|
+
stderr_file: TextIO = sys.stderr, *,
|
|
424
|
+
member_name: Optional[str] = None) -> None:
|
|
424
425
|
"""Create connection defaults, then read them from JSON."""
|
|
425
426
|
self.jira_type = JiraType.CLOUD
|
|
426
427
|
self.base_url = ''
|
|
@@ -431,7 +432,8 @@ class JiraConnectConfig(Config):
|
|
|
431
432
|
self._cached_token: Optional[str] = None
|
|
432
433
|
Config.__init__(self, from_json_data_text=from_json_data_text,
|
|
433
434
|
from_json_filename=from_json_filename,
|
|
434
|
-
auto_ch_hook=auto_ch_hook, stderr_file=stderr_file
|
|
435
|
+
auto_ch_hook=auto_ch_hook, stderr_file=stderr_file,
|
|
436
|
+
member_name=member_name)
|
|
435
437
|
|
|
436
438
|
@override
|
|
437
439
|
def _omit_none_from_json(self) -> list[str]:
|
|
@@ -600,7 +602,8 @@ class JiraPreset(Config):
|
|
|
600
602
|
def __init__(self, from_json_data_text: Optional[str] = None,
|
|
601
603
|
from_json_filename: Optional[PathOrStr] = None,
|
|
602
604
|
auto_ch_hook: Optional[ConfigAutoChangeHook] = None,
|
|
603
|
-
stderr_file: TextIO = sys.stderr
|
|
605
|
+
stderr_file: TextIO = sys.stderr, *,
|
|
606
|
+
member_name: Optional[str] = None) -> None:
|
|
604
607
|
"""Create preset defaults, then read them from JSON."""
|
|
605
608
|
self.connection_name = ''
|
|
606
609
|
self.backlog_column_map_name = ''
|
|
@@ -611,7 +614,8 @@ class JiraPreset(Config):
|
|
|
611
614
|
self.def_filter = ''
|
|
612
615
|
Config.__init__(self, from_json_data_text=from_json_data_text,
|
|
613
616
|
from_json_filename=from_json_filename,
|
|
614
|
-
auto_ch_hook=auto_ch_hook, stderr_file=stderr_file
|
|
617
|
+
auto_ch_hook=auto_ch_hook, stderr_file=stderr_file,
|
|
618
|
+
member_name=member_name)
|
|
615
619
|
|
|
616
620
|
@override
|
|
617
621
|
def _get_read_old_config(self) -> ReadOldConfiguration:
|
|
@@ -695,7 +699,8 @@ class JiraIOConfig(Config):
|
|
|
695
699
|
def __init__(self, from_json_data_text: Optional[str] = None,
|
|
696
700
|
from_json_filename: Optional[PathOrStr] = None,
|
|
697
701
|
auto_ch_hook: Optional[ConfigAutoChangeHook] = None,
|
|
698
|
-
stderr_file: TextIO = sys.stderr
|
|
702
|
+
stderr_file: TextIO = sys.stderr, *,
|
|
703
|
+
member_name: Optional[str] = None) -> None:
|
|
699
704
|
"""Create empty defaults, then read the jira configuration."""
|
|
700
705
|
self.connections: dict[str, JiraConnectConfig] = {}
|
|
701
706
|
self.backlog_column_maps: dict[str, JiraColumnMap] = {}
|
|
@@ -706,7 +711,8 @@ class JiraIOConfig(Config):
|
|
|
706
711
|
'issue_type_maps']
|
|
707
712
|
Config.__init__(self, from_json_data_text=from_json_data_text,
|
|
708
713
|
from_json_filename=from_json_filename,
|
|
709
|
-
auto_ch_hook=auto_ch_hook, stderr_file=stderr_file
|
|
714
|
+
auto_ch_hook=auto_ch_hook, stderr_file=stderr_file,
|
|
715
|
+
member_name=member_name)
|
|
710
716
|
|
|
711
717
|
@override
|
|
712
718
|
def _get_read_old_config(self) -> ReadOldConfiguration:
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|