Repository: translate/pootle

Issue:
Paths dropdown missing some parent dirs
if a dir contains only directories, not any active stores its not shown in menu (on master)


Discussion:

Resolving patch:
diff --git a/pootle/core/paths.py b/pootle/core/paths.py
--- a/pootle/core/paths.py
+++ b/pootle/core/paths.py
@@ -6,7 +6,11 @@
 # or later license. See the LICENSE file for a copy of the license and the
 # AUTHORS file for copyright and authorship information.
 
+import pathlib
 import posixpath
+from hashlib import md5
+
+from django.utils.encoding import force_bytes
 
 from pootle.core.decorators import persistent_property
 from pootle.core.delegate import revision
@@ -29,7 +33,7 @@ def rev_cache_key(self):
     def cache_key(self):
         return (
             "%s.%s.%s"
-            % (self.q,
+            % (md5(force_bytes(self.q)).hexdigest(),
                self.rev_cache_key,
                self.show_all))
 
@@ -52,12 +56,17 @@ def paths(self):
             st[1:]
             for st
             in self.stores.values_list("tp_path", flat=True))
-        dirs = set(
-            ("%s/" % posixpath.dirname(path))
-            for path
-            in stores
-            if (path.count("/") > 1
-                and self.q in path))
+        dirs = set()
+        for store in stores:
+            if posixpath.dirname(store) in dirs:
+                continue
+            dirs = (
+                dirs
+                | (set(
+                    "%s/" % str(p)
+                    for p
+                    in pathlib.PosixPath(store).parents
+                    if str(p) != ".")))
         return sorted(
             dirs | stores,
             key=lambda path: (posixpath.dirname(path), posixpath.basename(path)))


Test patch:
diff --git a/tests/core/forms.py b/tests/core/forms.py
--- a/tests/core/forms.py
+++ b/tests/core/forms.py
@@ -6,6 +6,7 @@
 # or later license. See the LICENSE file for a copy of the license and the
 # AUTHORS file for copyright and authorship information.
 
+import pathlib
 import posixpath
 
 import pytest
@@ -294,12 +295,20 @@ class DummyProjectPathsSearchForm(PathsSearchForm):
         for st
         in project_stores.values_list(
             "tp_path", flat=True).order_by())
-    dirs = set(
-        ("%s/" % posixpath.dirname(path))
-        for path
-        in stores
-        if (path.count("/") > 1))
-    paths = sorted(stores | dirs)
+    dirs = set()
+    for store in stores:
+        if posixpath.dirname(store) in dirs:
+            continue
+        dirs = (
+            dirs
+            | (set(
+                "%s/" % str(p)
+                for p
+                in pathlib.PosixPath(store).parents
+                if str(p) != ".")))
+    paths = sorted(
+        stores | dirs,
+        key=lambda path: (posixpath.dirname(path), posixpath.basename(path)))
     assert results["results"] == paths[0:2]
 
     for i in range(0, int(round(len(paths) / 2.0))):
@@ -324,13 +333,21 @@ class DummyProjectPathsSearchForm(PathsSearchForm):
         for st
         in project_stores.filter(tp_path__contains="1").values_list(
             "tp_path", flat=True).order_by())
-    dirs = set(
-        ("%s/" % posixpath.dirname(path))
-        for path
-        in stores
-        if (path.count("/") > 1
-            and "1" in path))
-    paths = sorted(stores | dirs)
+
+    dirs = set()
+    for store in stores:
+        if posixpath.dirname(store) in dirs:
+            continue
+        dirs = (
+            dirs
+            | (set(
+                "%s/" % str(p)
+                for p
+                in pathlib.PosixPath(store).parents
+                if str(p) != ".")))
+    paths = sorted(
+        stores | dirs,
+        key=lambda path: (posixpath.dirname(path), posixpath.basename(path)))
     assert form.is_valid()
     results = form.search()
     assert len(results["results"]) == 2
diff --git a/tests/core/paths.py b/tests/core/paths.py
--- a/tests/core/paths.py
+++ b/tests/core/paths.py
@@ -6,10 +6,14 @@
 # or later license. See the LICENSE file for a copy of the license and the
 # AUTHORS file for copyright and authorship information.
 
+import pathlib
 import posixpath
+from hashlib import md5
 
 import pytest
 
+from django.utils.encoding import force_bytes
+
 from pootle.core.paths import Paths
 from pootle_store.models import Store
 
@@ -36,7 +40,7 @@ def store_qs(self):
     assert (
         paths_util.cache_key
         == ("%s.%s.%s"
-            % (paths_util.q,
+            % (md5(force_bytes(paths_util.q)).hexdigest(),
                paths_util.rev_cache_key,
                paths_util.show_all)))
     assert (
@@ -52,8 +56,22 @@ def store_qs(self):
         for path
         in stores
         if (path.count("/") > 1))
-    assert paths_util.paths == sorted(stores | dirs)
-
+    dirs = set()
+    for store in stores:
+        if posixpath.dirname(store) in dirs:
+            continue
+        dirs = (
+            dirs
+            | (set(
+                "%s/" % str(p)
+                for p
+                in pathlib.PosixPath(store).parents
+                if str(p) != ".")))
+    assert (
+        paths_util.paths
+        == sorted(
+            stores | dirs,
+            key=lambda path: (posixpath.dirname(path), posixpath.basename(path))))
     paths_util = DummyPathsUtil(project0, "1", show_all=True)
     assert (
         Store.objects.exclude(is_template=True).filter(
@@ -61,10 +79,23 @@ def store_qs(self):
         == paths_util.stores.count())
     stores = set(
         st[1:] for st in paths_util.stores.values_list("tp_path", flat=True))
-    dirs = set(
-        ("%s/" % posixpath.dirname(path))
-        for path
-        in stores
-        if (path.count("/") > 1
-            and "1" in path))
-    assert paths_util.paths == sorted(stores | dirs)
+    for store in stores:
+        if posixpath.dirname(store) in dirs:
+            continue
+        dirs = (
+            dirs
+            | (set(
+                "%s/" % str(p)
+                for p
+                in pathlib.PosixPath(store).parents
+                if str(p) != ".")))
+    assert (
+        paths_util.paths
+        == sorted(
+            stores | dirs,
+            key=lambda path: (posixpath.dirname(path), posixpath.basename(path))))
+    assert (
+        paths_util.paths
+        == sorted(
+            stores | dirs,
+            key=lambda path: (posixpath.dirname(path), posixpath.basename(path))))