Repository: pypi/warehouse

Issue:
Update project name on new release if equivalent
Currently a project name is set when the project is created, and cannot be updated.

It should be possible to change the project name to something that will canonicalize to be the same name (e.g. from `CommonMark` to `commonmark`) by uploading a new release with the new name.

---

**Good First Issue**: This issue is good for first time contributors. If you've already contributed to Warehouse, work on [another issue without this label](https://github.com/pypa/warehouse/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aopen+-label%3A%22good+first+issue%22) instead. 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, feel free to ask them here, [`#pypa-dev` on Freenode](https://webchat.freenode.net/?channels=%23pypa-dev), or the [pypa-dev mailing list](https://groups.google.com/forum/#!forum/pypa-dev).

Possible to rename package due to _ vs - ?
I can't find clear info if renaming of projects like `homeassistant_cli` to `homeassistant-cli` is supported/allowed ? 

I tried to update all scripts etc. using _ to - but seems pypi insists on calling it homeassistant_cli because that was what the very first upload by accident had in it.

Can you help rename https://pypi.org/project/homeassistant_cli/ to https://pypi.org/project/homeassistant-cli/ so things are more clean - or is only option to delete the old and create new ? 

Thank you!


Discussion:
Hey @di , can I claim this ticket?
Hi @kwasielew, glad to hear you're working on this. We won't consider an issue "claimed" until there is a PR for it. I don't think anyone else is currently working on this though.
Blocked on #4772.


Resolving patch:
diff --git a/warehouse/forklift/legacy.py b/warehouse/forklift/legacy.py
--- a/warehouse/forklift/legacy.py
+++ b/warehouse/forklift/legacy.py
@@ -922,6 +922,12 @@ def file_upload(request):
             ),
         )
 
+    # Update name if it differs but is still equivalent. We don't need to check if
+    # they are equivalent when normalized because that's already been done when we
+    # queried for the project.
+    if project.name != form.name.data:
+        project.name = form.name.data
+
     # Uploading should prevent broken rendered descriptions.
     # Temporarily disabled, see
     # https://github.com/pypa/warehouse/issues/4079


Test patch:
diff --git a/tests/unit/forklift/test_legacy.py b/tests/unit/forklift/test_legacy.py
--- a/tests/unit/forklift/test_legacy.py
+++ b/tests/unit/forklift/test_legacy.py
@@ -2522,6 +2522,59 @@ def test_upload_fails_with_unsupported_wheel_plat(
             "400 Binary wheel .* has an unsupported " "platform tag .*", resp.status
         )
 
+    def test_upload_updates_existing_project_name(self, pyramid_config, db_request):
+        pyramid_config.testing_securitypolicy(userid=1)
+
+        user = UserFactory.create()
+        EmailFactory.create(user=user)
+        project = ProjectFactory.create(name="Package-Name")
+        RoleFactory.create(user=user, project=project)
+
+        new_project_name = "package-name"
+        filename = "{}-{}.tar.gz".format(new_project_name, "1.1")
+
+        db_request.user = user
+        db_request.remote_addr = "10.10.10.20"
+        db_request.user_agent = "warehouse-tests/6.6.6"
+        db_request.POST = MultiDict(
+            {
+                "metadata_version": "1.1",
+                "name": new_project_name,
+                "version": "1.1",
+                "summary": "This is my summary!",
+                "filetype": "sdist",
+                "md5_digest": "335c476dc930b959dda9ec82bd65ef19",
+                "content": pretend.stub(
+                    filename=filename,
+                    file=io.BytesIO(b"A fake file."),
+                    type="application/tar",
+                ),
+            }
+        )
+
+        storage_service = pretend.stub(store=lambda path, filepath, meta: None)
+        db_request.find_service = lambda svc, name=None: storage_service
+        db_request.remote_addr = "10.10.10.10"
+        db_request.user_agent = "warehouse-tests/6.6.6"
+
+        resp = legacy.file_upload(db_request)
+
+        assert resp.status_code == 200
+
+        # Ensure that a Project object name has been updated.
+        project = (
+            db_request.db.query(Project).filter(Project.name == new_project_name).one()
+        )
+
+        # Ensure that a Release object has been created.
+        release = (
+            db_request.db.query(Release)
+            .filter((Release.project == project) & (Release.version == "1.1"))
+            .one()
+        )
+
+        assert release.uploaded_via == "warehouse-tests/6.6.6"
+
     def test_upload_succeeds_creates_release(self, pyramid_config, db_request):
         pyramid_config.testing_securitypolicy(userid=1)