From 900bbc271d3e4854b54ced1c6007734435906b29 Mon Sep 17 00:00:00 2001
From: Dominik George <nik@naturalnet.de>
Date: Sun, 15 Nov 2020 12:42:16 +0100
Subject: [PATCH] Use setuptools entrypoints to find apps
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

In contrast to scanning the `aleksis.apps` namespace, this has some
benefits:

 1. Does not need to import the module to consider it
    (resolve potential circular imports 🤩)
 2. Does not need to scan filesystems and wheels
 3. Apps can choose their own namespaces, register multiple apps/
    variants, and much more)
---
 aleksis/core/util/core_helpers.py | 16 +++++-----------
 1 file changed, 5 insertions(+), 11 deletions(-)

diff --git a/aleksis/core/util/core_helpers.py b/aleksis/core/util/core_helpers.py
index aeffad13f..b7d3bcd7e 100644
--- a/aleksis/core/util/core_helpers.py
+++ b/aleksis/core/util/core_helpers.py
@@ -1,8 +1,7 @@
 import os
-import pkgutil
 import time
 from datetime import datetime, timedelta
-from importlib import import_module
+from importlib import import_module, metadata
 from itertools import groupby
 from operator import itemgetter
 from typing import Any, Callable, Optional, Sequence, Union
@@ -59,14 +58,8 @@ def dt_show_toolbar(request: HttpRequest) -> bool:
 
 
 def get_app_packages() -> Sequence[str]:
-    """Find all packages within the aleksis.apps namespace."""
-    # Import error are non-fatal here because probably simply no app is installed.
-    try:
-        import aleksis.apps
-    except ImportError:
-        return []
-
-    return [f"aleksis.apps.{pkg[1]}" for pkg in pkgutil.iter_modules(aleksis.apps.__path__)]
+    """Find all registered apps from the setuptools entrypoint."""
+    return [f"{ep.module}.{ep.attr}" for ep in metadata.entry_points()["aleksis.app"]]
 
 
 def merge_app_settings(
@@ -81,7 +74,8 @@ def merge_app_settings(
     Note: Only selected names will be imported frm it to minimise impact of
     potentially malicious apps!
     """
-    for pkg in get_app_packages():
+    for app in get_app_packages():
+        pkg = ".".join(app.split(".")[:-2])
         try:
             mod_settings = import_module(pkg + ".settings")
         except ImportError:
-- 
GitLab