Commit Graph
125 Commits
Author SHA1 Message Date
David Sangrey 913a2340a7 Fix Merge Issues 2026-01-01 22:34:59 -05:00
David Sangrey 6192803d61 Add VERSION check 2025-12-25 17:18:15 -05:00
David Sangrey beb68efae8 [2568] Fix Ships JSON Typo 2025-12-25 01:36:24 -05:00
David Sangrey 6fdf290438 [Fix] Allow Legacy Loading Mechanisms 2025-12-07 15:01:03 -05:00
David Sangrey 2041b3d3d3 [Minor] Update Type Hints and Alias Usages 2025-12-01 22:04:28 -05:00
David Sangrey b63b4b90ca [Minor] Move Linter Warning 2025-12-01 21:54:14 -05:00
Inutt b9f3cf3d6a Fix relative imports in plugins
Allow plugins to use relative imports to avoid conflicts between modules with the same name from another plugin.

Fixes #2345
diff --git a/plug.py b/plug.py
index 1a8779f7..8890c80f 100644
--- a/plug.py
+++ b/plug.py
@@ -48,13 +48,20 @@ last_error = LastError()
 class Plugin:
     """An EDMC plugin."""

-    def __init__(self, name: str, loadfile: Path | None, plugin_logger: logging.Logger | None):  # noqa: CCR001
+    def __init__(
+        self,
+        name: str,
+        loadfile: Path | None,
+        plugin_logger: logging.Logger | None,
+        internal: bool = False
+    ):  # noqa: CCR001
         """
         Load a single plugin.

         :param name: Base name of the file being loaded from.
         :param loadfile: Full path/filename of the plugin.
         :param plugin_logger: The logging instance for this plugin to use.
+        :param internal: True to use internal plugin loader logic. Defaults to False.
         :raises Exception: Typically, ImportError or OSError
         """
         self.name: str = name  # Display name.
@@ -65,14 +72,19 @@ class Plugin:
         if loadfile:
             logger.info(f'loading plugin "{name.replace(".", "_")}" from "{loadfile}"')
             try:
-                filename = 'plugin_'
-                filename += name.encode(encoding='ascii', errors='replace').decode('utf-8').replace('.', '_')
-                spec = importlib.util.spec_from_file_location(filename, loadfile)
-                # Replaces older load_module() code. Includes a safety check that the module name is set.
-                if spec is not None and spec.loader is not None:
-                    module = importlib.util.module_from_spec(spec)
-                    sys.modules[module.__name__] = module
-                    spec.loader.exec_module(module)
+                if internal:
+                    filename = 'plugin_'
+                    filename += name.encode(encoding='ascii', errors='replace').decode('utf-8').replace('.', '_')
+                    spec = importlib.util.spec_from_file_location(filename, loadfile)
+                    # Replaces older load_module() code. Includes a safety check that the module name is set.
+                    if spec is not None and spec.loader is not None:
+                        module = importlib.util.module_from_spec(spec)
+                        sys.modules[module.__name__] = module
+                        spec.loader.exec_module(module)
+                else:
+                    module = importlib.import_module('.load', name)
+
+                if module:
                     if getattr(module, 'plugin_start3', None):
                         newname = module.plugin_start3(Path(loadfile).resolve().parent)
                         self.name = str(newname) if newname else self.name
@@ -170,7 +182,7 @@ def _load_internal_plugins():
             try:
                 plugin_name = name[:-3]
                 plugin_path = config.internal_plugin_dir_path / name
-                plugin = Plugin(plugin_name, plugin_path, logger)
+                plugin = Plugin(plugin_name, plugin_path, logger, internal=True)
                 plugin.folder = None
                 internal.append(plugin)
             except Exception:

diff --git a/plug.py b/plug.py
index 1a8779f7..8890c80f 100644
--- a/plug.py
+++ b/plug.py
@@ -48,13 +48,20 @@ last_error = LastError()
 class Plugin:
     """An EDMC plugin."""

-    def __init__(self, name: str, loadfile: Path | None, plugin_logger: logging.Logger | None):  # noqa: CCR001
+    def __init__(
+        self,
+        name: str,
+        loadfile: Path | None,
+        plugin_logger: logging.Logger | None,
+        internal: bool = False
+    ):  # noqa: CCR001
         """
         Load a single plugin.

         :param name: Base name of the file being loaded from.
         :param loadfile: Full path/filename of the plugin.
         :param plugin_logger: The logging instance for this plugin to use.
+        :param internal: True to use internal plugin loader logic. Defaults to False.
         :raises Exception: Typically, ImportError or OSError
         """
         self.name: str = name  # Display name.
