Clear import directory, possibly
This commit is contained in:
1 parent
52a8589261
commit
22c04f6e15
7 files changed
+88
-6
No files matched your search
@@ -30,6 +30,7 @@ from copienator import (
|
||||
workspace_from_args,
|
||||
)
|
||||
from copienator.annotation_data import load_annotation_data
|
||||
from copienator.commands.import_annotations import clear_import_directory
|
||||
from copienator.answer_info import build_answer_info
|
||||
from copienator.filesystem import staged_directory
|
||||
from copienator.feedback_boxes import valid_feedback_box
|
||||
@@ -525,6 +526,8 @@ def process_correction(root_dir, data, all_labels, overwrite=False):
|
||||
|
||||
def build_parser() -> argparse.ArgumentParser:
|
||||
parser = evaluation_parser("Generate simple annotated copies.")
|
||||
parser.add_argument("--clear-import", action="store_true",
|
||||
help="Empty IMPORT_DIR after successful annotation generation")
|
||||
parser.add_argument(
|
||||
"--overwrite",
|
||||
action="store_true",
|
||||
@@ -533,7 +536,8 @@ def build_parser() -> argparse.ArgumentParser:
|
||||
return parser
|
||||
|
||||
|
||||
def run(workspace: EvaluationWorkspace, *, overwrite: bool = False) -> ExitCode:
|
||||
def run(workspace: EvaluationWorkspace, *, overwrite: bool = False,
|
||||
clear_import: bool = False) -> ExitCode:
|
||||
workspace.require_files("labels", "correction.json")
|
||||
workspace.require_directories("Copies", "Par label")
|
||||
labels = utils.read_all_labels(workspace.root)
|
||||
@@ -551,6 +555,8 @@ def run(workspace: EvaluationWorkspace, *, overwrite: bool = False) -> ExitCode:
|
||||
)
|
||||
if loaded.warnings and result == ExitCode.SUCCESS:
|
||||
return ExitCode.PARTIAL
|
||||
if clear_import and result == ExitCode.SUCCESS:
|
||||
clear_import_directory(workspace)
|
||||
return result
|
||||
|
||||
|
||||
@@ -559,7 +565,8 @@ def main(argv: Sequence[str] | None = None) -> int:
|
||||
return execute(
|
||||
parser,
|
||||
argv,
|
||||
lambda args: run(workspace_from_args(args), overwrite=args.overwrite),
|
||||
lambda args: run(workspace_from_args(args), overwrite=args.overwrite,
|
||||
clear_import=args.clear_import),
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ from copienator import (
|
||||
)
|
||||
from copienator.annotation_data import load_annotation_data
|
||||
from copienator.commands import annotating, annotating_with_checks
|
||||
from copienator.commands.import_annotations import clear_import_directory
|
||||
from copienator.filesystem import staged_directory
|
||||
from copienator.utils import natural_key
|
||||
|
||||
@@ -347,7 +348,8 @@ def _generate_groups(
|
||||
|
||||
|
||||
def run(
|
||||
workspace: EvaluationWorkspace, *, overwrite: bool = False, refaire: bool = False
|
||||
workspace: EvaluationWorkspace, *, overwrite: bool = False, refaire: bool = False,
|
||||
clear_import: bool = False,
|
||||
) -> ExitCode:
|
||||
workspace.require_files("labels", "correction.json")
|
||||
workspace.require_directories("Copies", "Par label")
|
||||
@@ -408,11 +410,17 @@ def run(
|
||||
return ExitCode.PARTIAL
|
||||
if generated == 0:
|
||||
print("No new grouped annotations were required.")
|
||||
return ExitCode.PARTIAL if loaded.warnings else ExitCode.SUCCESS
|
||||
if loaded.warnings:
|
||||
return ExitCode.PARTIAL
|
||||
if clear_import:
|
||||
clear_import_directory(workspace)
|
||||
return ExitCode.SUCCESS
|
||||
|
||||
|
||||
def build_parser() -> argparse.ArgumentParser:
|
||||
parser = evaluation_parser("Generate annotated PDFs grouped by labels.")
|
||||
parser.add_argument("--clear-import", action="store_true",
|
||||
help="Empty IMPORT_DIR after successful annotation generation")
|
||||
parser.add_argument(
|
||||
"--overwrite", action="store_true", help="Replace annotation outputs safely"
|
||||
)
|
||||
@@ -430,7 +438,8 @@ def main(argv: Sequence[str] | None = None) -> int:
|
||||
parser,
|
||||
argv,
|
||||
lambda args: run(
|
||||
workspace_from_args(args), overwrite=args.overwrite, refaire=args.refaire
|
||||
workspace_from_args(args), overwrite=args.overwrite, refaire=args.refaire,
|
||||
clear_import=args.clear_import,
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@ from copienator import (
|
||||
)
|
||||
from copienator.annotation_data import load_annotation_data
|
||||
from copienator.commands import annotating
|
||||
from copienator.commands.import_annotations import clear_import_directory
|
||||
from copienator.filesystem import staged_directory
|
||||
from copienator.utils import natural_key
|
||||
|
||||
@@ -269,6 +270,7 @@ def run(
|
||||
*,
|
||||
overwrite: bool = False,
|
||||
refaire: bool = False,
|
||||
clear_import: bool = False,
|
||||
) -> ExitCode:
|
||||
workspace.require_files("labels", "correction.json")
|
||||
workspace.require_directories("Copies", "Par label")
|
||||
@@ -319,6 +321,8 @@ def run(
|
||||
except IncompleteRedo:
|
||||
print("Warning: incomplete redo generation; previous BRnot was preserved.")
|
||||
return ExitCode.PARTIAL
|
||||
if clear_import:
|
||||
clear_import_directory(workspace)
|
||||
return ExitCode.SUCCESS
|
||||
|
||||
statuses: list[str] = []
|
||||
@@ -338,11 +342,15 @@ def run(
|
||||
statuses.append(future.result())
|
||||
if loaded.warnings or "partial" in statuses:
|
||||
return ExitCode.PARTIAL
|
||||
if clear_import:
|
||||
clear_import_directory(workspace)
|
||||
return ExitCode.SUCCESS
|
||||
|
||||
|
||||
def build_parser() -> argparse.ArgumentParser:
|
||||
parser = target_parser("Generate annotated PDFs with checkboxes.")
|
||||
parser.add_argument("--clear-import", action="store_true",
|
||||
help="Empty IMPORT_DIR after successful annotation generation")
|
||||
parser.add_argument(
|
||||
"--overwrite", action="store_true", help="Replace existing outputs"
|
||||
)
|
||||
@@ -364,6 +372,7 @@ def main(argv: Sequence[str] | None = None) -> int:
|
||||
target,
|
||||
overwrite=args.overwrite,
|
||||
refaire=args.refaire,
|
||||
clear_import=args.clear_import,
|
||||
)
|
||||
|
||||
return execute(parser, argv, handler)
|
||||
|
||||
@@ -5,15 +5,40 @@ from collections.abc import Sequence
|
||||
from pathlib import Path
|
||||
|
||||
from copienator import (
|
||||
CliError,
|
||||
EvaluationWorkspace,
|
||||
ExitCode,
|
||||
evaluation_parser,
|
||||
execute,
|
||||
workspace_from_args,
|
||||
)
|
||||
from copienator.configuration import IMPORT_DIR
|
||||
from copienator import configuration
|
||||
|
||||
ANNOTATION_DIRECTORIES = ("BGnot", "Bnot", "Anot")
|
||||
IMPORT_DIR = getattr(configuration, "IMPORT_DIR", None)
|
||||
|
||||
|
||||
def clear_import_directory(workspace: EvaluationWorkspace) -> None:
|
||||
"""Empty the configured import folder while preserving the folder itself."""
|
||||
if IMPORT_DIR is None or not str(IMPORT_DIR).strip():
|
||||
print("Aucun dossier d’import configuré ; aucun fichier supprimé.")
|
||||
return
|
||||
directory = Path(IMPORT_DIR).expanduser().resolve()
|
||||
if workspace.root.resolve().is_relative_to(directory) or Path.cwd().resolve().is_relative_to(directory):
|
||||
raise CliError(f"Le dossier d’import ne peut pas contenir l’évaluation ou le projet : {directory}",
|
||||
ExitCode.INVALID_ARGUMENTS)
|
||||
if not directory.exists():
|
||||
print(f"Dossier d’import absent ; aucun fichier supprimé : {directory}")
|
||||
return
|
||||
if not directory.is_dir():
|
||||
raise CliError(f"Le dossier d’import n’est pas un dossier : {directory}",
|
||||
ExitCode.INVALID_ARGUMENTS)
|
||||
for child in directory.iterdir():
|
||||
if child.is_dir() and not child.is_symlink():
|
||||
shutil.rmtree(child)
|
||||
else:
|
||||
child.unlink()
|
||||
print(f"Dossier d’import vidé : {directory}", flush=True)
|
||||
|
||||
|
||||
def sync_annotated(
|
||||
|
||||
@@ -527,6 +527,12 @@ def build_workflow(show_personal_steps: bool) -> list[StepDefinition]:
|
||||
),
|
||||
arguments=(
|
||||
arg_target("le dossier de l’évaluation"),
|
||||
ArgumentSpec(
|
||||
"clear_import", "Vider le dossier d’import", "bool", "--clear-import",
|
||||
default=bool(str(getattr(configuration, "IMPORT_DIR", "") or "").strip()),
|
||||
help="Supprime tous les fichiers et sous-dossiers du dossier IMPORT_DIR configuré "
|
||||
"après une génération réussie des copies annotées. Le dossier lui-même est conservé.",
|
||||
),
|
||||
ArgumentSpec(
|
||||
"overwrite",
|
||||
"Écraser les sorties",
|
||||
|
||||
@@ -52,6 +52,19 @@ class GuiConvenienceTests(unittest.TestCase):
|
||||
start.assert_not_called()
|
||||
self.assertEqual(self.app.state_store.step(step.id)["status"], "success")
|
||||
|
||||
def test_annotation_import_cleanup_can_be_unchecked(self):
|
||||
self.app.tree.selection_set("annotation")
|
||||
self.app.update()
|
||||
self.assertTrue(self.app.arg_vars["clear_import"].get())
|
||||
self.assertIn("--clear-import", self.app._make_command())
|
||||
self.app.arg_vars["clear_import"].set(False)
|
||||
self.assertNotIn("--clear-import", self.app._make_command())
|
||||
self.app.tree.selection_set("export")
|
||||
self.app.update()
|
||||
self.app.tree.selection_set("annotation")
|
||||
self.app.update()
|
||||
self.assertFalse(self.app.arg_vars["clear_import"].get())
|
||||
|
||||
def test_cutleft_visual_check_option_is_below_and_off_by_default(self):
|
||||
step = self.app.step_by_id["cutleft"]
|
||||
self.app.current_step = step
|
||||
|
||||
@@ -2705,6 +2705,19 @@ class WorkflowTests(unittest.TestCase):
|
||||
)
|
||||
self.assertEqual(command[4], "annotate-grouped")
|
||||
|
||||
def test_annotation_import_cleanup_defaults_to_configured_folder(self) -> None:
|
||||
for configured in (None, "", Path("Import")):
|
||||
with patch.object(workflow_module.configuration, "IMPORT_DIR", configured):
|
||||
step = next(step for step in build_workflow(False) if step.id == "annotation")
|
||||
for variant in step.variants:
|
||||
with self.subTest(configured=configured, variant=variant.id):
|
||||
command = build_command(REPOSITORY, step, variant, {}, self.evaluation)
|
||||
self.assertEqual("--clear-import" in command, bool(configured))
|
||||
command = build_command(
|
||||
REPOSITORY, step, variant, {"clear_import": False}, self.evaluation
|
||||
)
|
||||
self.assertNotIn("--clear-import", command)
|
||||
|
||||
def test_copy_preparation_commands_are_python(self) -> None:
|
||||
rotate = self.command("rotate", "rotate", {"target": self.evaluation})
|
||||
rename = self.command("rename", "rename", {"target": self.evaluation})
|
||||
|
||||
Reference in new issue
Block a user