Skip to content

Codebase improvements 3#908

Closed
sreckoskocilic wants to merge 14 commits into
fman-users:mainfrom
sreckoskocilic:codebase_improvements_7
Closed

Codebase improvements 3#908
sreckoskocilic wants to merge 14 commits into
fman-users:mainfrom
sreckoskocilic:codebase_improvements_7

Conversation

@sreckoskocilic

@sreckoskocilic sreckoskocilic commented May 7, 2026

Copy link
Copy Markdown
- os_.py: _get_os_release_name() returned None → AttributeError in is_arch()
- os_.py: Popen(**popen_kwargs) allowed shell injection via user JSON settings
- commands/init.py: plugin install path traversal via unsanitized repo name
- plugin.py: unbounded daemon thread spawning → bounded ThreadPoolExecutor
- init.py: _broadcast/_run_command/set_path iterated _listeners without snapshot
- commands/init.py: OpenSelectedFiles passed None to _open_files
- commands/init.py: _from_human_readable used wrong scheme when src/dest differ
- fs_cache.py: unsynchronized tree traversal in update_child/get_child/delete_child
- fs_cache.py: clear('') replaced root while concurrent query() held old reference
- mother_fs.py: always wrap iterdir results in CachedIterator (no plain-list caching)
- thread.py: _pending_tasks mutated from multiple threads without lock
- windows.json: dead Symantec timestamp URL → DigiCert
- fedora.json: missing hidden_imports for pgi overrides
- plugin.py: ReportExceptions double-handled SystemExit then suppressed it
- util/path.py: normalize couldn't resolve .. at root level
- worker.py: shutdown() raised RuntimeError if start() never called
- worker.py: shutdown sentinel skipped task_done()
- model.py: reload() read _files from worker while main thread mutated it
- model.py: _commit_sort_updates used stale row indices after concurrent changes
- icon_provider.py: TOCTOU on _cache[suffix] creating duplicate surrogate files
- model.py: _record_files_main/_on_files_reloaded fired after model replaced
- base.txt: fbs dependency fetched over plain HTTP → HTTPS
- build_impl/init.py: upload_file() used wrong var for local directory copy
- desk.sh + desk.cmd: venv/ → .venv/
- desk.cmd: added missing sign and publish aliases
- build_impl/init.py: chmod 600 missing check=True
- application_context.py: dead string expression → comments + updated PyInstaller URL
- fs.py: added docstrings clarifying copy/move receive full URLs
- init.py: documented before_location_change return convention
- windows.txt: removed stale Send2Trash 1.5.0 comment
- resize_cols_to_contents.py: _distribute_evenly/_exponentially lost pixels to truncation
- session.py: redundant is_first_run re-check diverged from instance attribute
- build.py: bare except: → except Exception: (4 occurrences)
- build.py: removed duplicate dirname import
- .gitignore: added .venv/ entry
- controller.py: file_path param renamed to file_url
- install.txt: NSIS version 2.51 → 3.x
- error.py: documented exc=None/False sentinel
- fs.py: added FileSystem class docstring
- fs_cache.py: Lock → RLock for per-attr locks preventing self-deadlock


- github.py: urlopen/requests.get without timeout or context manager — hangs GUI, leaks socket
- explorer_properties.py: CreatePopupMenu GDI handle leak + duplicate QueryContextMenu call
- uniform_row_heights.py: max() on empty generator crashes when model has 0 columns
- mac.json: added missing apple_developer_team_id for notarytool migration
- Dockerfiles (arch/fedora/ubuntu): venv → .venv to match desk.sh
- widgets.py: float division passed to QWidget.move() → integer division
- fs_cache.py: defaultdict(RLock) unbounded growth → explicit dict with guard lock
- fs_cache.py: added clear_attr() for per-attribute cache invalidation
- mother_fs.py: _on_file_added/_removed now clear parent stat/icon cache
- local/init.py: touch() on existing file clears stale stat cache
- build_impl/init.py: sys.stdout.encoding fallback to utf-8 for non-TTY
- desk.cmd: hardcoded Windows SDK version → dynamic lookup
- ubuntu.py: removed dead libpng12.so.0 exception
- quicksearch.py: guard negative sizeHintForRow return
- core/init.py: natural sort padding %06d → %020d for large numbers
- onboarding/init.py: unclosed <ul> when paragraphs end with list items
- quicksearch_matchers.py: contains_chars/contains_substring now case-insensitive
- zip.py: Run7ZipViaPty.wait() uses os.WEXITSTATUS for proper exit code
- local/init.py: _rename clears destination cache before notify
- install.txt: updated stale Xcode download URL
- widgets.py, key_event.py: "OS X" → "macOS"
- key_event.py, drag_and_drop.py: http:// → https:// Qt doc URLs
- goto.py: removed stale TODO comment


