bug/9548-incomplete-filenames-in-otanalytics-if-video-name-has-multiple-dots#821
Merged
schubsen merged 54 commits intoMay 29, 2026
Conversation
… multiple dots Path.with_suffix() replaces only the last dot-separated segment, so filenames like 'name.00000_2025-08-28_15-00-00' would lose the trailing part. Replace with_suffix() calls with parent / (name + suffix) to preserve the full stem.
schubsen
requested changes
Apr 14, 2026
schubsen
left a comment
Contributor
There was a problem hiding this comment.
The files with the suffixes
- .tracks_metadata.json
- .tracks.csv
- videos_metadata.json
still get truncated
…em on TrackExportSpecification
…em on TrackStatisticsExportSpecification
…log message, pathlib join)
…em on ExportSpecification (road user)
… directory and stem-based specification, ensuring consistent path management across all export methods.
Captures the design for adapting NiceGUI to the new (export_directory, file_stem, ...) export contract, with a locked-suffix UI that enforces filenames ending in <context>.<ext>.
Bite-sized TDD plan for the locked-suffix UI and new export DTO wiring.
- Fix strip_extension to remove the literal suffix (was a char-set rstrip). - Add stem-field + locked-suffix UI to FileChooserDialog with three modes: open (legacy single field), plain save (.<ext>), context export (.<context>.<ext>). - Rewrite ExportCountsDialog with the same pattern; suffix is derived from interval and format and updates live. get_specification() now produces a CountingSpecificationDto with export_directory and export_filename_stem (the field name introduced by commit 8d89b20).
…eDto Construct ExportFileDto from the dialog's typed accessors instead of the naive from_file_path helper (which would re-inject the context suffix into the stem). Also fix the cancel exception types: configure_export_file now raises CancelExportFile and configure_export_counts now raises CancelExportCounts, matching what the dummy viewmodel catches.
…ctory askopenfilename now opts into the legacy single-field mode (enforce_suffix=False) so file-open dialogs behave as before. The plain-save path (ask_for_save_file_path, used by otconfig/otflow saves) opts into the stem + locked-extension mode so the user cannot type an unsupported extension.
…ad code) - Replace overly broad except Exception with MissingInstanceError in _current_extension and _on_interval_or_format_change. - Reorder __init__ so _format_field exists before _filename_suffix_field (the suffix field's initial value reads _format_field.value via _build_locked_suffix -> _current_extension). - Remove the dead MARKER_FILENAME constant - no widget uses it. - Remove the unreachable 'or initial_dir' fallback on suggestion.parent.
…nagement - Encapsulate save directory, stem, and file type(s) within a dataclass. - Refactor `suggest_save_path` to return `SavePathSuggestion`, ensuring file paths are accessed via properties. - Update UI components and export dialogs to use `SavePathSuggestion` properties (`file_path`, `file_stem`, `save_directory`). - Remove redundant path manipulation logic across modules.
…xportCountsDialog` - Replace hardcoded paths and filename stems with `SavePathSuggestion` values. - Ensure consistent test logic using dataclass properties for save paths. - Refactor mocked ViewModel to return `SavePathSuggestion` objects.
…ARKER_FILENAME_SUFFIX` - Update Playwright script to use separate marker elements for filename stem and suffix. - Adjust logic to construct the complete filename from stem and suffix inputs.
…-if-video-name-has-multiple-dots # Conflicts: # OTAnalytics/application/datastore.py # OTAnalytics/plugin_parser/track_export.py # OTAnalytics/plugin_ui/cli.py # tests/unit/OTAnalytics/plugin_parser/test_road_user_assignment_export.py # tests/unit/OTAnalytics/plugin_parser/test_track_export.py
…UiFactory
The factory converted tkinter-style filetypes (e.g. "*.otconfig") into the
dict consumed by FileChooserDialog using `ext.replace(".", "")`, which
removes the dot but leaves the `*`. With enforce_suffix=True the dialog
now shows a locked, read-only suffix badge built from that extension, so
the badge became `.*otconfig` and Save As produced filenames such as
`project.*otconfig.otconfig`. This made the acceptance test
`test_project_information_export_import_playwright` wait forever for
`test_name.otconfig` to appear.
- Extract a build_file_extensions() helper that strips the wildcard via
the existing remove_wildcard_from() before removing the dot, and use it
from both askopenfilename and ask_for_save_file_path.
- Bound the previously-unbounded wait-for-file loop in the acceptance
test so a future save regression fails fast with a clear assertion
instead of hanging.
- Add a unit test for build_file_extensions covering glob, dotted and
bare extension inputs.
Push parsing of the dialog result into the dialog classes themselves so the factory no longer reaches into ``_input_values`` dicts. - ``ToplevelExportFile.get_data()`` now returns ``ExportFileDto``; the stem/directory/extension are exposed as properties driven by ``_input_values``. - ``ToplevelExportCounts.get_data()`` now returns a new ``CountsExportDto`` carrying start/end, counting event, interval, directory, stem, and format. ``CtkUiFactory.configure_export_counts`` consumes that DTO directly instead of unpacking dict keys. - Promote ``ensure_dot_in_extension`` and ``strip_extension`` from ``adapter_ui.helpers`` to ``application.files`` so the application layer (``suggest_save_path``) and both UI plugins can import them without depending on the UI adapter package. - ``SavePathSuggestion`` now validates its inputs in ``__post_init__`` (``file_type`` must start with ``.``, ``context_file_type`` must not), and ``SavePathSuggester.suggest`` sanitises ``file_type`` via ``ensure_dot_in_extension`` so callers can pass it with or without the leading dot. No behavioural change for users; this is preparation for the duplicated-suffix fix that follows.
macOS Tk 9.0 appends ``defaultextension`` to ``initialfile`` even when
``initialfile`` already ends with that extension — but only for
non-system file types like ``.otevents`` (``.csv`` and ``.xlsx`` go
through a different code path and are not affected). Combined with our
``strip_extension`` / ``derive_save_path_from`` pipeline, accepting the
buggy prefilled name compounded the suffix on every otevents export,
producing on-disk filenames like
``foo.copy.events.otevents.otevents.events.otevents``.
Pass ``initialfile`` without the file_type extension so Tk appends it
exactly once. Drop the leading wildcard from ``defaultextension`` to
match the format the API expects (``save_otconfig`` already used this
form).
- Add ``SavePathSuggestion.name_without_file_type`` returning
``{stem}.{context}`` (or ``{stem}`` when no context); use it as
``initialfile`` in both ``_choose_file`` methods.
- Use ``f".{ext}"`` as ``defaultextension`` (no leading ``*``).
…ndles file types with or without leading dot
…d update GitHub Actions to run system tests
…-if-video-name-has-multiple-dots
* validate file existence for expected output files * fix missing dots in export file names
…-otanalytics-if-video-name-has-multiple-dots' into bug/9548-incomplete-filenames-in-otanalytics-if-video-name-has-multiple-dots
schubsen
approved these changes
May 29, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes save/export filename handling so generated paths and Save As dialogs consistently apply file extensions exactly once, including filenames with multiple dots and custom extensions such as
.otevents.Changes
SavePathSuggestionto centralize save directory, filename stem, context suffix, file type, and derived file path handling..oteventssuffixes in CustomTkinter save dialogs by passing the filename without the final file type asinitialfile.*before building enforced suffixes.Testing
SavePathSuggestionintegration and extension handling.OP#9548