# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from first import first
from pyramid.httpexceptions import HTTPMovedPermanently, HTTPNotFound
from pyramid.view import view_config
from sqlalchemy.orm.exc import NoResultFound

from warehouse.accounts.models import User
from warehouse.cache.origin import origin_cache
from warehouse.packaging.models import Release, Role


@view_config(
    route_name="packaging.project",
    renderer="packaging/detail.html",
    decorator=[
        origin_cache(
            1 * 24 * 60 * 60,                         # 1 day
            stale_while_revalidate=1 * 24 * 60 * 60,  # 1 day
            stale_if_error=5 * 24 * 60 * 60,          # 5 days
        ),
    ],
)
def project_detail(project, request):
    if project.name != request.matchdict.get("name", project.name):
        return HTTPMovedPermanently(
            request.current_route_path(name=project.name),
        )

    try:
        release = (
            request.db.query(Release)
                      .filter(Release.project == project)
                      .order_by(
                          Release.is_prerelease.nullslast(),
                          Release._pypi_ordering.desc())
                      .limit(1)
                      .one()
        )
    except NoResultFound:
        return HTTPNotFound()

    return release_detail(release, request)


@view_config(
    route_name="packaging.release",
    renderer="packaging/detail.html",
    decorator=[
        origin_cache(
            1 * 24 * 60 * 60,                         # 1 day
            stale_while_revalidate=1 * 24 * 60 * 60,  # 1 day
            stale_if_error=5 * 24 * 60 * 60,          # 5 days
        ),
    ],
)
def release_detail(release, request):
    project = release.project

    if not {project.name, release.version} <= set(request.matchdict.values()):
        return HTTPMovedPermanently(
            request.current_route_path(
                name=project.name, version=release.version,
            ),
        )

    # Get all of the registered versions for this Project, in order of newest
    # to oldest.
    all_releases = (
        request.db.query(Release)
                  .filter(Release.project == project)
                  .with_entities(
                      Release.version,
                      Release.is_prerelease,
                      Release.created)
                  .order_by(Release._pypi_ordering.desc())
                  .all()
    )

    # Get the latest non-prerelease of this Project, or the latest release if
    # all releases are prereleases.
    latest_release = first(
        all_releases,
        key=lambda r: not r.is_prerelease,
        default=all_releases[0],
    )

    # Get all of the maintainers for this project.
    maintainers = [
        r.user
        for r in (
            request.db.query(Role)
            .join(User)
            .filter(Role.project == project)
            .distinct(User.username)
            .order_by(User.username)
            .all()
        )
    ]

    # Get the license from the classifiers or metadata, preferring classifiers.
    license = None
    if release.license:
        # Make a best effort when the entire license text is given
        # by using the first line only.
        license = release.license.split('\n')[0]
    license_classifiers = [c.split(" :: ")[-1] for c in release.classifiers
                           if c.startswith("License")]
    if license_classifiers:
        license = ', '.join(license_classifiers)

    return {
        "project": project,
        "release": release,
        "files": release.files.all(),
        "latest_release": latest_release,
        "all_releases": all_releases,
        "maintainers": maintainers,
        "license": license,
    }


@view_config(
    route_name="includes.edit-project-button",
    renderer="includes/edit-project-button.html",
    uses_session=True,
    permission="manage",
)
def edit_project_button(project, request):
    return {'project': project}

warehouse/packaging/views.py
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from first import first
from pyramid.httpexceptions import HTTPMovedPermanently, HTTPNotFound
from pyramid.view import view_config
from sqlalchemy.orm.exc import NoResultFound

from warehouse.accounts.models import User
from warehouse.cache.origin import origin_cache
from warehouse.packaging.models import Release, Role


@view_config(
    route_name="packaging.project",
    renderer="packaging/detail.html",
    decorator=[
        origin_cache(
            1 * 24 * 60 * 60,                         # 1 day
            stale_while_revalidate=1 * 24 * 60 * 60,  # 1 day
            stale_if_error=5 * 24 * 60 * 60,          # 5 days
        ),
    ],
)
def project_detail(project, request):
    if project.name != request.matchdict.get("name", project.name):
        return HTTPMovedPermanently(
            request.current_route_path(name=project.name),
        )

    try:
        release = (
            request.db.query(Release)
                      .filter(Release.project == project)
                      .order_by(
                          Release.is_prerelease.nullslast(),
                          Release._pypi_ordering.desc())
                      .limit(1)
                      .one()
        )
    except NoResultFound:
        return HTTPNotFound()

    return release_detail(release, request)