@@ -65,14 +72,19 @@ class Plugin:
         if loadfile:
             logger.info(f'loading plugin "{name.replace(".", "_")}" from "{loadfile}"')
             try:
-                filename = 'plugin_'
-                filename += name.encode(encoding='ascii', errors='replace').decode('utf-8').replace('.', '_')
-                spec = importlib.util.spec_from_file_location(filename, loadfile)
-                # Replaces older load_module() code. Includes a safety check that the module name is set.
-                if spec is not None and spec.loader is not None:
-                    module = importlib.util.module_from_spec(spec)
-                    sys.modules[module.__name__] = module
-                    spec.loader.exec_module(module)
+                if internal:
+                    filename = 'plugin_'
+                    filename += name.encode(encoding='ascii', errors='replace').decode('utf-8').replace('.', '_')
+                    spec = importlib.util.spec_from_file_location(filename, loadfile)
+                    # Replaces older load_module() code. Includes a safety check that the module name is set.
+                    if spec is not None and spec.loader is not None:
+                        module = importlib.util.module_from_spec(spec)
+                        sys.modules[module.__name__] = module
+                        spec.loader.exec_module(module)
+                else:
+                    module = importlib.import_module('.load', name)
+
+                if module:
                     if getattr(module, 'plugin_start3', None):
                         newname = module.plugin_start3(Path(loadfile).resolve().parent)
                         self.name = str(newname) if newname else self.name
@@ -170,7 +182,7 @@ def _load_internal_plugins():
             try:
                 plugin_name = name[:-3]
                 plugin_path = config.internal_plugin_dir_path / name
-                plugin = Plugin(plugin_name, plugin_path, logger)
+                plugin = Plugin(plugin_name, plugin_path, logger, internal=True)
                 plugin.folder = None
                 internal.append(plugin)
             except Exception:
