winipedia-utils 0.1.52__tar.gz → 0.1.54__tar.gz

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.
Files changed (100) hide show
  1. {winipedia_utils-0.1.52 → winipedia_utils-0.1.54}/PKG-INFO +1 -1
  2. {winipedia_utils-0.1.52 → winipedia_utils-0.1.54}/pyproject.toml +1 -1
  3. {winipedia_utils-0.1.52 → winipedia_utils-0.1.54}/winipedia_utils/django/command.py +2 -2
  4. {winipedia_utils-0.1.52 → winipedia_utils-0.1.54}/winipedia_utils/modules/package.py +14 -5
  5. {winipedia_utils-0.1.52 → winipedia_utils-0.1.54}/winipedia_utils/oop/mixins/meta.py +6 -6
  6. {winipedia_utils-0.1.52 → winipedia_utils-0.1.54}/winipedia_utils/oop/mixins/mixin.py +11 -2
  7. {winipedia_utils-0.1.52 → winipedia_utils-0.1.54}/winipedia_utils/pyside/ui/base/base.py +5 -14
  8. {winipedia_utils-0.1.52 → winipedia_utils-0.1.54}/winipedia_utils/pyside/ui/pages/base/base.py +11 -5
  9. {winipedia_utils-0.1.52 → winipedia_utils-0.1.54}/winipedia_utils/pyside/ui/pages/browser.py +0 -4
  10. {winipedia_utils-0.1.52 → winipedia_utils-0.1.54}/winipedia_utils/pyside/ui/pages/player.py +1 -5
  11. {winipedia_utils-0.1.52 → winipedia_utils-0.1.54}/winipedia_utils/pyside/ui/windows/base/base.py +10 -12
  12. {winipedia_utils-0.1.52 → winipedia_utils-0.1.54}/LICENSE +0 -0
  13. {winipedia_utils-0.1.52 → winipedia_utils-0.1.54}/README.md +0 -0
  14. {winipedia_utils-0.1.52 → winipedia_utils-0.1.54}/winipedia_utils/__init__.py +0 -0
  15. {winipedia_utils-0.1.52 → winipedia_utils-0.1.54}/winipedia_utils/concurrent/__init__.py +0 -0
  16. {winipedia_utils-0.1.52 → winipedia_utils-0.1.54}/winipedia_utils/concurrent/concurrent.py +0 -0
  17. {winipedia_utils-0.1.52 → winipedia_utils-0.1.54}/winipedia_utils/concurrent/multiprocessing.py +0 -0
  18. {winipedia_utils-0.1.52 → winipedia_utils-0.1.54}/winipedia_utils/concurrent/multithreading.py +0 -0
  19. {winipedia_utils-0.1.52 → winipedia_utils-0.1.54}/winipedia_utils/consts.py +0 -0
  20. {winipedia_utils-0.1.52 → winipedia_utils-0.1.54}/winipedia_utils/data/__init__.py +0 -0
  21. {winipedia_utils-0.1.52 → winipedia_utils-0.1.54}/winipedia_utils/data/dataframe.py +0 -0
  22. {winipedia_utils-0.1.52 → winipedia_utils-0.1.54}/winipedia_utils/django/__init__.py +0 -0
  23. {winipedia_utils-0.1.52 → winipedia_utils-0.1.54}/winipedia_utils/django/bulk.py +0 -0
  24. {winipedia_utils-0.1.52 → winipedia_utils-0.1.54}/winipedia_utils/django/database.py +0 -0
  25. {winipedia_utils-0.1.52 → winipedia_utils-0.1.54}/winipedia_utils/git/__init__.py +0 -0
  26. {winipedia_utils-0.1.52 → winipedia_utils-0.1.54}/winipedia_utils/git/gitignore/__init__.py +0 -0
  27. {winipedia_utils-0.1.52 → winipedia_utils-0.1.54}/winipedia_utils/git/gitignore/gitignore.py +0 -0
  28. {winipedia_utils-0.1.52 → winipedia_utils-0.1.54}/winipedia_utils/git/pre_commit/__init__.py +0 -0
  29. {winipedia_utils-0.1.52 → winipedia_utils-0.1.54}/winipedia_utils/git/pre_commit/config.py +0 -0
  30. {winipedia_utils-0.1.52 → winipedia_utils-0.1.54}/winipedia_utils/git/pre_commit/hooks.py +0 -0
  31. {winipedia_utils-0.1.52 → winipedia_utils-0.1.54}/winipedia_utils/git/pre_commit/run_hooks.py +0 -0
  32. {winipedia_utils-0.1.52 → winipedia_utils-0.1.54}/winipedia_utils/iterating/__init__.py +0 -0
  33. {winipedia_utils-0.1.52 → winipedia_utils-0.1.54}/winipedia_utils/iterating/iterate.py +0 -0
  34. {winipedia_utils-0.1.52 → winipedia_utils-0.1.54}/winipedia_utils/logging/__init__.py +0 -0
  35. {winipedia_utils-0.1.52 → winipedia_utils-0.1.54}/winipedia_utils/logging/ansi.py +0 -0
  36. {winipedia_utils-0.1.52 → winipedia_utils-0.1.54}/winipedia_utils/logging/config.py +0 -0
  37. {winipedia_utils-0.1.52 → winipedia_utils-0.1.54}/winipedia_utils/logging/logger.py +0 -0
  38. {winipedia_utils-0.1.52 → winipedia_utils-0.1.54}/winipedia_utils/modules/__init__.py +0 -0
  39. {winipedia_utils-0.1.52 → winipedia_utils-0.1.54}/winipedia_utils/modules/class_.py +0 -0
  40. {winipedia_utils-0.1.52 → winipedia_utils-0.1.54}/winipedia_utils/modules/function.py +0 -0
  41. {winipedia_utils-0.1.52 → winipedia_utils-0.1.54}/winipedia_utils/modules/module.py +0 -0
  42. {winipedia_utils-0.1.52 → winipedia_utils-0.1.54}/winipedia_utils/oop/__init__.py +0 -0
  43. {winipedia_utils-0.1.52 → winipedia_utils-0.1.54}/winipedia_utils/oop/mixins/__init__.py +0 -0
  44. {winipedia_utils-0.1.52 → winipedia_utils-0.1.54}/winipedia_utils/os/__init__.py +0 -0
  45. {winipedia_utils-0.1.52 → winipedia_utils-0.1.54}/winipedia_utils/os/os.py +0 -0
  46. {winipedia_utils-0.1.52 → winipedia_utils-0.1.54}/winipedia_utils/projects/__init__.py +0 -0
  47. {winipedia_utils-0.1.52 → winipedia_utils-0.1.54}/winipedia_utils/projects/poetry/__init__.py +0 -0
  48. {winipedia_utils-0.1.52 → winipedia_utils-0.1.54}/winipedia_utils/projects/poetry/config.py +0 -0
  49. {winipedia_utils-0.1.52 → winipedia_utils-0.1.54}/winipedia_utils/projects/poetry/poetry.py +0 -0
  50. {winipedia_utils-0.1.52 → winipedia_utils-0.1.54}/winipedia_utils/projects/project.py +0 -0
  51. {winipedia_utils-0.1.52 → winipedia_utils-0.1.54}/winipedia_utils/py.typed +0 -0
  52. {winipedia_utils-0.1.52 → winipedia_utils-0.1.54}/winipedia_utils/pyside/__init__.py +0 -0
  53. {winipedia_utils-0.1.52 → winipedia_utils-0.1.54}/winipedia_utils/pyside/core/__init__.py +0 -0
  54. {winipedia_utils-0.1.52 → winipedia_utils-0.1.54}/winipedia_utils/pyside/core/py_qiodevice.py +0 -0
  55. {winipedia_utils-0.1.52 → winipedia_utils-0.1.54}/winipedia_utils/pyside/ui/__init__.py +0 -0
  56. {winipedia_utils-0.1.52 → winipedia_utils-0.1.54}/winipedia_utils/pyside/ui/base/__init__.py +0 -0
  57. {winipedia_utils-0.1.52 → winipedia_utils-0.1.54}/winipedia_utils/pyside/ui/pages/__init__.py +0 -0
  58. {winipedia_utils-0.1.52 → winipedia_utils-0.1.54}/winipedia_utils/pyside/ui/pages/base/__init__.py +0 -0
  59. {winipedia_utils-0.1.52 → winipedia_utils-0.1.54}/winipedia_utils/pyside/ui/widgets/__init__.py +0 -0
  60. {winipedia_utils-0.1.52 → winipedia_utils-0.1.54}/winipedia_utils/pyside/ui/widgets/browser.py +0 -0
  61. {winipedia_utils-0.1.52 → winipedia_utils-0.1.54}/winipedia_utils/pyside/ui/widgets/clickable_widget.py +0 -0
  62. {winipedia_utils-0.1.52 → winipedia_utils-0.1.54}/winipedia_utils/pyside/ui/widgets/media_player.py +0 -0
  63. {winipedia_utils-0.1.52 → winipedia_utils-0.1.54}/winipedia_utils/pyside/ui/widgets/notification.py +0 -0
  64. {winipedia_utils-0.1.52 → winipedia_utils-0.1.54}/winipedia_utils/pyside/ui/windows/__init__.py +0 -0
  65. {winipedia_utils-0.1.52 → winipedia_utils-0.1.54}/winipedia_utils/pyside/ui/windows/base/__init__.py +0 -0
  66. {winipedia_utils-0.1.52 → winipedia_utils-0.1.54}/winipedia_utils/resources/__init__.py +0 -0
  67. {winipedia_utils-0.1.52 → winipedia_utils-0.1.54}/winipedia_utils/resources/svgs/__init__.py +0 -0
  68. {winipedia_utils-0.1.52 → winipedia_utils-0.1.54}/winipedia_utils/resources/svgs/delete_garbage_can.svg +0 -0
  69. {winipedia_utils-0.1.52 → winipedia_utils-0.1.54}/winipedia_utils/resources/svgs/download_arrow.svg +0 -0
  70. {winipedia_utils-0.1.52 → winipedia_utils-0.1.54}/winipedia_utils/resources/svgs/exit_fullscreen_icon.svg +0 -0
  71. {winipedia_utils-0.1.52 → winipedia_utils-0.1.54}/winipedia_utils/resources/svgs/fullscreen_icon.svg +0 -0
  72. {winipedia_utils-0.1.52 → winipedia_utils-0.1.54}/winipedia_utils/resources/svgs/menu_icon.svg +0 -0
  73. {winipedia_utils-0.1.52 → winipedia_utils-0.1.54}/winipedia_utils/resources/svgs/pause_icon.svg +0 -0
  74. {winipedia_utils-0.1.52 → winipedia_utils-0.1.54}/winipedia_utils/resources/svgs/play_icon.svg +0 -0
  75. {winipedia_utils-0.1.52 → winipedia_utils-0.1.54}/winipedia_utils/resources/svgs/plus_icon.svg +0 -0
  76. {winipedia_utils-0.1.52 → winipedia_utils-0.1.54}/winipedia_utils/resources/svgs/svg.py +0 -0
  77. {winipedia_utils-0.1.52 → winipedia_utils-0.1.54}/winipedia_utils/security/__init__.py +0 -0
  78. {winipedia_utils-0.1.52 → winipedia_utils-0.1.54}/winipedia_utils/security/cryptography.py +0 -0
  79. {winipedia_utils-0.1.52 → winipedia_utils-0.1.54}/winipedia_utils/security/keyring.py +0 -0
  80. {winipedia_utils-0.1.52 → winipedia_utils-0.1.54}/winipedia_utils/setup.py +0 -0
  81. {winipedia_utils-0.1.52 → winipedia_utils-0.1.54}/winipedia_utils/testing/__init__.py +0 -0
  82. {winipedia_utils-0.1.52 → winipedia_utils-0.1.54}/winipedia_utils/testing/assertions.py +0 -0
  83. {winipedia_utils-0.1.52 → winipedia_utils-0.1.54}/winipedia_utils/testing/convention.py +0 -0
  84. {winipedia_utils-0.1.52 → winipedia_utils-0.1.54}/winipedia_utils/testing/create_tests.py +0 -0
  85. {winipedia_utils-0.1.52 → winipedia_utils-0.1.54}/winipedia_utils/testing/fixtures.py +0 -0
  86. {winipedia_utils-0.1.52 → winipedia_utils-0.1.54}/winipedia_utils/testing/tests/__init__.py +0 -0
  87. {winipedia_utils-0.1.52 → winipedia_utils-0.1.54}/winipedia_utils/testing/tests/base/__init__.py +0 -0
  88. {winipedia_utils-0.1.52 → winipedia_utils-0.1.54}/winipedia_utils/testing/tests/base/fixtures/__init__.py +0 -0
  89. {winipedia_utils-0.1.52 → winipedia_utils-0.1.54}/winipedia_utils/testing/tests/base/fixtures/fixture.py +0 -0
  90. {winipedia_utils-0.1.52 → winipedia_utils-0.1.54}/winipedia_utils/testing/tests/base/fixtures/scopes/__init__.py +0 -0
  91. {winipedia_utils-0.1.52 → winipedia_utils-0.1.54}/winipedia_utils/testing/tests/base/fixtures/scopes/class_.py +0 -0
  92. {winipedia_utils-0.1.52 → winipedia_utils-0.1.54}/winipedia_utils/testing/tests/base/fixtures/scopes/function.py +0 -0
  93. {winipedia_utils-0.1.52 → winipedia_utils-0.1.54}/winipedia_utils/testing/tests/base/fixtures/scopes/module.py +0 -0
  94. {winipedia_utils-0.1.52 → winipedia_utils-0.1.54}/winipedia_utils/testing/tests/base/fixtures/scopes/package.py +0 -0
  95. {winipedia_utils-0.1.52 → winipedia_utils-0.1.54}/winipedia_utils/testing/tests/base/fixtures/scopes/session.py +0 -0
  96. {winipedia_utils-0.1.52 → winipedia_utils-0.1.54}/winipedia_utils/testing/tests/base/utils/__init__.py +0 -0
  97. {winipedia_utils-0.1.52 → winipedia_utils-0.1.54}/winipedia_utils/testing/tests/base/utils/utils.py +0 -0
  98. {winipedia_utils-0.1.52 → winipedia_utils-0.1.54}/winipedia_utils/testing/tests/conftest.py +0 -0
  99. {winipedia_utils-0.1.52 → winipedia_utils-0.1.54}/winipedia_utils/text/__init__.py +0 -0
  100. {winipedia_utils-0.1.52 → winipedia_utils-0.1.54}/winipedia_utils/text/string.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: winipedia-utils