@view_config(
    route_name="packaging.release",
    renderer="packaging/detail.html",
    decorator=[
        origin_cache(
            1 * 24 * 60 * 60,                         # 1 day
            stale_while_revalidate=1 * 24 * 60 * 60,  # 1 day
            stale_if_error=5 * 24 * 60 * 60,          # 5 days
        ),
    ],
)
def release_detail(release, request):
    project = release.project

    if not {project.name, release.version} <= set(request.matchdict.values()):
        return HTTPMovedPermanently(
            request.current_route_path(
                name=project.name, version=release.version,
            ),
        )

    # Get all of the registered versions for this Project, in order of newest
    # to oldest.
    all_releases = (
        request.db.query(Release)
                  .filter(Release.project == project)
                  .with_entities(
                      Release.version,
                      Release.is_prerelease,
                      Release.created)
                  .order_by(Release._pypi_ordering.desc())
                  .all()
    )

    # Get the latest non-prerelease of this Project, or the latest release if
    # all releases are prereleases.
    latest_release = first(
        all_releases,
        key=lambda r: not r.is_prerelease,
        default=all_releases[0],
    )

    # Get all of the maintainers for this project.
    maintainers = [
        r.user
        for r in (
            request.db.query(Role)
            .join(User)
            .filter(Role.project == project)
            .distinct(User.username)
            .order_by(User.username)
            .all()
        )
    ]

    # Get the license from the classifiers or metadata, preferring classifiers.
    license = None
    if release.license:
        # Make a best effort when the entire license text is given
        # by using the first line only.
        license = release.license.split('\n')[0]
    license_classifiers = [c.split(" :: ")[-1] for c in release.classifiers
                           if c.startswith("License")]
    if license_classifiers:
        license = ', '.join(license_classifiers)

    return {
        "project": project,
        "release": release,
        "files": release.files.all(),
        "latest_release": latest_release,
        "all_releases": all_releases,
        "maintainers": maintainers,
        "license": license,
    }


@view_config(
    route_name="includes.edit-project-button",
    renderer="includes/manage-project-button.html",
    uses_session=True,
    permission="manage",
)
def edit_project_button(project, request):
    return {'project': project}

warehouse/packaging/views.py
diff --git a/warehouse/packaging/views.py b/warehouse/packaging/views.py
index 5d534e1ae03d..4711e17cbfc7 100644
--- a/warehouse/packaging/views.py
+++ b/warehouse/packaging/views.py
@@ -132,7 +132,7 @@ def release_detail(release, request):
 
 @view_config(
     route_name="includes.edit-project-button",
-    renderer="includes/edit-project-button.html",
+    renderer="includes/manage-project-button.html",
     uses_session=True,
     permission="manage",
 )
diff --git a/warehouse/static/sass/blocks/_package-snippet.scss b/warehouse/static/sass/blocks/_package-snippet.scss
index 7a1607bf9f98..fc0dca22e324 100644
--- a/warehouse/static/sass/blocks/_package-snippet.scss
+++ b/warehouse/static/sass/blocks/_package-snippet.scss
@@ -69,7 +69,7 @@
   }
 
   &__buttons {
-    width: 140px;
+    width: 180px;
 
     .button {
       display: inline-block;
diff --git a/warehouse/templates/includes/edit-project-button.html b/warehouse/templates/includes/manage-project-button.html
similarity index 94%
rename from warehouse/templates/includes/edit-project-button.html
rename to warehouse/templates/includes/manage-project-button.html
index 5ea96acada81..7607e3a1b13f 100644
--- a/warehouse/templates/includes/edit-project-button.html
+++ b/warehouse/templates/includes/manage-project-button.html
@@ -13,5 +13,5 @@
 -#}
 
 {% if request.user %}
-  <a href="{{ request.route_path('manage.project.releases', project_name=project.name) }}" class="button button--primary package-description__edit-button">Edit Project</a>
+  <a href="{{ request.route_path('manage.project.releases', project_name=project.name) }}" class="button button--primary package-description__edit-button">Manage Project</a>
 {% endif %}
diff --git a/warehouse/templates/manage/projects.html b/warehouse/templates/manage/projects.html
index 06b316d6f168..b7960ae0b5cb 100644
--- a/warehouse/templates/manage/projects.html
+++ b/warehouse/templates/manage/projects.html
@@ -46,12 +46,12 @@ <h3 class="package-snippet__title">{{ project.name }}</h3>
             href="{{ request.route_path('manage.project.releases', project_name=project.normalized_name) }}"
             class="button button--primary"
             {% if project.name in projects_owned %}
-            title="Edit this project"
+            title="Manage this project"
             {% else %}
             disabled
             title="You are not an owner of this project"
             {% endif %}
-            >Edit</a>
+            >Manage</a>
           <a
             href="{{ request.route_path('packaging.project', name=project.normalized_name) }}"
             class="button"

Change "Edit" to "Manage" in "Your Projects"
Change the button/link text "Edit" to "Manage" in "Your Projects".

From IRC conversation with @alanbato, @ewdurbin and @nlhkabu .

~~~
<EWDurbin> I think perhaps “Manage” might be a better name for the button that currently says “Edit"
<EWDurbin> Just right off the bat. Since well you can’t really Edit anything, just delete files/releases/projects
<di_codes> ^ agreed
<alanbato> Makes sense to me, Edit misguides people into thinking they can change project attributes imho
<nlh> yep 100% agree
<sumanah> nlh: and I agree with them but I want to hear your thoughts -- you're the one who's done user testing, so do you think people would understand "manage"?
<nlh> i'll open a PR :)
<nlh> yes
<sumanah> thanks nlh!
<nlh> it's also more consistent with the URL structure
~~~

But I do not see a pull request from Nicole yet, so I declare this a:

**Good First Issue**: This issue is good for first time contributors. If there is not a corresponding pull request for this issue, it is up for grabs. For directions for getting set up, see our [Getting Started Guide](https://warehouse.pypa.io/development/getting-started/). If you are working on this issue and have questions, please feel free to ask them here, in [`#pypa-dev` on Freenode](https://webchat.freenode.net/?channels=%23pypa-dev), or on the [pypa-dev mailing list](https://groups.google.com/forum/#!forum/pypa-dev).
Fix for #3118
Fixes #3118.

Updated the projects.html and the relating sass snippet to show **manage** in stead of **edit** when in **Your projects**.