2025-11-24 18:00:58 +00:00
David Sangrey 30da989bc5 [Minor] Update LastError to a Dataclass 2025-11-11 22:16:57 -05:00
David Sangrey 65273742d0 [#1775] Retire Usage of Assert
Removes assert statements from EDMC non-test code, paving the way to enable -OO code.
2025-04-27 21:58:01 -04:00
David Sangrey 4c334835f2 [Minor] Simplify if-else statements 2025-04-11 19:57:18 -04:00
David Sangrey 2c4e409ca3 Merge branch 'main' into develop 2025-04-02 00:01:39 -04:00
David Sangrey 84538c88e9 [Minor] Update Winsparkle Ver, Remove UwU
Also clarifies an import for importlib and fixes a pre-commit hook
2025-04-01 23:27:13 -04:00
Florian Probst 92a752cee0 Update plug.py 2025-02-24 23:31:28 +01:00
David Sangrey f18ead9efa [#1428] Implement Timestamp Checker 2025-02-16 20:49:03 -05:00
David Sangrey f8b7a8b919 [2114] Cleanup Initial Commit
Some of these are already paths.
2024-06-10 17:49:13 -04:00
David Sangrey fe8818d187 [2114] Apply PathLib Handover 2024-06-10 17:21:06 -04:00
David Sangrey d4960efa8c [Lang] Update Translations
Also corrects fleetcarrier to proper Fleet Carrier
2024-06-03 16:44:18 -04:00
David Sangrey 47f36a035c [1462] Remove Useless Comment
Add Slightly More Useful Comment
2024-05-01 11:08:27 -04:00
David Sangrey c48df655d1 [#1462] LoadModule Replacement, Take Two
The previous attempt was almost correct - but we needed to ensure that the system was aware of the module in order to handle it correctly.
2024-04-30 23:16:51 -04:00
David Sangrey d9c7a79155 [Minor] Update Type Hintings
No Content Changes, Shuts Up MyPy
2024-04-06 16:59:49 -04:00
David Sangrey b7633fa6e3 Handover a number of Lists to Tuples
Tuples are (slightly) more efficient for comparing if x in y. Not that it'll really matter at this scale, but it's technically better and simple to implement.

Applying to all files except theme.py, because theme.py is scary.
2023-12-27 00:29:35 -05:00
Phoebe 34d91dfb2d [Enhancement] Broken Plugins Popup
- Adds a Popup at startup about Plugins that failed to load.
- Adds entry about broken Plugins in the Settings - Plugins tab.
- Adds corresponding translation entries.
2023-12-14 01:06:09 +01:00
David Sangrey f30fb56f6e [2051] Re-add missing context
It's not a refactor if I don't accidentally nuke a lang comment
2023-11-30 22:05:59 -05:00
David Sangrey cb2a18025c [2051] First Pass Remaining Files 2023-11-30 21:30:18 -05:00
David Sangrey eedb9b840c #1462 It was, in fact, not that simple. 2023-08-03 22:31:36 -04:00
David Sangrey 0f5be049ed #1462 Suppress MyPy, who is Wrong. 2023-08-03 18:05:39 -04:00
David Sangrey db73b9d775 #2047 Suppress Inaccurate MyPy 2023-08-03 17:33:23 -04:00
David Sangrey 816d041992 #1462 Remove Deprecated load_module() 2023-08-03 16:30:50 -04:00
Athanasius 6b9ec285fd plug.py: Use x if x else y not or , & small type cleanup 2022-12-30 16:43:58 +00:00
Athanasius 74b070ffe9 Merge pull request #1773 from aussig/feature/847/capi-fleetcarrier
Feature/847/capi fleetcarrier
2022-12-30 16:15:37 +00:00
Athanasius 18833c5e36 plugins: Comment *why* the "load plugins that are packages" first is there
It's *NOT* that it will actually load the plugin *as* a package, as the code
explicitly only loads `load.py` still.
2022-12-26 19:48:38 +00:00
aussig 1c39ca5eb9 Merge branch 'develop' into feature/847/capi-fleetcarrier 2022-12-24 10:38:22 +00:00
Athanasius 5d1eb9e3b1 Fix "could be None" conditional for call to plug.notify_journal_entry()
In testing the *first* hit on this does have `monitor.cmdr` set, but neither
`monitor.system` or `monitor.station`.  So:

1. Allow those to be `None` in the function signature,
2. Guard against only `monitor.cmdr` being falsey before the call.
3. Move the `if err:` to the same scope.
2022-12-24 10:11:11 +00:00
aussig 41962663d8 Merge branch 'develop' into feature/847/capi-fleetcarrier 2022-12-24 08:21:18 +00:00
Athanasius 37b054b3d3 Fix type of master passed to plug.load_plugins() 2022-12-23 14:47:27 +00:00
Athanasius 71cbfb8358 plugins/edsm: Lots of type fixing, inc. conditionals where None is possible 2022-12-23 14:47:23 +00:00
Athanasius f4b150960c prefs.py & related files: Fix up mypy type checking
* Some trivial.
* As myNotebook.py's class is based on `ttk.Notebook`, typing changed to
  that.
2022-12-23 14:47:21 +00:00
Athanasius 26b12f5b14 plugins/inara, plug.py: Minor typing fixes 2022-12-23 14:47:18 +00:00
aussig 9e17c46b25 Implement suggestions from PR #1773. 2022-12-22 16:21:42 +00:00
aussig 8e5953408e Handling of /fleetcarrier CAPI endpoint and implementation of plugin callback function 2022-12-21 23:00:35 +00:00
Athanasius b6fe115ea7 CAPI: Add support for plugin cmdr_data_legacy()
* Renames `plug.notify_newdata()` to the more precise `notify_capidata()`.
* If CAPI data was from SERVER_LEGACY, then use plugin `cmdr_data_legacy()`
  instead of `cmdr_data()`.
2022-12-08 11:17:52 +00:00
Athanasius a0c73a5c71 plug.py: flake8 & mypy pass 2022-12-03 14:48:50 +00:00
Athanasius 1f21c7fae4 plug.py: Only type annotation coverage to go in flake8 2022-12-03 14:10:09 +00:00
Athanasius 3247fb805c plug.py: Further docstring fixes 2022-12-03 14:05:59 +00:00
Athanasius 413b2f06f8 plug.py: Some docstrings, change to plugin loading
* Plugin loading: Avoid using .format()
2022-12-03 14:03:47 +00:00
Athanasius c8081f339a plug.py: Use logger.trace_if(...) 2021-08-13 15:14:02 +01:00
norohind c08c1a574e plug.py: reorder notify* functions 2021-08-11 13:55:46 +03:00
norohind ba38b5f02d plug.py: more verbose log message on failed while handling CQC mode journal entry 2021-08-10 16:16:01 +03:00
norohind 7b39b0fda0 plug.py: use copy.deepcopy() instead of dict() in cqc_callback
To create deepcopy for passing data to cqc_callback
2021-08-10 15:55:14 +03:00
norohind 030713f5b9 plug.py: rename journal_entry to cqc_callback in notify_journal_entry_cqc 2021-08-10 13:55:10 +03:00