3
- Version: 0.1.52
3
+ Version: 0.1.54
4
4
  Summary: A package with many utility functions
5
5
  License: MIT
6
6
  Author: Winipedia
@@ -1,7 +1,7 @@
1
1
  # Project section
2
2
  [project]
3
3
  name = "winipedia-utils"
4
- version = "0.1.52"
4
+ version = "0.1.54"
5
5
  description = "A package with many utility functions"
6
6
  readme = "README.md"
7
7
  requires-python = ">=3.12,<3.14"
@@ -12,12 +12,12 @@ from typing import Any, final
12
12
 
13
13
  from django.core.management import BaseCommand
14
14
 
15
- from winipedia_utils.oop.mixins.mixin import ABCImplementationLoggingMixin
15
+ from winipedia_utils.oop.mixins.mixin import ABCLoggingMixin
16
16
 
17
17
  logger = logging.getLogger(__name__)
18
18
 
19
19
 
20
- class ABCBaseCommand(ABCImplementationLoggingMixin, BaseCommand):
20
+ class ABCBaseCommand(ABCLoggingMixin, BaseCommand):
21
21
  """Abstract base class for Django management commands with logging and validation.
22
22
 
23
23
  This class serves as a foundation for creating Django management commands that
@@ -368,14 +368,23 @@ def get_main_package() -> ModuleType:
368
368
 
369
369
  Even when this package is installed as a module.
370
370
  """
371
+ from winipedia_utils.modules.module import to_module_name
372
+
371
373
  main = sys.modules.get("__main__")
372
374
  if main is None:
373
375
  msg = "No __main__ module found"
374
376
  raise ValueError(msg)
375
377
 
376
- package_name = main.__package__
377
- if package_name is None:
378
- msg = "No __package__ found in __main__"
379
- raise ValueError(msg)
378
+ package_name = getattr(main, "__package__", None)
379
+ if package_name:
380
+ package_name = package_name.split(".")[0]
381
+ return import_module(package_name)
382
+
383
+ file_name = getattr(main, "__file__", None)
384
+ if file_name:
385
+ package_name = to_module_name(file_name)
386
+ package_name = package_name.split(".")[0]
387
+ return import_module(package_name)
380
388
 
381
- return import_module(package_name)
389
+ msg = "Not able to determine the main package"
390
+ raise ValueError(msg)
@@ -21,7 +21,7 @@ from winipedia_utils.text.string import value_to_truncated_string
21
21
  logger = get_logger(__name__)
22
22
 
23
23
 
24
- class LoggingMeta(ABCMeta):
24
+ class ABCLoggingMeta(ABCMeta):
25
25
  """Metaclass that automatically adds logging to class methods.
26
26
 
27
27
  Wraps non-magic methods with a logging decorator that tracks method calls,
@@ -30,11 +30,11 @@ class LoggingMeta(ABCMeta):
30
30
  """
