Repository: pypi/warehouse

Issue:
Disable "view project" links when project has no releases
Currently in the logged-in UI, there are a few places where there are "View" and "View Project" buttons for a maintainer's project, which lead to the project page (e.g. `https://pypi.org/project/<project_name>/`)

However if the project has no releases, the project page will be 404. In this case, we should disable these buttons (via the `disabled` attribute) and add an alt text saying something like "This project has no releases".


Discussion:

Resolving patch:
diff --git a/warehouse/manage/views.py b/warehouse/manage/views.py
--- a/warehouse/manage/views.py
+++ b/warehouse/manage/views.py
@@ -71,7 +71,15 @@ def save_profile(self):
     effective_principals=Authenticated,
 )
 def manage_projects(request):
-    return {}
+
+    def _key(project):
+        if project.releases:
+            return project.releases[0].created
+        return project.created
+
+    return {
+        'projects': sorted(request.user.projects, key=_key, reverse=True)
+    }
 
 
 @view_config(
diff --git a/warehouse/packaging/models.py b/warehouse/packaging/models.py
--- a/warehouse/packaging/models.py
+++ b/warehouse/packaging/models.py
@@ -175,6 +175,16 @@ def documentation_url(self):
 
         return request.route_url("legacy.docs", project=self.name)
 
+    @property
+    def owners(self):
+        return (
+            orm.object_session(self)
+            .query(User)
+            .join(Role.user)
+            .filter(Role.project == self, Role.role_name == 'Owner')
+            .all()
+        )
+
 
 class DependencyKind(enum.IntEnum):
 


Test patch:
diff --git a/tests/unit/manage/test_views.py b/tests/unit/manage/test_views.py
--- a/tests/unit/manage/test_views.py
+++ b/tests/unit/manage/test_views.py
@@ -111,9 +111,33 @@ def test_save_profile_validation_fails(self, monkeypatch):
 class TestManageProjects:
 
     def test_manage_projects(self):
-        request = pretend.stub()
+        project_with_older_release = pretend.stub(
+            releases=[pretend.stub(created=0)]
+        )
+        project_with_newer_release = pretend.stub(
+            releases=[pretend.stub(created=2)]
+        )
+        older_project_with_no_releases = pretend.stub(releases=[], created=1)
+        newer_project_with_no_releases = pretend.stub(releases=[], created=3)
+        request = pretend.stub(
+            user=pretend.stub(
+                projects=[
+                    project_with_older_release,
+                    project_with_newer_release,
+                    newer_project_with_no_releases,
+                    older_project_with_no_releases,
+                ],
+            ),
+        )
 
-        assert views.manage_projects(request) == {}
+        assert views.manage_projects(request) == {
+            'projects': [
+                newer_project_with_no_releases,
+                project_with_newer_release,
+                older_project_with_no_releases,
+                project_with_older_release,
+            ],
+        }
 
 
 class TestManageProjectSettings:
diff --git a/tests/unit/packaging/test_models.py b/tests/unit/packaging/test_models.py
--- a/tests/unit/packaging/test_models.py
+++ b/tests/unit/packaging/test_models.py
@@ -116,6 +116,15 @@ def test_acl(self, db_session):
             (Allow, str(maintainer2.user.id), ["upload"]),
         ]
 
+    def test_owners(self, db_session):
+        project = DBProjectFactory.create()
+        owner1 = DBRoleFactory.create(project=project)
+        owner2 = DBRoleFactory.create(project=project)
+        DBRoleFactory.create(project=project, role_name="Maintainer")
+        DBRoleFactory.create(project=project, role_name="Maintainer")
+
+        assert set(project.owners) == set([owner1.user, owner2.user])
+
 
 class TestRelease: