donna 0.2.0__py3-none-any.whl → 0.2.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.
- donna/artifacts/intro.md +39 -0
- donna/artifacts/research/specs/report.md +163 -0
- donna/artifacts/research/work/research.md +198 -0
- donna/artifacts/rfc/specs/request_for_change.md +270 -0
- donna/artifacts/rfc/work/create.md +120 -0
- donna/artifacts/rfc/work/do.md +109 -0
- donna/artifacts/rfc/work/plan.md +68 -0
- donna/artifacts/usage/artifacts.md +55 -12
- donna/artifacts/usage/cli.md +114 -39
- donna/artifacts/usage/worlds.md +8 -2
- donna/cli/__main__.py +1 -1
- donna/cli/commands/artifacts.py +104 -17
- donna/cli/commands/sessions.py +8 -8
- donna/cli/commands/workspaces.py +42 -0
- donna/cli/errors.py +18 -0
- donna/cli/types.py +16 -9
- donna/cli/utils.py +2 -2
- donna/core/errors.py +1 -11
- donna/core/result.py +5 -8
- donna/core/utils.py +0 -3
- donna/lib/__init__.py +4 -0
- donna/lib/sources.py +1 -1
- donna/lib/worlds.py +2 -2
- donna/machine/action_requests.py +0 -5
- donna/machine/artifacts.py +8 -6
- donna/machine/primitives.py +5 -5
- donna/machine/sessions.py +13 -5
- donna/machine/state.py +4 -4
- donna/machine/tasks.py +4 -18
- donna/machine/templates.py +4 -2
- donna/primitives/artifacts/specification.py +13 -2
- donna/primitives/artifacts/workflow.py +11 -2
- donna/primitives/directives/list.py +86 -0
- donna/primitives/directives/view.py +52 -11
- donna/primitives/operations/finish_workflow.py +13 -2
- donna/primitives/operations/output.py +87 -0
- donna/primitives/operations/request_action.py +3 -9
- donna/primitives/operations/run_script.py +2 -2
- donna/protocol/utils.py +22 -0
- donna/workspaces/artifacts.py +238 -0
- donna/{world → workspaces}/artifacts_discovery.py +1 -1
- donna/{world → workspaces}/config.py +18 -11
- donna/{world → workspaces}/errors.py +55 -45
- donna/workspaces/initialization.py +78 -0
- donna/{world → workspaces}/markdown.py +21 -26
- donna/{world → workspaces}/sources/base.py +2 -2
- donna/{world → workspaces}/sources/markdown.py +8 -7
- donna/{world → workspaces}/templates.py +4 -4
- donna/workspaces/tmp.py +51 -0
- donna/{world → workspaces}/worlds/base.py +6 -3
- donna/{world → workspaces}/worlds/filesystem.py +30 -10
- donna/{world → workspaces}/worlds/python.py +12 -9
- donna-0.2.2.dist-info/METADATA +463 -0
- donna-0.2.2.dist-info/RECORD +92 -0
- {donna-0.2.0.dist-info → donna-0.2.2.dist-info}/WHEEL +1 -1
- donna/artifacts/work/do_it.md +0 -142
- donna/artifacts/work/do_it_fast.md +0 -98
- donna/artifacts/work/planning.md +0 -245
- donna/cli/commands/projects.py +0 -49
- donna/world/artifacts.py +0 -122
- donna/world/initialization.py +0 -42
- donna/world/tmp.py +0 -33
- donna/world/worlds/__init__.py +0 -0
- donna-0.2.0.dist-info/METADATA +0 -44
- donna-0.2.0.dist-info/RECORD +0 -85
- /donna/{artifacts/work → workspaces}/__init__.py +0 -0
- /donna/{world → workspaces}/sources/__init__.py +0 -0
- /donna/{world → workspaces/worlds}/__init__.py +0 -0
- {donna-0.2.0.dist-info → donna-0.2.2.dist-info}/entry_points.txt +0 -0
- {donna-0.2.0.dist-info → donna-0.2.2.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import enum
|
|
2
2
|
from typing import Any
|
|
3
3
|
|
|
4
|
-
import pydantic
|
|
5
4
|
from markdown_it import MarkdownIt
|
|
6
5
|
from markdown_it.token import Token
|
|
7
6
|
from markdown_it.tree import SyntaxTreeNode
|
|
@@ -11,7 +10,7 @@ from donna.core.entities import BaseEntity
|
|
|
11
10
|
from donna.core.errors import ErrorsList
|
|
12
11
|
from donna.core.result import Err, Ok, Result, unwrap_to_error
|
|
13
12
|
from donna.domain.ids import FullArtifactId
|
|
14
|
-
from donna.
|
|
13
|
+
from donna.workspaces import errors as world_errors
|
|
15
14
|
|
|
16
15
|
|
|
17
16
|
class SectionLevel(str, enum.Enum):
|
|
@@ -54,8 +53,6 @@ class SectionSource(BaseEntity):
|
|
|
54
53
|
original_tokens: list[Token]
|
|
55
54
|
analysis_tokens: list[Token]
|
|
56
55
|
|
|
57
|
-
model_config = pydantic.ConfigDict(frozen=False)
|
|
58
|
-
|
|
59
56
|
def _as_markdown(self, tokens: list[Token], with_title: bool) -> str:
|
|
60
57
|
parts = []
|
|
61
58
|
|
|
@@ -110,15 +107,21 @@ def clear_heading(text: str) -> str:
|
|
|
110
107
|
def _parse_h1(
|
|
111
108
|
sections: list[SectionSource], node: SyntaxTreeNode, artifact_id: FullArtifactId | None
|
|
112
109
|
) -> Result[SyntaxTreeNode | None, ErrorsList]:
|
|
113
|
-
section
|
|
114
|
-
|
|
115
|
-
if section.level != SectionLevel.h1:
|
|
110
|
+
if sections and any(section.level == SectionLevel.h1 for section in sections):
|
|
116
111
|
return Err([world_errors.MarkdownMultipleH1Sections(artifact_id=artifact_id)])
|
|
117
112
|
|
|
118
|
-
if
|
|
119
|
-
return Err([world_errors.
|
|
113
|
+
if sections:
|
|
114
|
+
return Err([world_errors.MarkdownH1SectionMustBeFirst(artifact_id=artifact_id)])
|
|
115
|
+
|
|
116
|
+
new_section = SectionSource(
|
|
117
|
+
level=SectionLevel.h1,
|
|
118
|
+
title=clear_heading(render_back(node.to_tokens()).strip()),
|
|
119
|
+
original_tokens=[],
|
|
120
|
+
analysis_tokens=[],
|
|
121
|
+
configs=[],
|
|
122
|
+
)
|
|
120
123
|
|
|
121
|
-
|
|
124
|
+
sections.append(new_section)
|
|
122
125
|
|
|
123
126
|
return Ok(node.next_sibling)
|
|
124
127
|
|
|
@@ -126,10 +129,9 @@ def _parse_h1(
|
|
|
126
129
|
def _parse_h2(
|
|
127
130
|
sections: list[SectionSource], node: SyntaxTreeNode, artifact_id: FullArtifactId | None
|
|
128
131
|
) -> Result[SyntaxTreeNode | None, ErrorsList]:
|
|
129
|
-
section = sections[-1]
|
|
130
132
|
|
|
131
|
-
if
|
|
132
|
-
return Err([world_errors.
|
|
133
|
+
if not sections:
|
|
134
|
+
return Err([world_errors.MarkdownH1SectionMustBeFirst(artifact_id=artifact_id)])
|
|
133
135
|
|
|
134
136
|
new_section = SectionSource(
|
|
135
137
|
level=SectionLevel.h2,
|
|
@@ -147,7 +149,6 @@ def _parse_h2(
|
|
|
147
149
|
def _parse_heading(
|
|
148
150
|
sections: list[SectionSource], node: SyntaxTreeNode, artifact_id: FullArtifactId | None
|
|
149
151
|
) -> Result[SyntaxTreeNode | None, ErrorsList]:
|
|
150
|
-
section = sections[-1]
|
|
151
152
|
|
|
152
153
|
if node.tag == "h1":
|
|
153
154
|
return _parse_h1(sections, node, artifact_id)
|
|
@@ -155,7 +156,11 @@ def _parse_heading(
|
|
|
155
156
|
if node.tag == "h2":
|
|
156
157
|
return _parse_h2(sections, node, artifact_id)
|
|
157
158
|
|
|
158
|
-
|
|
159
|
+
if not sections:
|
|
160
|
+
return Err([world_errors.MarkdownH1SectionMustBeFirst(artifact_id=artifact_id)])
|
|
161
|
+
|
|
162
|
+
sections[-1].original_tokens.extend(node.to_tokens())
|
|
163
|
+
|
|
159
164
|
return Ok(node.next_sibling)
|
|
160
165
|
|
|
161
166
|
|
|
@@ -231,15 +236,7 @@ def parse( # noqa: CCR001, CFQ001
|
|
|
231
236
|
# we do not need root node
|
|
232
237
|
node: SyntaxTreeNode | None = SyntaxTreeNode(tokens).children[0]
|
|
233
238
|
|
|
234
|
-
sections: list[SectionSource] = [
|
|
235
|
-
SectionSource(
|
|
236
|
-
level=SectionLevel.h1,
|
|
237
|
-
title=None,
|
|
238
|
-
original_tokens=[],
|
|
239
|
-
analysis_tokens=[],
|
|
240
|
-
configs=[],
|
|
241
|
-
)
|
|
242
|
-
]
|
|
239
|
+
sections: list[SectionSource] = []
|
|
243
240
|
|
|
244
241
|
while node is not None:
|
|
245
242
|
|
|
@@ -263,5 +260,3 @@ def parse( # noqa: CCR001, CFQ001
|
|
|
263
260
|
node = node.next_sibling
|
|
264
261
|
|
|
265
262
|
return Ok(sections)
|
|
266
|
-
|
|
267
|
-
return sections
|
|
@@ -13,8 +13,8 @@ from donna.machine.primitives import Primitive
|
|
|
13
13
|
if TYPE_CHECKING:
|
|
14
14
|
from donna.domain.ids import FullArtifactId
|
|
15
15
|
from donna.machine.artifacts import Artifact
|
|
16
|
-
from donna.
|
|
17
|
-
from donna.
|
|
16
|
+
from donna.workspaces.artifacts import ArtifactRenderContext
|
|
17
|
+
from donna.workspaces.config import SourceConfig as SourceConfigModel
|
|
18
18
|
|
|
19
19
|
|
|
20
20
|
class SourceConfig(BaseEntity, ABC):
|
|
@@ -6,11 +6,11 @@ from donna.core.result import Err, Ok, Result, unwrap_to_error
|
|
|
6
6
|
from donna.domain.ids import ArtifactSectionId, FullArtifactId, PythonImportPath
|
|
7
7
|
from donna.machine.artifacts import Artifact, ArtifactSection, ArtifactSectionConfig, ArtifactSectionMeta
|
|
8
8
|
from donna.machine.primitives import Primitive, resolve_primitive
|
|
9
|
-
from donna.
|
|
10
|
-
from donna.
|
|
11
|
-
from donna.
|
|
12
|
-
from donna.
|
|
13
|
-
from donna.
|
|
9
|
+
from donna.workspaces import errors as world_errors
|
|
10
|
+
from donna.workspaces import markdown
|
|
11
|
+
from donna.workspaces.artifacts import ArtifactRenderContext
|
|
12
|
+
from donna.workspaces.sources.base import SourceConfig, SourceConstructor
|
|
13
|
+
from donna.workspaces.templates import RenderMode, render
|
|
14
14
|
|
|
15
15
|
|
|
16
16
|
class MarkdownSectionConstructor(Protocol):
|
|
@@ -111,6 +111,7 @@ class MarkdownSectionMixin:
|
|
|
111
111
|
kind=section_config.kind,
|
|
112
112
|
title=title,
|
|
113
113
|
description=description,
|
|
114
|
+
tags=section_config.tags,
|
|
114
115
|
primary=primary,
|
|
115
116
|
meta=meta,
|
|
116
117
|
)
|
|
@@ -140,7 +141,7 @@ def parse_artifact_content(
|
|
|
140
141
|
)
|
|
141
142
|
|
|
142
143
|
if not original_sections:
|
|
143
|
-
# return
|
|
144
|
+
# return Environment errors
|
|
144
145
|
return Err([world_errors.MarkdownArtifactWithoutSections(artifact_id=full_id)])
|
|
145
146
|
|
|
146
147
|
for original, analyzed in zip(original_sections, analyzed_sections):
|
|
@@ -257,4 +258,4 @@ def _ensure_markdown_constructible(
|
|
|
257
258
|
|
|
258
259
|
|
|
259
260
|
if TYPE_CHECKING:
|
|
260
|
-
from donna.
|
|
261
|
+
from donna.workspaces.config import SourceConfig as SourceConfigModel
|
|
@@ -12,10 +12,10 @@ from donna.core.errors import EnvironmentErrorsProxy, ErrorsList
|
|
|
12
12
|
from donna.core.result import Err, Ok, Result
|
|
13
13
|
from donna.domain.ids import FullArtifactId
|
|
14
14
|
from donna.machine.templates import Directive
|
|
15
|
-
from donna.
|
|
15
|
+
from donna.workspaces import errors as world_errors
|
|
16
16
|
|
|
17
17
|
if TYPE_CHECKING:
|
|
18
|
-
from donna.
|
|
18
|
+
from donna.workspaces.artifacts import ArtifactRenderContext
|
|
19
19
|
|
|
20
20
|
|
|
21
21
|
class RenderMode(enum.Enum):
|
|
@@ -57,7 +57,7 @@ class DirectivePathBuilder:
|
|
|
57
57
|
return DirectivePathBuilder(self._parts + (name,))
|
|
58
58
|
|
|
59
59
|
@jinja2.pass_context
|
|
60
|
-
def __call__(self, context: jinja2.runtime.Context, *argv: object) -> object: # noqa: CCR001
|
|
60
|
+
def __call__(self, context: jinja2.runtime.Context, *argv: object, **kwargs: object) -> object: # noqa: CCR001
|
|
61
61
|
artifact_id = context.get("artifact_id")
|
|
62
62
|
directive_path = ".".join(self._parts)
|
|
63
63
|
if len(self._parts) < 2:
|
|
@@ -112,7 +112,7 @@ class DirectivePathBuilder:
|
|
|
112
112
|
)
|
|
113
113
|
|
|
114
114
|
try:
|
|
115
|
-
result = directive.apply_directive(context, *argv)
|
|
115
|
+
result = directive.apply_directive(context, *argv, **kwargs)
|
|
116
116
|
except EnvironmentErrorsProxy:
|
|
117
117
|
raise
|
|
118
118
|
except core_errors.InternalError:
|
donna/workspaces/tmp.py
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import pathlib
|
|
2
|
+
import shutil
|
|
3
|
+
import time
|
|
4
|
+
|
|
5
|
+
from donna.cli.types import FullArtifactIdArgument
|
|
6
|
+
from donna.workspaces.config import config, config_dir
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def dir() -> pathlib.Path:
|
|
10
|
+
cfg = config()
|
|
11
|
+
tmp_path = cfg.tmp_dir
|
|
12
|
+
|
|
13
|
+
if not cfg.tmp_dir.is_absolute():
|
|
14
|
+
tmp_path = config_dir() / tmp_path
|
|
15
|
+
|
|
16
|
+
tmp_path.mkdir(parents=True, exist_ok=True)
|
|
17
|
+
|
|
18
|
+
return tmp_path
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def file_for_artifact(artifact_id: FullArtifactIdArgument, extension: str) -> pathlib.Path:
|
|
22
|
+
directory = dir()
|
|
23
|
+
|
|
24
|
+
directory.mkdir(parents=True, exist_ok=True)
|
|
25
|
+
|
|
26
|
+
normalized_extension = extension.lstrip(".")
|
|
27
|
+
artifact_file_name = f"{str(artifact_id).replace('/', '.')}.{int(time.time() * 1000)}.{normalized_extension}"
|
|
28
|
+
|
|
29
|
+
return directory / artifact_file_name
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def file_for_slug(slug: str, extension: str) -> pathlib.Path:
|
|
33
|
+
directory = dir()
|
|
34
|
+
|
|
35
|
+
directory.mkdir(parents=True, exist_ok=True)
|
|
36
|
+
|
|
37
|
+
normalized_slug = slug.replace("/", ".").replace("\\", ".")
|
|
38
|
+
normalized_extension = extension.lstrip(".")
|
|
39
|
+
artifact_file_name = f"{normalized_slug}.{int(time.time() * 1000)}.{normalized_extension}"
|
|
40
|
+
|
|
41
|
+
return directory / artifact_file_name
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def create_file_for_slug(slug: str, extension: str) -> pathlib.Path:
|
|
45
|
+
path = file_for_slug(slug, extension)
|
|
46
|
+
path.touch()
|
|
47
|
+
return path
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def clear() -> None:
|
|
51
|
+
shutil.rmtree(dir())
|
|
@@ -11,8 +11,8 @@ from donna.machine.artifacts import Artifact
|
|
|
11
11
|
from donna.machine.primitives import Primitive
|
|
12
12
|
|
|
13
13
|
if TYPE_CHECKING:
|
|
14
|
-
from donna.
|
|
15
|
-
from donna.
|
|
14
|
+
from donna.workspaces.artifacts import ArtifactRenderContext
|
|
15
|
+
from donna.workspaces.config import WorldConfig
|
|
16
16
|
|
|
17
17
|
|
|
18
18
|
class World(BaseEntity, ABC):
|
|
@@ -36,6 +36,9 @@ class World(BaseEntity, ABC):
|
|
|
36
36
|
self, artifact_id: ArtifactId, content: bytes, extension: str
|
|
37
37
|
) -> Result[None, ErrorsList]: ... # noqa: E704
|
|
38
38
|
|
|
39
|
+
@abstractmethod
|
|
40
|
+
def remove(self, artifact_id: ArtifactId) -> Result[None, ErrorsList]: ... # noqa: E704
|
|
41
|
+
|
|
39
42
|
@abstractmethod
|
|
40
43
|
def file_extension_for(self, artifact_id: ArtifactId) -> Result[str, ErrorsList]: ... # noqa: E704
|
|
41
44
|
|
|
@@ -47,7 +50,7 @@ class World(BaseEntity, ABC):
|
|
|
47
50
|
# For the artifact: uniform API for storing/loading data
|
|
48
51
|
# Against the artifact:
|
|
49
52
|
# - session data MUST be accessible only by Donna => no one should be able to read/write/list it
|
|
50
|
-
# - session data will require an
|
|
53
|
+
# - session data will require an additional kind(s) of artifact(s) just for that purpose
|
|
51
54
|
# - session data may change more frequently than regular artifacts
|
|
52
55
|
|
|
53
56
|
@abstractmethod
|
|
@@ -6,14 +6,14 @@ from donna.core.errors import ErrorsList
|
|
|
6
6
|
from donna.core.result import Err, Ok, Result, unwrap_to_error
|
|
7
7
|
from donna.domain.ids import ArtifactId, FullArtifactId, FullArtifactIdPattern
|
|
8
8
|
from donna.machine.artifacts import Artifact
|
|
9
|
-
from donna.
|
|
10
|
-
from donna.
|
|
11
|
-
from donna.
|
|
12
|
-
from donna.
|
|
13
|
-
from donna.
|
|
9
|
+
from donna.workspaces import errors as world_errors
|
|
10
|
+
from donna.workspaces.artifacts import ArtifactRenderContext
|
|
11
|
+
from donna.workspaces.artifacts_discovery import ArtifactListingNode, list_artifacts_by_pattern
|
|
12
|
+
from donna.workspaces.worlds.base import World as BaseWorld
|
|
13
|
+
from donna.workspaces.worlds.base import WorldConstructor
|
|
14
14
|
|
|
15
15
|
if TYPE_CHECKING:
|
|
16
|
-
from donna.
|
|
16
|
+
from donna.workspaces.config import SourceConfigValue, WorldConfig
|
|
17
17
|
|
|
18
18
|
|
|
19
19
|
class World(BaseWorld):
|
|
@@ -35,7 +35,7 @@ class World(BaseWorld):
|
|
|
35
35
|
if not parent.exists():
|
|
36
36
|
return Ok(None)
|
|
37
37
|
|
|
38
|
-
from donna.
|
|
38
|
+
from donna.workspaces.config import config
|
|
39
39
|
|
|
40
40
|
supported_extensions = config().supported_extensions()
|
|
41
41
|
matches = [
|
|
@@ -55,7 +55,7 @@ class World(BaseWorld):
|
|
|
55
55
|
def _get_source_by_filename(
|
|
56
56
|
self, artifact_id: ArtifactId, filename: str
|
|
57
57
|
) -> Result["SourceConfigValue", ErrorsList]:
|
|
58
|
-
from donna.
|
|
58
|
+
from donna.workspaces.config import config
|
|
59
59
|
|
|
60
60
|
extension = pathlib.Path(filename).suffix
|
|
61
61
|
source_config = config().find_source_for_extension(extension)
|
|
@@ -89,7 +89,7 @@ class World(BaseWorld):
|
|
|
89
89
|
full_id = FullArtifactId((self.id, artifact_id))
|
|
90
90
|
|
|
91
91
|
extension = pathlib.Path(path.name).suffix
|
|
92
|
-
from donna.
|
|
92
|
+
from donna.workspaces.config import config
|
|
93
93
|
|
|
94
94
|
source_config = config().find_source_for_extension(extension)
|
|
95
95
|
if source_config is None:
|
|
@@ -123,6 +123,20 @@ class World(BaseWorld):
|
|
|
123
123
|
path.write_bytes(content)
|
|
124
124
|
return Ok(None)
|
|
125
125
|
|
|
126
|
+
@unwrap_to_error
|
|
127
|
+
def remove(self, artifact_id: ArtifactId) -> Result[None, ErrorsList]:
|
|
128
|
+
if self.readonly:
|
|
129
|
+
return Err([world_errors.WorldReadonly(world_id=self.id)])
|
|
130
|
+
|
|
131
|
+
path = self._resolve_artifact_file(artifact_id).unwrap()
|
|
132
|
+
|
|
133
|
+
if path is None:
|
|
134
|
+
return Ok(None)
|
|
135
|
+
|
|
136
|
+
path.unlink()
|
|
137
|
+
|
|
138
|
+
return Ok(None)
|
|
139
|
+
|
|
126
140
|
@unwrap_to_error
|
|
127
141
|
def file_extension_for(self, artifact_id: ArtifactId) -> Result[str, ErrorsList]:
|
|
128
142
|
path = self._resolve_artifact_file(artifact_id).unwrap()
|
|
@@ -181,9 +195,15 @@ class FilesystemWorldConstructor(WorldConstructor):
|
|
|
181
195
|
if path_value is None:
|
|
182
196
|
raise ValueError(f"World config '{config.id}' does not define a filesystem path")
|
|
183
197
|
|
|
198
|
+
from donna.workspaces.config import project_dir
|
|
199
|
+
|
|
200
|
+
path = pathlib.Path(path_value).expanduser()
|
|
201
|
+
if not path.is_absolute():
|
|
202
|
+
path = project_dir() / path
|
|
203
|
+
|
|
184
204
|
return World(
|
|
185
205
|
id=config.id,
|
|
186
|
-
path=
|
|
206
|
+
path=path.resolve(),
|
|
187
207
|
readonly=config.readonly,
|
|
188
208
|
session=config.session,
|
|
189
209
|
)
|
|
@@ -7,14 +7,14 @@ from donna.core.errors import ErrorsList
|
|
|
7
7
|
from donna.core.result import Err, Ok, Result, unwrap_to_error
|
|
8
8
|
from donna.domain.ids import ArtifactId, FullArtifactId, FullArtifactIdPattern, WorldId
|
|
9
9
|
from donna.machine.artifacts import Artifact
|
|
10
|
-
from donna.
|
|
11
|
-
from donna.
|
|
12
|
-
from donna.
|
|
13
|
-
from donna.
|
|
14
|
-
from donna.
|
|
10
|
+
from donna.workspaces import errors as world_errors
|
|
11
|
+
from donna.workspaces.artifacts import ArtifactRenderContext
|
|
12
|
+
from donna.workspaces.artifacts_discovery import ArtifactListingNode, list_artifacts_by_pattern
|
|
13
|
+
from donna.workspaces.worlds.base import World as BaseWorld
|
|
14
|
+
from donna.workspaces.worlds.base import WorldConstructor
|
|
15
15
|
|
|
16
16
|
if TYPE_CHECKING:
|
|
17
|
-
from donna.
|
|
17
|
+
from donna.workspaces.config import SourceConfigValue, WorldConfig
|
|
18
18
|
|
|
19
19
|
|
|
20
20
|
class Python(BaseWorld):
|
|
@@ -59,7 +59,7 @@ class Python(BaseWorld):
|
|
|
59
59
|
if not resource_dir.is_dir():
|
|
60
60
|
return Ok(None)
|
|
61
61
|
|
|
62
|
-
from donna.
|
|
62
|
+
from donna.workspaces.config import config
|
|
63
63
|
|
|
64
64
|
supported_extensions = config().supported_extensions()
|
|
65
65
|
matches = [
|
|
@@ -81,7 +81,7 @@ class Python(BaseWorld):
|
|
|
81
81
|
def _get_source_by_filename(
|
|
82
82
|
self, artifact_id: ArtifactId, filename: str
|
|
83
83
|
) -> Result["SourceConfigValue", ErrorsList]:
|
|
84
|
-
from donna.
|
|
84
|
+
from donna.workspaces.config import config
|
|
85
85
|
|
|
86
86
|
extension = pathlib.Path(filename).suffix
|
|
87
87
|
source_config = config().find_source_for_extension(extension)
|
|
@@ -115,7 +115,7 @@ class Python(BaseWorld):
|
|
|
115
115
|
full_id = FullArtifactId((self.id, artifact_id))
|
|
116
116
|
|
|
117
117
|
extension = pathlib.Path(resource_path.name).suffix
|
|
118
|
-
from donna.
|
|
118
|
+
from donna.workspaces.config import config
|
|
119
119
|
|
|
120
120
|
source_config = config().find_source_for_extension(extension)
|
|
121
121
|
if source_config is None:
|
|
@@ -142,6 +142,9 @@ class Python(BaseWorld):
|
|
|
142
142
|
def update(self, artifact_id: ArtifactId, content: bytes, extension: str) -> Result[None, ErrorsList]:
|
|
143
143
|
return Err([world_errors.WorldReadonly(world_id=self.id)])
|
|
144
144
|
|
|
145
|
+
def remove(self, artifact_id: ArtifactId) -> Result[None, ErrorsList]:
|
|
146
|
+
return Err([world_errors.WorldReadonly(world_id=self.id)])
|
|
147
|
+
|
|
145
148
|
@unwrap_to_error
|
|
146
149
|
def file_extension_for(self, artifact_id: ArtifactId) -> Result[str, ErrorsList]:
|
|
147
150
|
resource_path = self._resolve_artifact_file(artifact_id).unwrap()
|