31
31
 
32
32
  def __new__(
33
- mcs: type["LoggingMeta"],
33
+ mcs: type["ABCLoggingMeta"],
34
34
  name: str,
35
35
  bases: tuple[type, ...],
36
36
  dct: dict[str, Any],
37
- ) -> "LoggingMeta":
37
+ ) -> "ABCLoggingMeta":
38
38
  """Create a new class with logging-wrapped methods.
39
39
 
40
40
  Args:
@@ -169,7 +169,7 @@ class LoggingMeta(ABCMeta):
169
169
  return wrapper
170
170
 
171
171
 
172
- class ImplementationMeta(ABCMeta):
172
+ class StrictABCMeta(ABCMeta):
173
173
  """Metaclass that enforces implementation.
174
174
 
175
175
  Ensures that concrete subclasses properly implement all required attributes
@@ -179,7 +179,7 @@ class ImplementationMeta(ABCMeta):
179
179
  """
180
180
 
181
181
  def __init__(
182
- cls: "ImplementationMeta",
182
+ cls: "StrictABCMeta",
183
183
  name: str,
184
184
  bases: tuple[type, ...],
185
185
  namespace: dict[str, Any],
@@ -319,7 +319,7 @@ class ImplementationMeta(ABCMeta):
319
319
  return list(attrs)
320
320
 
321
321
 
322
- class ABCImplementationLoggingMeta(ImplementationMeta, LoggingMeta):
322
+ class StrictABCLoggingMeta(StrictABCMeta, ABCLoggingMeta):
323
323
  """Combined metaclass that merges implementation, logging, and ABC functionality.
