Skip to content

bug/9548-incomplete-filenames-in-otanalytics-if-video-name-has-multiple-dots#821

Merged
schubsen merged 54 commits into
mainfrom
bug/9548-incomplete-filenames-in-otanalytics-if-video-name-has-multiple-dots
May 29, 2026
Merged

bug/9548-incomplete-filenames-in-otanalytics-if-video-name-has-multiple-dots#821
schubsen merged 54 commits into
mainfrom
bug/9548-incomplete-filenames-in-otanalytics-if-video-name-has-multiple-dots

Conversation

@randy-seng

@randy-seng randy-seng commented Mar 27, 2026

Copy link
Copy Markdown
Member

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

  • Introduced SavePathSuggestion to centralize save directory, filename stem, context suffix, file type, and derived file path handling.
  • Normalized extension handling so callers can pass file types with or without a leading dot.
  • Fixed duplicated .otevents suffixes in CustomTkinter save dialogs by passing the filename without the final file type as initialfile.
  • Fixed NiceGUI file extension parsing by stripping glob wildcards like * before building enforced suffixes.
  • Refactored CustomTkinter export dialogs to return typed DTOs instead of exposing internal input dictionaries.
  • Tightened export-count dialog behavior
  • Updated unit and acceptance tests around save path suggestions, export dialogs, and file extension handling.

Testing

  • Updated unit tests for SavePathSuggestion integration and extension handling.
  • Added coverage for NiceGUI file extension conversion.
  • Improved acceptance-test timeout behavior so save regressions fail clearly instead of hanging.

OP#9548

… 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.
@randy-seng randy-seng requested a review from schubsen April 13, 2026 09:36

@schubsen schubsen left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The files with the suffixes

  • .tracks_metadata.json
  • .tracks.csv
  • videos_metadata.json
    still get truncated

randy-seng added 27 commits May 11, 2026 10:19
… 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).
randy-seng added 21 commits May 26, 2026 07:56
…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
@randy-seng randy-seng requested a review from schubsen May 28, 2026 13:46
* 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 schubsen merged commit aa1dabc into main May 29, 2026
18 checks passed
@schubsen schubsen deleted the bug/9548-incomplete-filenames-in-otanalytics-if-video-name-has-multiple-dots branch May 29, 2026 15:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants