pycforge 0.15.2__py3-none-any.whl
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.
- pycforge/__init__.py +8 -0
- pycforge/__main__.py +2 -0
- pycforge/_version.py +1 -0
- pycforge/converter/__init__.py +0 -0
- pycforge/converter/analysis/__init__.py +5 -0
- pycforge/converter/analysis/functions.py +723 -0
- pycforge/converter/analysis/model.py +158 -0
- pycforge/converter/analysis/planning.py +464 -0
- pycforge/converter/analysis/stage.py +1976 -0
- pycforge/converter/analysis/symbols.py +237 -0
- pycforge/converter/analysis/validation.py +2166 -0
- pycforge/converter/c_output/__init__.py +2 -0
- pycforge/converter/c_output/conformance.py +297 -0
- pycforge/converter/c_output/renderer.py +220 -0
- pycforge/converter/conditional_regions/__init__.py +71 -0
- pycforge/converter/conditional_regions/analysis.py +481 -0
- pycforge/converter/conditional_regions/lowering.py +579 -0
- pycforge/converter/conditional_regions/model.py +243 -0
- pycforge/converter/conditional_regions/validation.py +690 -0
- pycforge/converter/containers/__init__.py +19 -0
- pycforge/converter/containers/analysis.py +542 -0
- pycforge/converter/containers/lowering.py +290 -0
- pycforge/converter/containers/model.py +146 -0
- pycforge/converter/contracts/__init__.py +0 -0
- pycforge/converter/contracts/configuration.py +178 -0
- pycforge/converter/contracts/identifiers.py +68 -0
- pycforge/converter/contracts/versions.py +71 -0
- pycforge/converter/core/__init__.py +0 -0
- pycforge/converter/core/artifact_io.py +87 -0
- pycforge/converter/core/cancellation.py +7 -0
- pycforge/converter/core/canonicalization.py +254 -0
- pycforge/converter/core/context.py +13 -0
- pycforge/converter/core/diagnostics.py +95 -0
- pycforge/converter/core/enums.py +23 -0
- pycforge/converter/core/fingerprint.py +22 -0
- pycforge/converter/core/pipeline.py +8 -0
- pycforge/converter/core/progress.py +25 -0
- pycforge/converter/core/request.py +50 -0
- pycforge/converter/core/resource_policy.py +31 -0
- pycforge/converter/core/result.py +23 -0
- pycforge/converter/core/serialization.py +36 -0
- pycforge/converter/core/stage.py +10 -0
- pycforge/converter/core/stage_artifact.py +80 -0
- pycforge/converter/core/stage_outcome.py +15 -0
- pycforge/converter/decision_trace/__init__.py +0 -0
- pycforge/converter/decision_trace/recorder.py +52 -0
- pycforge/converter/facade.py +459 -0
- pycforge/converter/frontend/__init__.py +4 -0
- pycforge/converter/frontend/normalizer.py +59 -0
- pycforge/converter/frontend/parser.py +20 -0
- pycforge/converter/frontend/source_document.py +93 -0
- pycforge/converter/frontend/stages.py +518 -0
- pycforge/converter/frontend/validation.py +76 -0
- pycforge/converter/io/__init__.py +0 -0
- pycforge/converter/io/atomic_writer.py +33 -0
- pycforge/converter/ir/__init__.py +1 -0
- pycforge/converter/ir/c_ir/__init__.py +4 -0
- pycforge/converter/ir/c_ir/builder.py +26 -0
- pycforge/converter/ir/c_ir/model.py +318 -0
- pycforge/converter/ir/c_ir/serialization.py +88 -0
- pycforge/converter/ir/c_ir/validation.py +834 -0
- pycforge/converter/ir/python_ir/__init__.py +17 -0
- pycforge/converter/ir/python_ir/nodes.py +86 -0
- pycforge/converter/keyword_calls/__init__.py +68 -0
- pycforge/converter/keyword_calls/analysis.py +458 -0
- pycforge/converter/keyword_calls/lowering.py +271 -0
- pycforge/converter/keyword_calls/model.py +304 -0
- pycforge/converter/keyword_calls/validation.py +802 -0
- pycforge/converter/keyword_only_calls/__init__.py +68 -0
- pycforge/converter/keyword_only_calls/analysis.py +640 -0
- pycforge/converter/keyword_only_calls/lowering.py +376 -0
- pycforge/converter/keyword_only_calls/model.py +328 -0
- pycforge/converter/keyword_only_calls/validation.py +1357 -0
- pycforge/converter/lowering.py +1000 -0
- pycforge/converter/modules/__init__.py +13 -0
- pycforge/converter/modules/analysis.py +1250 -0
- pycforge/converter/modules/lowering.py +200 -0
- pycforge/converter/modules/model.py +73 -0
- pycforge/converter/modules/stage.py +192 -0
- pycforge/converter/numeric_semantics/__init__.py +23 -0
- pycforge/converter/numeric_semantics/analysis.py +420 -0
- pycforge/converter/numeric_semantics/lowering.py +153 -0
- pycforge/converter/numeric_semantics/model.py +123 -0
- pycforge/converter/records/__init__.py +34 -0
- pycforge/converter/records/analysis.py +1394 -0
- pycforge/converter/records/lowering.py +393 -0
- pycforge/converter/records/model.py +319 -0
- pycforge/converter/rules/__init__.py +3 -0
- pycforge/converter/support_templates/__init__.py +49 -0
- pycforge/converter/support_templates/assembly.py +106 -0
- pycforge/converter/support_templates/factories.py +348 -0
- pycforge/converter/support_templates/model.py +159 -0
- pycforge/converter/support_templates/registry.py +388 -0
- pycforge/converter/telemetry/__init__.py +0 -0
- pycforge/converter/telemetry/sink.py +39 -0
- pycforge/ide/__init__.py +19 -0
- pycforge/ide/__main__.py +5 -0
- pycforge/ide/_worker_event_codec.py +276 -0
- pycforge/ide/_worker_protocol_json.py +197 -0
- pycforge/ide/_worker_protocol_types.py +90 -0
- pycforge/ide/_worker_request_codec.py +200 -0
- pycforge/ide/_worker_request_data.py +260 -0
- pycforge/ide/_worker_result_data.py +343 -0
- pycforge/ide/action_contract.py +469 -0
- pycforge/ide/action_validation.py +229 -0
- pycforge/ide/command_palette.py +223 -0
- pycforge/ide/controller.py +904 -0
- pycforge/ide/controller_conversion.py +546 -0
- pycforge/ide/controller_io.py +205 -0
- pycforge/ide/editor.py +951 -0
- pycforge/ide/editor_commands_qt.py +274 -0
- pycforge/ide/editor_lexical.py +43 -0
- pycforge/ide/editor_sidebars.py +236 -0
- pycforge/ide/editor_syntax.py +243 -0
- pycforge/ide/find_replace.py +535 -0
- pycforge/ide/icons.py +91 -0
- pycforge/ide/io_service.py +196 -0
- pycforge/ide/model.py +164 -0
- pycforge/ide/panels.py +903 -0
- pycforge/ide/positions.py +220 -0
- pycforge/ide/process_worker.py +130 -0
- pycforge/ide/qt.py +230 -0
- pycforge/ide/qt_actions.py +418 -0
- pycforge/ide/qt_close.py +169 -0
- pycforge/ide/qt_command_palette.py +297 -0
- pycforge/ide/qt_contract.py +220 -0
- pycforge/ide/qt_documents.py +590 -0
- pycforge/ide/qt_editor_buffers.py +113 -0
- pycforge/ide/qt_editor_surfaces.py +112 -0
- pycforge/ide/qt_menus.py +324 -0
- pycforge/ide/qt_projection.py +500 -0
- pycforge/ide/qt_shell.py +348 -0
- pycforge/ide/qt_shell_interactions.py +320 -0
- pycforge/ide/qt_state.py +393 -0
- pycforge/ide/qt_workspace_features.py +398 -0
- pycforge/ide/qt_workspace_navigation.py +208 -0
- pycforge/ide/qt_workspace_observers.py +173 -0
- pycforge/ide/qt_workspace_panels.py +545 -0
- pycforge/ide/qt_workspace_widgets.py +228 -0
- pycforge/ide/resources/icons/about.svg +1 -0
- pycforge/ide/resources/icons/add-document.svg +1 -0
- pycforge/ide/resources/icons/brand-mark.svg +1 -0
- pycforge/ide/resources/icons/bundle-search.svg +1 -0
- pycforge/ide/resources/icons/cancel.svg +1 -0
- pycforge/ide/resources/icons/check.svg +1 -0
- pycforge/ide/resources/icons/chevron-right.svg +1 -0
- pycforge/ide/resources/icons/close.svg +1 -0
- pycforge/ide/resources/icons/collapse-all.svg +1 -0
- pycforge/ide/resources/icons/command-palette.svg +1 -0
- pycforge/ide/resources/icons/convert.svg +1 -0
- pycforge/ide/resources/icons/copy.svg +1 -0
- pycforge/ide/resources/icons/cut.svg +1 -0
- pycforge/ide/resources/icons/decision-trace.svg +1 -0
- pycforge/ide/resources/icons/details.svg +1 -0
- pycforge/ide/resources/icons/diagnostics.svg +1 -0
- pycforge/ide/resources/icons/duplicate-line.svg +1 -0
- pycforge/ide/resources/icons/exit.svg +1 -0
- pycforge/ide/resources/icons/expand-all.svg +1 -0
- pycforge/ide/resources/icons/export.svg +1 -0
- pycforge/ide/resources/icons/find.svg +1 -0
- pycforge/ide/resources/icons/go-to-line.svg +1 -0
- pycforge/ide/resources/icons/go-to-output.svg +1 -0
- pycforge/ide/resources/icons/go-to-source.svg +1 -0
- pycforge/ide/resources/icons/history.svg +1 -0
- pycforge/ide/resources/icons/indent.svg +1 -0
- pycforge/ide/resources/icons/link-c.svg +1 -0
- pycforge/ide/resources/icons/mappings.svg +1 -0
- pycforge/ide/resources/icons/module.svg +1 -0
- pycforge/ide/resources/icons/move-down.svg +1 -0
- pycforge/ide/resources/icons/move-line-down.svg +1 -0
- pycforge/ide/resources/icons/move-line-up.svg +1 -0
- pycforge/ide/resources/icons/move-up.svg +1 -0
- pycforge/ide/resources/icons/next.svg +1 -0
- pycforge/ide/resources/icons/open.svg +1 -0
- pycforge/ide/resources/icons/outdent.svg +1 -0
- pycforge/ide/resources/icons/outline.svg +1 -0
- pycforge/ide/resources/icons/paste.svg +1 -0
- pycforge/ide/resources/icons/previous.svg +1 -0
- pycforge/ide/resources/icons/primary-module.svg +1 -0
- pycforge/ide/resources/icons/redo.svg +1 -0
- pycforge/ide/resources/icons/remove-document.svg +1 -0
- pycforge/ide/resources/icons/replace.svg +1 -0
- pycforge/ide/resources/icons/save-as.svg +1 -0
- pycforge/ide/resources/icons/save.svg +1 -0
- pycforge/ide/resources/icons/select-all.svg +1 -0
- pycforge/ide/resources/icons/settings.svg +1 -0
- pycforge/ide/resources/icons/show-c.svg +1 -0
- pycforge/ide/resources/icons/split-view.svg +1 -0
- pycforge/ide/resources/icons/summary.svg +1 -0
- pycforge/ide/resources/icons/telemetry.svg +1 -0
- pycforge/ide/resources/icons/toggle-comment.svg +1 -0
- pycforge/ide/resources/icons/toggle-fold.svg +1 -0
- pycforge/ide/resources/icons/undo.svg +1 -0
- pycforge/ide/resources/icons/whitespace.svg +1 -0
- pycforge/ide/revisions.py +400 -0
- pycforge/ide/search_service.py +280 -0
- pycforge/ide/session_history.py +150 -0
- pycforge/ide/source_editing.py +417 -0
- pycforge/ide/source_structure.py +558 -0
- pycforge/ide/source_structure_async.py +191 -0
- pycforge/ide/supervisor.py +503 -0
- pycforge/ide/theme.py +119 -0
- pycforge/ide/theme_stylesheet.py +598 -0
- pycforge/ide/theme_workspace_stylesheet.py +155 -0
- pycforge/ide/visual_tokens.py +142 -0
- pycforge/ide/worker_protocol.py +80 -0
- pycforge/ide/workspace_search.py +462 -0
- pycforge/ide/workspace_session.py +256 -0
- pycforge/laboratory/__init__.py +6 -0
- pycforge/laboratory/audits.py +2244 -0
- pycforge/laboratory/checkpoint_e.py +2685 -0
- pycforge/laboratory/cli.py +119 -0
- pycforge/laboratory/exit_codes.py +11 -0
- pycforge/laboratory/keyword_audit.py +661 -0
- pycforge/laboratory/keyword_only_audit.py +481 -0
- pycforge-0.15.2.dist-info/METADATA +209 -0
- pycforge-0.15.2.dist-info/RECORD +221 -0
- pycforge-0.15.2.dist-info/WHEEL +5 -0
- pycforge-0.15.2.dist-info/entry_points.txt +5 -0
- pycforge-0.15.2.dist-info/licenses/LICENSE +674 -0
- pycforge-0.15.2.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
"""Immutable, presentation-only document tab and split-pane state.
|
|
2
|
+
|
|
3
|
+
This module deliberately stores document identifiers only. It cannot retain
|
|
4
|
+
source text, paths, conversion results, observer data, or other semantic
|
|
5
|
+
artifacts. The controller remains the authority for the exact current set and
|
|
6
|
+
order of SourceBundle documents.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
from dataclasses import dataclass, replace
|
|
12
|
+
from enum import Enum
|
|
13
|
+
from typing import Iterable
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
MAX_EDITOR_PANES = 2
|
|
17
|
+
MAX_SESSION_DOCUMENTS = 64
|
|
18
|
+
MAX_DOCUMENT_ID_CHARS = 256
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class SplitOrientation(str, Enum):
|
|
22
|
+
HORIZONTAL = "horizontal"
|
|
23
|
+
VERTICAL = "vertical"
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def _document_ids(values: Iterable[str]) -> tuple[str, ...]:
|
|
27
|
+
if isinstance(values, (str, bytes)):
|
|
28
|
+
raise TypeError("document IDs must be an iterable of complete IDs")
|
|
29
|
+
records = tuple(values)
|
|
30
|
+
if not records:
|
|
31
|
+
raise ValueError("workspace session requires a document")
|
|
32
|
+
if len(records) > MAX_SESSION_DOCUMENTS:
|
|
33
|
+
raise ValueError(
|
|
34
|
+
f"workspace session exceeds {MAX_SESSION_DOCUMENTS} documents"
|
|
35
|
+
)
|
|
36
|
+
for value in records:
|
|
37
|
+
if (
|
|
38
|
+
not isinstance(value, str)
|
|
39
|
+
or not value
|
|
40
|
+
or len(value) > MAX_DOCUMENT_ID_CHARS
|
|
41
|
+
or any(ord(character) < 32 for character in value)
|
|
42
|
+
):
|
|
43
|
+
raise ValueError("document IDs must be bounded printable text")
|
|
44
|
+
if len(records) != len(set(records)):
|
|
45
|
+
raise ValueError("workspace session document IDs must be unique")
|
|
46
|
+
return records
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def _orientation(value: SplitOrientation | str) -> SplitOrientation:
|
|
50
|
+
try:
|
|
51
|
+
return SplitOrientation(value)
|
|
52
|
+
except (TypeError, ValueError) as exc:
|
|
53
|
+
raise ValueError("split orientation is invalid") from exc
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
@dataclass(frozen=True, slots=True)
|
|
57
|
+
class WorkspaceSession:
|
|
58
|
+
"""Exact tab order and at most two document-ID-only editor panes."""
|
|
59
|
+
|
|
60
|
+
document_ids: tuple[str, ...]
|
|
61
|
+
pane_document_ids: tuple[str, ...]
|
|
62
|
+
active_pane: int = 0
|
|
63
|
+
split_orientation: SplitOrientation = SplitOrientation.HORIZONTAL
|
|
64
|
+
|
|
65
|
+
def __post_init__(self) -> None:
|
|
66
|
+
documents = _document_ids(self.document_ids)
|
|
67
|
+
if documents != self.document_ids:
|
|
68
|
+
raise TypeError("document IDs must be a tuple")
|
|
69
|
+
panes = self.pane_document_ids
|
|
70
|
+
if not isinstance(panes, tuple) or not 1 <= len(panes) <= MAX_EDITOR_PANES:
|
|
71
|
+
raise ValueError("workspace session must contain one or two panes")
|
|
72
|
+
if any(document_id not in documents for document_id in panes):
|
|
73
|
+
raise ValueError("every pane must show a current document")
|
|
74
|
+
if (
|
|
75
|
+
isinstance(self.active_pane, bool)
|
|
76
|
+
or not isinstance(self.active_pane, int)
|
|
77
|
+
or not 0 <= self.active_pane < len(panes)
|
|
78
|
+
):
|
|
79
|
+
raise ValueError("active pane is outside the session")
|
|
80
|
+
if not isinstance(self.split_orientation, SplitOrientation):
|
|
81
|
+
raise TypeError("split orientation must be SplitOrientation")
|
|
82
|
+
|
|
83
|
+
@property
|
|
84
|
+
def active_document_id(self) -> str:
|
|
85
|
+
return self.pane_document_ids[self.active_pane]
|
|
86
|
+
|
|
87
|
+
@property
|
|
88
|
+
def is_split(self) -> bool:
|
|
89
|
+
return len(self.pane_document_ids) == MAX_EDITOR_PANES
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def create_workspace_session(
|
|
93
|
+
document_ids: Iterable[str],
|
|
94
|
+
active_document_id: str | None = None,
|
|
95
|
+
) -> WorkspaceSession:
|
|
96
|
+
"""Create a one-pane session over the exact supplied tab order."""
|
|
97
|
+
|
|
98
|
+
records = _document_ids(document_ids)
|
|
99
|
+
active = records[0] if active_document_id is None else active_document_id
|
|
100
|
+
if active not in records:
|
|
101
|
+
raise ValueError("active document is not a current document")
|
|
102
|
+
return WorkspaceSession(records, (active,))
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def activate_document(
|
|
106
|
+
session: WorkspaceSession,
|
|
107
|
+
document_id: str,
|
|
108
|
+
*,
|
|
109
|
+
pane: int | None = None,
|
|
110
|
+
) -> WorkspaceSession:
|
|
111
|
+
"""Show a current document in one pane and make that pane active."""
|
|
112
|
+
|
|
113
|
+
if not isinstance(session, WorkspaceSession):
|
|
114
|
+
raise TypeError("session must be WorkspaceSession")
|
|
115
|
+
if document_id not in session.document_ids:
|
|
116
|
+
raise ValueError("cannot activate a document outside the current tabs")
|
|
117
|
+
target = session.active_pane if pane is None else pane
|
|
118
|
+
if (
|
|
119
|
+
isinstance(target, bool)
|
|
120
|
+
or not isinstance(target, int)
|
|
121
|
+
or not 0 <= target < len(session.pane_document_ids)
|
|
122
|
+
):
|
|
123
|
+
raise ValueError("target pane is outside the session")
|
|
124
|
+
panes = list(session.pane_document_ids)
|
|
125
|
+
panes[target] = document_id
|
|
126
|
+
return replace(
|
|
127
|
+
session,
|
|
128
|
+
pane_document_ids=tuple(panes),
|
|
129
|
+
active_pane=target,
|
|
130
|
+
)
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
def activate_pane(
|
|
134
|
+
session: WorkspaceSession,
|
|
135
|
+
pane: int,
|
|
136
|
+
) -> WorkspaceSession:
|
|
137
|
+
"""Make an existing pane active without changing either pane document."""
|
|
138
|
+
|
|
139
|
+
if not isinstance(session, WorkspaceSession):
|
|
140
|
+
raise TypeError("session must be WorkspaceSession")
|
|
141
|
+
if (
|
|
142
|
+
isinstance(pane, bool)
|
|
143
|
+
or not isinstance(pane, int)
|
|
144
|
+
or not 0 <= pane < len(session.pane_document_ids)
|
|
145
|
+
):
|
|
146
|
+
raise ValueError("target pane is outside the session")
|
|
147
|
+
return replace(session, active_pane=pane)
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
def split_session(
|
|
151
|
+
session: WorkspaceSession,
|
|
152
|
+
orientation: SplitOrientation | str,
|
|
153
|
+
*,
|
|
154
|
+
document_id: str | None = None,
|
|
155
|
+
) -> WorkspaceSession:
|
|
156
|
+
"""Open or reorient the second pane, never creating a third pane."""
|
|
157
|
+
|
|
158
|
+
if not isinstance(session, WorkspaceSession):
|
|
159
|
+
raise TypeError("session must be WorkspaceSession")
|
|
160
|
+
resolved = _orientation(orientation)
|
|
161
|
+
target = session.active_document_id if document_id is None else document_id
|
|
162
|
+
if target not in session.document_ids:
|
|
163
|
+
raise ValueError("split document is not a current document")
|
|
164
|
+
if session.is_split:
|
|
165
|
+
panes = list(session.pane_document_ids)
|
|
166
|
+
panes[session.active_pane] = target
|
|
167
|
+
return replace(
|
|
168
|
+
session,
|
|
169
|
+
pane_document_ids=tuple(panes),
|
|
170
|
+
split_orientation=resolved,
|
|
171
|
+
)
|
|
172
|
+
return WorkspaceSession(
|
|
173
|
+
session.document_ids,
|
|
174
|
+
(session.active_document_id, target),
|
|
175
|
+
active_pane=1,
|
|
176
|
+
split_orientation=resolved,
|
|
177
|
+
)
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
def close_split(
|
|
181
|
+
session: WorkspaceSession,
|
|
182
|
+
*,
|
|
183
|
+
keep_pane: int | None = None,
|
|
184
|
+
) -> WorkspaceSession:
|
|
185
|
+
"""Collapse to one pane, keeping the active pane unless specified."""
|
|
186
|
+
|
|
187
|
+
if not isinstance(session, WorkspaceSession):
|
|
188
|
+
raise TypeError("session must be WorkspaceSession")
|
|
189
|
+
target = session.active_pane if keep_pane is None else keep_pane
|
|
190
|
+
if (
|
|
191
|
+
isinstance(target, bool)
|
|
192
|
+
or not isinstance(target, int)
|
|
193
|
+
or not 0 <= target < len(session.pane_document_ids)
|
|
194
|
+
):
|
|
195
|
+
raise ValueError("pane to keep is outside the session")
|
|
196
|
+
return WorkspaceSession(
|
|
197
|
+
session.document_ids,
|
|
198
|
+
(session.pane_document_ids[target],),
|
|
199
|
+
active_pane=0,
|
|
200
|
+
split_orientation=session.split_orientation,
|
|
201
|
+
)
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
def reconcile_session(
|
|
205
|
+
session: WorkspaceSession,
|
|
206
|
+
current_document_ids: Iterable[str],
|
|
207
|
+
*,
|
|
208
|
+
active_document_id: str | None = None,
|
|
209
|
+
) -> WorkspaceSession:
|
|
210
|
+
"""Reconcile tabs and panes to the controller's exact current IDs.
|
|
211
|
+
|
|
212
|
+
Existing pane choices survive when their document still exists. A removed
|
|
213
|
+
pane document is replaced by the requested active document. The active
|
|
214
|
+
pane always shows the controller-selected active document when one is
|
|
215
|
+
supplied.
|
|
216
|
+
"""
|
|
217
|
+
|
|
218
|
+
if not isinstance(session, WorkspaceSession):
|
|
219
|
+
raise TypeError("session must be WorkspaceSession")
|
|
220
|
+
current = _document_ids(current_document_ids)
|
|
221
|
+
active = (
|
|
222
|
+
session.active_document_id
|
|
223
|
+
if active_document_id is None
|
|
224
|
+
and session.active_document_id in current
|
|
225
|
+
else current[0]
|
|
226
|
+
if active_document_id is None
|
|
227
|
+
else active_document_id
|
|
228
|
+
)
|
|
229
|
+
if active not in current:
|
|
230
|
+
raise ValueError("active document is not a current document")
|
|
231
|
+
panes = [
|
|
232
|
+
document_id if document_id in current else active
|
|
233
|
+
for document_id in session.pane_document_ids
|
|
234
|
+
]
|
|
235
|
+
panes[session.active_pane] = active
|
|
236
|
+
return WorkspaceSession(
|
|
237
|
+
current,
|
|
238
|
+
tuple(panes),
|
|
239
|
+
active_pane=session.active_pane,
|
|
240
|
+
split_orientation=session.split_orientation,
|
|
241
|
+
)
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
__all__ = [
|
|
245
|
+
"MAX_DOCUMENT_ID_CHARS",
|
|
246
|
+
"MAX_EDITOR_PANES",
|
|
247
|
+
"MAX_SESSION_DOCUMENTS",
|
|
248
|
+
"SplitOrientation",
|
|
249
|
+
"WorkspaceSession",
|
|
250
|
+
"activate_document",
|
|
251
|
+
"activate_pane",
|
|
252
|
+
"close_split",
|
|
253
|
+
"create_workspace_session",
|
|
254
|
+
"reconcile_session",
|
|
255
|
+
"split_session",
|
|
256
|
+
]
|