324
324
 
325
325
  This metaclass combines the features of:
@@ -11,12 +11,12 @@ enforcement and built-in logging capabilities.
11
11
  """
12
12
 
13
13
  from winipedia_utils.logging.logger import get_logger
14
- from winipedia_utils.oop.mixins.meta import ABCImplementationLoggingMeta
14
+ from winipedia_utils.oop.mixins.meta import ABCLoggingMeta, StrictABCLoggingMeta
15
15
 
16
16
  logger = get_logger(__name__)
17
17
 
18
18
 
19
- class ABCImplementationLoggingMixin(metaclass=ABCImplementationLoggingMeta):
19
+ class StrictABCLoggingMixin(metaclass=StrictABCLoggingMeta):
20
20
  """mixin class that provides implementation, logging, and ABC functionality.
21
21
 
22
22
  This mixin can be used as a base class for other mixins that need:
@@ -26,3 +26,12 @@ class ABCImplementationLoggingMixin(metaclass=ABCImplementationLoggingMeta):
26
26
 
27
27
  Subclasses must set __abstract__ = False when they provide concrete implementations.
28
28
  """
29
+
30
+
31
+ class ABCLoggingMixin(metaclass=ABCLoggingMeta):
32
+ """Mixin class that provides automatic method logging with performance tracking.
33
+
34
+ This mixin can be used as a base class for other mixins that need:
35
+ - Automatic method logging (from LoggingMeta)
36
+
37
+ """
@@ -5,7 +5,7 @@ This module contains the base UI class for the VideoVault application.
5
5
 
6
6
  from abc import abstractmethod
7
7
  from types import ModuleType
8
- from typing import TYPE_CHECKING, Any, Self, cast, final
8
+ from typing import TYPE_CHECKING, Any, Self, cast
9
9
 
10
10
  from PySide6.QtCore import QObject
11
11
  from PySide6.QtGui import QIcon
@@ -15,7 +15,7 @@ from winipedia_utils.modules.class_ import (
15
15
  get_all_nonabstract_subclasses,
16
16
  )
17
17
  from winipedia_utils.modules.package import get_main_package, walk_package
18
- from winipedia_utils.oop.mixins.meta import ABCImplementationLoggingMeta
18
+ from winipedia_utils.oop.mixins.meta import ABCLoggingMeta
19
19
  from winipedia_utils.resources.svgs.svg import get_svg_path
20
20
  from winipedia_utils.text.string import split_on_uppercase
21
21
 
@@ -25,17 +25,16 @@ if TYPE_CHECKING:
25
25
  from winipedia_utils.pyside.ui.windows.base.base import Base as BaseWindow
26
26
 
27
27
 
28
- class QABCImplementationLoggingMeta(
29
- ABCImplementationLoggingMeta,
28
+ class QABCLoggingMeta(
29
+ ABCLoggingMeta,
30
30
  type(QObject), # type: ignore[misc]
31
31
  ):
32
32
  """Metaclass for the QABCImplementationLoggingMixin."""
33
33
 
34
34
 
35
- class Base(metaclass=QABCImplementationLoggingMeta):
35
+ class Base(metaclass=QABCLoggingMeta):
36
36
  """Base UI class for a Qt application."""
37
37
 
38
- @final
39
38
  def __init__(self, *args: Any, **kwargs: Any) -> None:
40
39
  """Initialize the base UI."""
41
40
  super().__init__(*args, **kwargs)
@@ -76,7 +75,6 @@ class Base(metaclass=QABCImplementationLoggingMeta):
76
75
  """
77
76
 
78
77
  @classmethod
79
- @final
80
78
  def get_display_name(cls) -> str:
81
79
  """Get the display name of the UI.
82
80
 
@@ -86,7 +84,6 @@ class Base(metaclass=QABCImplementationLoggingMeta):
86
84
  return " ".join(split_on_uppercase(cls.__name__))
87
85
 
88
86
  @classmethod
89
- @final
90
87
  def get_subclasses(cls, package: ModuleType | None = None) -> list[type[Self]]:
91
88
  """Get all subclasses of the UI.
92
89
 
@@ -106,7 +103,6 @@ class Base(metaclass=QABCImplementationLoggingMeta):
106
103
  children = get_all_nonabstract_subclasses(cls)
107
104
  return sorted(children, key=lambda cls: cls.__name__)
108
105
 
109
- @final
110
106
  def set_current_page(self, page_cls: type["BasePage"]) -> None:
111
107
  """Set the current page in the stack.
112
108
 
@@ -115,7 +111,6 @@ class Base(metaclass=QABCImplementationLoggingMeta):
115
111
  """
116
112
  self.get_stack().setCurrentWidget(self.get_page(page_cls))
117
113
 
118
- @final
119
114
  def get_stack(self) -> QStackedWidget:
120
115
  """Get the stack widget of the window.
121
116
 
@@ -126,7 +121,6 @@ class Base(metaclass=QABCImplementationLoggingMeta):
126
121
 
127
122
  return window.stack
128
123
 
129
- @final
130
124
  def get_stack_pages(self) -> list["BasePage"]:
131
125
  """Get all pages from the stack.
132
126
 