- widgets.py: FilterBar._on_text_changed null guard when sourceModel() returns None
- build_impl/init.py: requests.post() without timeout → added timeout=30
- build_impl/init.py: record_release_url HTTPS validation
- build_impl/init.py: assert SETTINGS['release'] → explicit RuntimeError
- build_impl/init.py: upload_core_to_github excluded .git from cleanup
- fman/init.py: DATA_DIRECTORY join(None, 'fman') crash when APPDATA unset
- plugin.py: deprecated load_module() → importlib.util spec-based loading
- mother_fs.py: CachedIterator.get_next variable shadowing caused wrong pointer
- model.py: dict(self._files) → .copy() preventing RuntimeError on concurrent mutation
- model/init.py: _on_file_removed null sourceModel guard
- aws.py: CloudFront CallerReference uniqueness to prevent silent invalidation skip
- build.py: assert snapshot guard → explicit ValueError
- ubuntu/Dockerfile: deprecated --no-ri --no-rdoc → --no-document
- post-commit: skip silently when FMAN_API_SECRET unset + curl --fail --silent


- extending tests coverage

…paring two tuples, every equality check returns True

- master -> main branch fix
- prepare_trash now calls self.move_to_trash instead of self.delete, so plugin subclasses won't permanently delete files when the user expects trashing
- NotImplementedError - unrecognized platforms fail fast with a clear message instead of a cryptic NameError
- removed shadowing basename import
- get_column_widths uses range so plugin-added columns get their widths saved/restored
…it__ always runs, even on exception.

  - util/qt/__init__.py — Added missing c_void_p import from ctypes, fixing a macOS runtime crash.
  - table.py — Fixed off-by-one: bounds check now rejects len + 1 correctly.
  - widgets.py — Added null guard on _main_window before accessing it in state change handler.
…ved, so a/b/c/../../d correctly becomes a/d.

  - session.py — Removed dead _get_startup_message method (duplicated by _show_startup_messages)
…st entries

- widgets.py: saveState/restoreState crashed when QMainWindow state >= 256 bytes (bytes→struct.pack)
- drag_and_drop.py: unguarded from_qurl in dropMimeData caused crash on invalid URLs
- commands/__init__.py: tuple-unpack crash when zip has != 1 top-level directory
- fs.py: notify_file_changed race on callback list (added lock + snapshot)
- util/__init__.py: Event.trigger mutation during iteration (snapshot copy)
- model.py: sort() mutated shared state from worker thread (atomic commit via main thread)
- model.py: _load_remaining_files iterated self._rows without snapshot
- mother_fs.py: CachedIterator remove→append race made files permanently invisible
- mother_fs.py: CachedIterator.get_next held lock during blocking I/O
- model.py: reload() cleared iterdir cache but not per-file stat cache
- commands/__init__.py: HistoryListener KeyError on GoBack/GoForward
- plugin.py: break after first validation error silently dropped subsequent errors
- commands/__init__.py: wrong show_alert() variant in _Delete task
- model/__init__.py: SortedFileSystemModel memory leak (added shutdown + visited cap)
- resize_cols_to_contents.py: column expansion on shrink ignored available_width
- goto.py: dead dedup code (already_yielded set populated but never checked)
- fman/__init__.py: removed 3 stale TODO comments
- install.txt: fixed timestamp URL + removed hardcoded personal path
- arch.txt: added comment explaining intentional pgi absence
- build.py: publish() missing Debian branch
- ubuntu.py: hardcoded x86_64 libgtk path → ctypes.util.find_library
- mac.py: migrated xcrun altool → notarytool submit --wait
- build_impl/__init__.py: is_package regex → hasattr(__path__)
- command_registry.py: after_command fired even when command raised exception
- commands/__init__.py: removed dead variable
- windows.txt: removed duplicate PyQt5 pin
- fedora/fman.repo: enabled gpgcheck + added gpgkey
- desk.cmd: hardcoded path → relative %~dp0..
- post-commit: hardcoded secret → env var
- CHANGELOG.md: added QtQmlModels to stripped frameworks list
- build_impl/__init__.py: master → main branch reference
…_arch()