@@ -139,7 +133,6 @@ class Base(metaclass=QABCImplementationLoggingMeta):
139
133
  # get all the pages
140
134
  return [cast("BasePage", stack.widget(i)) for i in range(stack.count())]
141
135
 
142
- @final
143
136
  def get_page[T: "BasePage"](self, page_cls: type[T]) -> T:
144
137
  """Get a specific page from the stack.
145
138
 
@@ -155,7 +148,6 @@ class Base(metaclass=QABCImplementationLoggingMeta):
155
148
  return cast("T", page)
156
149
 
157
150
  @classmethod
158
- @final
159
151
  def get_svg_icon(cls, svg_name: str, package: ModuleType | None = None) -> QIcon:
160
152
  """Get a QIcon for an SVG file.
161
153
 
@@ -170,7 +162,6 @@ class Base(metaclass=QABCImplementationLoggingMeta):
170
162
  return QIcon(str(get_svg_path(svg_name, package=package)))
171
163
 
172
164
  @classmethod
173
- @final
174
165
  def get_page_static[T: "BasePage"](cls, page_cls: type[T]) -> T:
175
166
  """Get a page statically from the main window.
176
167
 
@@ -4,7 +4,7 @@ This module contains the base page class for the VideoVault application.
4
4
  """
5
5
 
6
6
  from functools import partial
7
- from typing import final
7
+ from typing import TYPE_CHECKING, Any
8
8
 
9
9
  from PySide6.QtCore import Qt
10
10
  from PySide6.QtWidgets import (
@@ -19,11 +19,19 @@ from PySide6.QtWidgets import (
19
19
 
20
20
  from winipedia_utils.pyside.ui.base.base import Base as BaseUI
21
21
 
22
+ if TYPE_CHECKING:
23
+ from winipedia_utils.pyside.ui.windows.base.base import Base as BaseWindow
24
+
22
25
 
23
26
  class Base(BaseUI, QWidget):
24
27
  """Base page class for the VideoVault application."""
25
28
 
26
- @final
29
+ def __init__(self, base_window: "BaseWindow", *args: Any, **kwargs: Any) -> None:
30
+ """Initialize the base page."""
31
+ super().__init__(*args, **kwargs)
32
+ self.base_window = base_window
33
+ self.base_window.add_page(self)
34
+
27
35
  def base_setup(self) -> None:
28
36
  """Setup the base Qt object of the UI.
29
37
 
@@ -39,7 +47,6 @@ class Base(BaseUI, QWidget):
39
47
 
40
48
  self.add_menu_dropdown_button()
41
49
 
42
- @final
43
50
  def add_menu_dropdown_button(self) -> None:
44
51
  """Add a dropdown menu that leads to each page.
45
52
 
@@ -58,11 +65,10 @@ class Base(BaseUI, QWidget):
58
65
  self.menu_dropdown = QMenu(self.menu_button)
59
66
  self.menu_button.setMenu(self.menu_dropdown)
60
67
 
61
- for page_cls in Base.get_subclasses():
68
+ for page_cls in self.base_window.get_all_page_classes():
62
69
  action = self.menu_dropdown.addAction(page_cls.get_display_name())
63
70
  action.triggered.connect(partial(self.set_current_page, page_cls))
64
71
 
65
- @final
66
72
  def add_to_page_button(
67
73
  self, to_page_cls: type["Base"], layout: QLayout
68
74
  ) -> QPushButton:
@@ -3,8 +3,6 @@
3
3
  This module contains the add downloads page class for the VideoVault application.
4
4
  """
5
5
 
6
- from typing import final
7
-
8
6
  from winipedia_utils.pyside.ui.pages.base.base import Base as BasePage
9
7
  from winipedia_utils.pyside.ui.widgets.browser import Browser as BrowserWidget
10
8
 
@@ -12,7 +10,6 @@ from winipedia_utils.pyside.ui.widgets.browser import Browser as BrowserWidget
12
10
  class Browser(BasePage):
13
11
  """Add downloads page for the VideoVault application."""
14
12
 
15
- @final
16
13
  def setup(self) -> None:
17
14
  """Setup the UI.
18
15
 
@@ -20,7 +17,6 @@ class Browser(BasePage):
20
17
  """
21
18
  self.add_brwoser()
22
19
 
23
- @final
24
20
  def add_brwoser(self) -> None:
25
21
  """Add a browser to surf the web.
26
22
 
@@ -6,7 +6,7 @@ This module contains the player page class for the VideoVault application.
6
6
  from abc import abstractmethod
7
7
  from collections.abc import Callable
8
8
  from pathlib import Path
9
- from typing import Any, final
9
+ from typing import Any
10
10
 
11
11
  from cryptography.hazmat.primitives.ciphers.aead import AESGCM
12
12
 
@@ -26,7 +26,6 @@ class Player(BasePage):
26
26
  position: The position to start playback from in milliseconds.
27
27
  """
28
28
 
29
- @final
30
29
  def setup(self) -> None:
31
30
  """Setup the UI.
32
31
 
@@ -34,7 +33,6 @@ class Player(BasePage):
34
33
  """
35
34
  self.media_player = MediaPlayer(self.v_layout)
36
35
 
37
- @final
38
36
  def play_file_from_func(
39
37
  self,
40
38
  play_func: Callable[..., Any],
@@ -58,7 +56,6 @@ class Player(BasePage):
58
56
  # Stop current playback and clean up resources
59
57
  play_func(path=path, position=position, **kwargs)
60
58
 
61
- @final
62
59
  def play_file(self, path: Path, position: int = 0) -> None:
63
60
  """Play a regular video file.
64
61
 
@@ -70,7 +67,6 @@ class Player(BasePage):
70
67
  self.media_player.play_file, path=path, position=position
71
68
  )
72
69
 
73
- @final
74
70
  def play_encrypted_file(
75
71
  self, path: Path, aes_gcm: AESGCM, position: int = 0
76
72
  ) -> None:
@@ -5,7 +5,6 @@ This module contains the base window class for the VideoVault application.
5
5
 
6
6
  from abc import abstractmethod
7
7
  from collections.abc import Generator
8
- from typing import final
9
8
 
10
9
  from PySide6.QtWidgets import QMainWindow, QStackedWidget
11
10
 
@@ -16,12 +15,16 @@ from winipedia_utils.pyside.ui.pages.base.base import Base as BasePage
16
15
  class Base(BaseUI, QMainWindow):
17
16
  """Base window class for the VideoVault application."""
18
17
 
18
+ @classmethod
19
+ @abstractmethod
20
+ def get_all_page_classes(cls) -> list[type[BasePage]]:
21
+ """Get all page classes."""
22
+
19
23
  @classmethod
20
24
  @abstractmethod
21
25
  def get_start_page_cls(cls) -> type[BasePage]:
22
26
  """Get the start page class."""
23
27
 
24
- @final
25
28
  def base_setup(self) -> None:
26
29
  """Get the Qt object of the UI."""
27
30
  self.setWindowTitle(self.get_display_name())
@@ -29,24 +32,19 @@ class Base(BaseUI, QMainWindow):
29
32
  self.stack = QStackedWidget()
30
33
  self.setCentralWidget(self.stack)
31
34
 
32
- self.add_pages()
35
+ self.make_pages()
33
36
 
34
37
  self.set_start_page()
35
38
 
36
- @final
37
- def add_pages(self) -> None:
39
+ def add_page(self, page: BasePage) -> None:
38
40
  """Add the pages to the window."""
39
- self.pages = list(self.make_pages())
40
- for page in self.pages:
41
- self.stack.addWidget(page)
41
+ self.stack.addWidget(page)
42
42
 
43
- @final
44
43
  def make_pages(self) -> Generator[BasePage, None, None]:
45
44
  """Get the pages to add to the window."""
46
- for page_cls in BasePage.get_subclasses():
47
- yield page_cls()
45
+ for page_cls in self.get_all_page_classes():
46
+ yield page_cls(base_window=self)
48
47
 
49
- @final
50
48
  def set_start_page(self) -> None:
51
49
  """Set the start page."""
52
50
  self.set_current_page(self.get_start_page_cls())