- os_.py: Popen(**popen_kwargs) allowed shell injection via user JSON settings
- commands/__init__.py: plugin install path traversal via unsanitized repo name
- plugin.py: unbounded daemon thread spawning → bounded ThreadPoolExecutor
- __init__.py: _broadcast/_run_command/set_path iterated _listeners without snapshot
- commands/__init__.py: OpenSelectedFiles passed None to _open_files
- commands/__init__.py: _from_human_readable used wrong scheme when src/dest differ
- fs_cache.py: unsynchronized tree traversal in update_child/get_child/delete_child
- fs_cache.py: clear('') replaced root while concurrent query() held old reference
- mother_fs.py: always wrap iterdir results in CachedIterator (no plain-list caching)
- thread.py: _pending_tasks mutated from multiple threads without lock
- windows.json: dead Symantec timestamp URL → DigiCert
- fedora.json: missing hidden_imports for pgi overrides
- cursor_movement.py: page_up/page_down dropped toggle_selection on extra step
- plugin.py: ReportExceptions double-handled SystemExit then suppressed it
- util/path.py: normalize couldn't resolve .. at root level
- worker.py: shutdown() raised RuntimeError if start() never called
- worker.py: shutdown sentinel skipped task_done()
- model.py: reload() read _files from worker while main thread mutated it
- model.py: _commit_sort_updates used stale row indices after concurrent changes
- icon_provider.py: TOCTOU on _cache[suffix] creating duplicate surrogate files
- model.py: _record_files_main/_on_files_reloaded fired after model replaced
- base.txt: fbs dependency fetched over plain HTTP → HTTPS
- build_impl/__init__.py: upload_file() used wrong var for local directory copy
- desk.sh + desk.cmd: venv/ → .venv/
- desk.cmd: added missing sign and publish aliases
- build_impl/__init__.py: chmod 600 missing check=True
- application_context.py: dead string expression → comments + updated PyInstaller URL
- fs.py: added docstrings clarifying copy/move receive full URLs
- __init__.py: documented before_location_change return convention
- windows.txt: removed stale Send2Trash 1.5.0 comment
- resize_cols_to_contents.py: _distribute_evenly/_exponentially lost pixels to truncation
- session.py: redundant is_first_run re-check diverged from instance attribute
- build.py: bare except: → except Exception: (4 occurrences)
- build.py: removed duplicate dirname import
- .gitignore: added .venv/ entry
- controller.py: file_path param renamed to file_url
- install.txt: NSIS version 2.51 → 3.x
- error.py: documented exc=None/False sentinel
- fs.py: added FileSystem class docstring
- fs_cache.py: Lock → RLock for per-attr locks preventing self-deadlock
…— hangs GUI, leaks socket

- explorer_properties.py: CreatePopupMenu GDI handle leak + duplicate QueryContextMenu call
- uniform_row_heights.py: max() on empty generator crashes when model has 0 columns
- mac.json: added missing apple_developer_team_id for notarytool migration
- Dockerfiles (arch/fedora/ubuntu): venv → .venv to match desk.sh
- widgets.py: float division passed to QWidget.move() → integer division
- fs_cache.py: defaultdict(RLock) unbounded growth → explicit dict with guard lock
- fs_cache.py: added clear_attr() for per-attribute cache invalidation
- mother_fs.py: _on_file_added/_removed now clear parent stat/icon cache
- local/__init__.py: touch() on existing file clears stale stat cache
- build_impl/__init__.py: sys.stdout.encoding fallback to utf-8 for non-TTY
- desk.cmd: hardcoded Windows SDK version → dynamic lookup
- ubuntu.py: removed dead libpng12.so.0 exception
- quicksearch.py: guard negative sizeHintForRow return
- core/__init__.py: natural sort padding %06d → %020d for large numbers
- onboarding/__init__.py: unclosed <ul> when paragraphs end with list items
- quicksearch_matchers.py: contains_chars/contains_substring now case-insensitive
- zip.py: Run7ZipViaPty.wait() uses os.WEXITSTATUS for proper exit code
- local/__init__.py: _rename clears destination cache before notify
- install.txt: updated stale Xcode download URL
- widgets.py, key_event.py: "OS X" → "macOS"
- key_event.py, drag_and_drop.py: http:// → https:// Qt doc URLs
- goto.py: removed stale TODO comment
…) returns None

- build_impl/__init__.py: requests.post() without timeout → added timeout=30
- build_impl/__init__.py: record_release_url HTTPS validation
- build_impl/__init__.py: assert SETTINGS['release'] → explicit RuntimeError
- build_impl/__init__.py: upload_core_to_github excluded .git from cleanup
- fman/__init__.py: DATA_DIRECTORY join(None, 'fman') crash when APPDATA unset
- plugin.py: deprecated load_module() → importlib.util spec-based loading
- mother_fs.py: CachedIterator.get_next variable shadowing caused wrong pointer
- model.py: dict(self._files) → .copy() preventing RuntimeError on concurrent mutation
- model/__init__.py: _on_file_removed null sourceModel guard
- aws.py: CloudFront CallerReference uniqueness to prevent silent invalidation skip
- build.py: assert snapshot guard → explicit ValueError
- ubuntu/Dockerfile: deprecated --no-ri --no-rdoc → --no-document
- post-commit: skip silently when FMAN_API_SECRET unset + curl --fail --silent
@sreckoskocilic

Copy link
Copy Markdown
Author

Closing in favor of smaller, thematic PRs. This was too large to review as a single PR

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant