internlm/SWE-Fixer-Train-110K huggingface dataset:
Repository: pypi/warehouse

Issue:
Add Russian translation
The Russian Translation is at [100% on Weblate](https://hosted.weblate.org/languages/ru/pypa/) so I think it should be added to the localization footer.


Discussion:

Resolving patch:
diff --git a/warehouse/i18n/__init__.py b/warehouse/i18n/__init__.py
--- a/warehouse/i18n/__init__.py
+++ b/warehouse/i18n/__init__.py
@@ -31,6 +31,7 @@
     "el": "Ελληνικά",  # Greek
     "de": "Deutsch",  # German
     "zh_Hans": "简体中文",  # Simplified Chinese
+    "ru": "Русский",  # Russian
 }
 
 LOCALE_ATTR = "_LOCALE_"


Test patch:
Repository: pypi/warehouse

Issue:
Audit 'recovery code' copy against copywriting guidelines
I noticed that some of the text introduced in the new 2fa recovery codes interfaces do not meet the [guidelines](https://warehouse.readthedocs.io/ui-principles/#write-clearly-with-consistent-style-and-terminology), mostly by using `Title Case` instead of `Sentence case`, as recommended.

We need to audit and update strings in:

- Any emails sent about 2FA recovery codes
- The new UIs for generating recovery codes
- The new [help text](https://pypi.org/help/#recoverycodes)

Don't forget to run `make translations` to update the translation files :)

---

**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).

**Screenshot Required**: *If your pull request makes a visual change*, include a screenshot of your update. This helps our team give you feedback faster.



Discussion:

Resolving patch:
diff --git a/warehouse/accounts/forms.py b/warehouse/accounts/forms.py
--- a/warehouse/accounts/forms.py
+++ b/warehouse/accounts/forms.py
@@ -341,7 +341,7 @@ def validate_recovery_code_value(self, field):
         recovery_code_value = field.data.encode("utf-8")
 
         if not self.user_service.check_recovery_code(self.user_id, recovery_code_value):
-            raise wtforms.validators.ValidationError(_("Invalid Recovery Code."))
+            raise wtforms.validators.ValidationError(_("Invalid recovery code."))
 
 
 class RequestPasswordResetForm(forms.Form):


Test patch:
diff --git a/tests/unit/accounts/test_forms.py b/tests/unit/accounts/test_forms.py
--- a/tests/unit/accounts/test_forms.py
+++ b/tests/unit/accounts/test_forms.py
@@ -730,7 +730,7 @@ def test_invalid_recovery_code(self, pyramid_config):
         )
 
         assert not form.validate()
-        assert str(form.recovery_code_value.errors.pop()) == "Invalid Recovery Code."
+        assert str(form.recovery_code_value.errors.pop()) == "Invalid recovery code."
 
     def test_valid_recovery_code(self):
         form = forms.RecoveryCodeAuthenticationForm(
Repository: pypi/warehouse

Issue:
Ordering at /stats is incorrect for TestPyPI
The list at https://test.pypi.org/stats/ is incorrect and lists projects with 0 bytes first:

<img width="736" alt="Screen Shot 2020-07-01 at 10 06 59 AM" src="https://user-images.githubusercontent.com/294415/86260240-a06f1b00-bb82-11ea-8940-4cc7aced95f6.png">

The 0-byte projects should not be included in that list. 

---

**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, in the [`#pypa-dev` chat channel on Freenode](https://webchat.freenode.net/?channels=%23pypa-dev), or on the [distutils-sig.python.org mailing list](https://mail.python.org/mailman3/lists/distutils-sig.python.org/).

**Screenshot Required**: *If your pull request makes a visual change*, include a screenshot of your update. This helps our team give you feedback faster.

Ordering at /stats is incorrect for TestPyPI
The list at https://test.pypi.org/stats/ is incorrect and lists projects with 0 bytes first:

<img width="736" alt="Screen Shot 2020-07-01 at 10 06 59 AM" src="https://user-images.githubusercontent.com/294415/86260240-a06f1b00-bb82-11ea-8940-4cc7aced95f6.png">

The 0-byte projects should not be included in that list. 

---

**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, in the [`#pypa-dev` chat channel on Freenode](https://webchat.freenode.net/?channels=%23pypa-dev), or on the [distutils-sig.python.org mailing list](https://mail.python.org/mailman3/lists/distutils-sig.python.org/).

**Screenshot Required**: *If your pull request makes a visual change*, include a screenshot of your update. This helps our team give you feedback faster.



Discussion:

Resolving patch:
diff --git a/warehouse/views.py b/warehouse/views.py
--- a/warehouse/views.py
+++ b/warehouse/views.py
@@ -399,7 +399,7 @@ def stats(request):
     top_100_packages = (
         request.db.query(Project)
         .with_entities(Project.name, Project.total_size)
-        .order_by(Project.total_size.desc())
+        .order_by(Project.total_size.desc().nullslast())
         .limit(100)
         .all()
     )


Test patch:
Repository: pypi/warehouse

Issue:
/pypi/{package}/{version}/json: yanking an older release updates latest release's yanked_reason field
**Describe the bug**
Yanking an older version of a package leads to unexpected side-effect for latest version's package info provided via the JSON endpoint. In particular, the `yanked_reason` field gets updated.

**Expected behavior**
When yanking a version of a package, no other verision's `yanked_reason` field should be updated.

**To Reproduce**
1. Create new package on test.pypi.org
2. Release version `0.2.0`.
3. Release version `0.3.0`.
4. Yank version `0.2.0`.
5. Check json endpoint of package version `0.3.0`.

```console
$ curl -sL https://test.pypi.org/pypi/abn-test-rss-yank/0.3.0/json | jq '.info.yanked'
false
$ curl -sL https://test.pypi.org/pypi/abn-test-rss-yank/0.3.0/json | jq '.info.yanked_reason'
"Testing Yank"
```

**My Platform**
N/A

**Additional context**
* Test package: https://test.pypi.org/project/abn-test-rss-yank/



Discussion:
This appears to be due to this line:

https://github.com/pypa/warehouse/blob/bd2b3a22f4f84072eb03abb771a88ddab1489e7a/warehouse/legacy/api/json.py#L193

The reference to `r` here is a remnant from this iterator:

https://github.com/pypa/warehouse/blob/bd2b3a22f4f84072eb03abb771a88ddab1489e7a/warehouse/legacy/api/json.py#L129

The fix should be as direct as changing the earlier line to `release.yanked_reason`.


Resolving patch:
diff --git a/warehouse/legacy/api/json.py b/warehouse/legacy/api/json.py
--- a/warehouse/legacy/api/json.py
+++ b/warehouse/legacy/api/json.py
@@ -190,7 +190,7 @@ def json_release(release, request):
             "home_page": release.home_page,
             "download_url": release.download_url,
             "yanked": release.yanked,
-            "yanked_reason": r.yanked_reason or None,
+            "yanked_reason": release.yanked_reason or None,
         },
         "urls": releases[release.version],
         "releases": releases,


Test patch:
Repository: pypi/warehouse

Issue:
Add Traditional Chinese Translation
The Traditional Chinese Translation is at 100% on Weblate so I think it should be added to the localization footer.


Discussion:
For reference, [here's the documentation](https://warehouse.pypa.io/translations.html?#adding-a-newly-completed-translation). Do you want to take care of the PR adding the language? 

The current Weblate PR is https://github.com/pypa/warehouse/pull/9502 and it's already 6000 lines, so you may need someone to merge this first.
Thank you !

I will take care of the PR adding the language.

However, who can merge the current Weblate PR #9502 ?
@di / @ewdurbin :)

Resolving patch:
diff --git a/warehouse/i18n/__init__.py b/warehouse/i18n/__init__.py
--- a/warehouse/i18n/__init__.py
+++ b/warehouse/i18n/__init__.py
@@ -31,6 +31,7 @@
         "el",  # Greek
         "de",  # German
         "zh_Hans",  # Simplified Chinese
+        "zh_Hant",  # Traditional Chinese
         "ru",  # Russian
         "he",  # Hebrew
         "eo",  # Esperanto


Test patch:
Repository: pypi/warehouse

Issue:
Pass the project name to the basic-auth-with-2fa email.
Closes #11859



Discussion:
This will include the project name in the jinja2 context, but won't actually include the project name in the email itself as far as I can tell -- I assume you want it in the email's body.
Oh, yes! I'd forgotten to commit the email templates.
I've included them now: body.html and body.txt

Thank you.

Resolving patch:
diff --git a/warehouse/email/__init__.py b/warehouse/email/__init__.py
--- a/warehouse/email/__init__.py
+++ b/warehouse/email/__init__.py
@@ -305,7 +305,7 @@ def send_token_compromised_email_leak(request, user, *, public_url, origin):
     repeat_window=datetime.timedelta(days=1),
 )
 def send_basic_auth_with_two_factor_email(request, user, *, project_name):
-    return {}
+    return {"project_name": project_name}
 
 
 @_email("account-deleted")


Test patch:
diff --git a/tests/unit/email/test_init.py b/tests/unit/email/test_init.py
--- a/tests/unit/email/test_init.py
+++ b/tests/unit/email/test_init.py
@@ -1299,7 +1299,7 @@ def test_basic_auth_with_2fa_email(
             pyramid_request, stub_user, project_name=project_name
         )
 
-        assert result == {}
+        assert result == {"project_name": project_name}
         assert pyramid_request.task.calls == [pretend.call(send_email)]
         assert send_email.delay.calls == [
             pretend.call(
Repository: pypi/warehouse

Issue:
Restrict the number of pending organization requests per user
When creating an organization, the create page should disappear once the request has been submitted. It should be replaced with a message saying that the user should wait for the admin and for how many days. We should restrict the number of pending requests per user at any given time.

To replicate the issue-

1. Log in
2. Click on 'Your Organizations'
3. Create an organization and submit the request for admin approval

It is possible to create another new account.


![org7](https://user-images.githubusercontent.com/37237726/175110467-6203eb55-d583-4300-906f-63557e768a2a.png)




Discussion:
Priority 3/3 
Limit to a configurable number

Resolving patch:
diff --git a/warehouse/manage/views.py b/warehouse/manage/views.py
--- a/warehouse/manage/views.py
+++ b/warehouse/manage/views.py
@@ -1227,6 +1227,7 @@ def __init__(self, request):
     def default_response(self):
         all_user_organizations = user_organizations(self.request)
 
+        # Get list of invites as (organization, token) tuples.
         organization_invites = (
             self.organization_service.get_organization_invites_by_user(
                 self.request.user.id
@@ -1237,11 +1238,19 @@ def default_response(self):
             for organization_invite in organization_invites
         ]
 
+        # Get list of organizations that are approved (True) or pending (None).
+        organizations = self.organization_service.get_organizations_by_user(
+            self.request.user.id
+        )
+        organizations = [
+            organization
+            for organization in organizations
+            if organization.is_approved is not False
+        ]
+
         return {
             "organization_invites": organization_invites,
-            "organizations": self.organization_service.get_organizations_by_user(
-                self.request.user.id
-            ),
+            "organizations": organizations,
             "organizations_managed": list(
                 organization.name
                 for organization in all_user_organizations["organizations_managed"]


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
@@ -2337,7 +2337,7 @@ def test_default_response(self, monkeypatch):
         )
         monkeypatch.setattr(views, "CreateOrganizationForm", create_organization_cls)
 
-        organization = pretend.stub(name=pretend.stub())
+        organization = pretend.stub(name=pretend.stub(), is_approved=None)
 
         user_organizations = pretend.call_recorder(
             lambda *a, **kw: {
Repository: pypi/warehouse

Issue:
Sorting team names
When teams are created in an organization, the teams are listed in the insert order. Ideally, it should be listed in alpha order or the owner should be able to sort the team names.

To recreate the issue-

- Select an organization
- Click on 'Teams'

The teams in the org will be listed in the order they were created. It is not possible to sort the teams. 
![test5](https://user-images.githubusercontent.com/37237726/183524128-5d4a4a3f-de64-40b9-8490-2e595266fe86.png)




Discussion:

Resolving patch:
diff --git a/warehouse/organizations/models.py b/warehouse/organizations/models.py
--- a/warehouse/organizations/models.py
+++ b/warehouse/organizations/models.py
@@ -255,6 +255,11 @@ class Organization(HasEvents, db.Model):
     users = orm.relationship(
         User, secondary=OrganizationRole.__table__, backref="organizations", viewonly=True  # type: ignore # noqa
     )
+    teams = orm.relationship(
+        "Team",
+        back_populates="organization",
+        order_by=lambda: Team.name.asc(),  # type: ignore
+    )
     projects = orm.relationship(
         "Project", secondary=OrganizationProject.__table__, back_populates="organization", viewonly=True  # type: ignore # noqa
     )
@@ -587,7 +592,7 @@ class Team(HasEvents, db.Model):
         index=True,
     )
 
-    organization = orm.relationship("Organization", lazy=False, backref="teams")
+    organization = orm.relationship("Organization", lazy=False, back_populates="teams")
     members = orm.relationship(
         User, secondary=TeamRole.__table__, backref="teams", viewonly=True  # type: ignore # noqa
     )


Test patch:
Repository: pypi/warehouse

Issue:
Present org info to Owner
When an Owner clicks on an organization, the page should show the number of members, teams and projects in the org. Right now the page shows People in the org which is second on the list.

To recreate the issue-
- Log in
- Click on 'Your Organizations'
- Select an organization
![test7](https://user-images.githubusercontent.com/37237726/183528925-f600a128-cb6f-40f0-bf5a-948d8b625fea.png)

The landing page could show the the number of members, teams and projects in the org. 



Discussion:

Resolving patch:
diff --git a/warehouse/organizations/models.py b/warehouse/organizations/models.py
--- a/warehouse/organizations/models.py
+++ b/warehouse/organizations/models.py
@@ -540,8 +540,15 @@ class TeamProjectRole(db.Model):
         nullable=False,
     )
 
-    project = orm.relationship("Project", lazy=False)
-    team = orm.relationship("Team", lazy=False)
+    project = orm.relationship(
+        "Project",
+        lazy=False,
+        back_populates="team_project_roles",
+    )
+    team = orm.relationship(
+        "Team",
+        lazy=False,
+    )
 
 
 class TeamFactory:
diff --git a/warehouse/packaging/models.py b/warehouse/packaging/models.py
--- a/warehouse/packaging/models.py
+++ b/warehouse/packaging/models.py
@@ -201,7 +201,16 @@ class Project(SitemapMixin, TwoFactorRequireable, HasEvents, db.Model):
         uselist=False,
         viewonly=True,
     )
-    roles = orm.relationship(Role, back_populates="project", passive_deletes=True)
+    roles = orm.relationship(
+        Role,
+        back_populates="project",
+        passive_deletes=True,
+    )
+    team_project_roles = orm.relationship(
+        TeamProjectRole,
+        back_populates="project",
+        passive_deletes=True,
+    )
     users = orm.relationship(User, secondary=Role.__table__, backref="projects", viewonly=True)  # type: ignore # noqa
     releases = orm.relationship(
         "Release",


Test patch:
Repository: pypi/warehouse

Issue:
Updating the organization account name triggers an error
When the organization account name is updated, the update triggers an SQLAlchemy error. 

To recreate the error-

- Click on 'Your organizations'
- Click on 'Manage' for a specific organization
- Click on 'Settings'
- Scroll to the bottom of the page and click on 'Change organization account name'
- Enter the New organization account name and Current organization account name
- Click on 'Change organization account name'

If the new name that is chosen was used previously, it leads to the error shown below. Essentially, we cannot revert to a previous org account name.


<img width="1429" alt="org_name_error" src="https://user-images.githubusercontent.com/37237726/197764693-a2244868-5d46-4a82-9be9-354ae4754012.png">



Discussion:
Can the name be changed to an account name that is not used currently? Should we limit the number of times an org account name can be changed?
I'm able to reproduce this error in a couple of ways:

1) By changing only the capitalization of an organization, e.g. `psf` -> `PSF`
2) By trying to change the organization name back to a previous one, e.g. `psf` -> `pyfound` -> `psf`

For 1), I think this is a case where the normalization of the name for the catalog comes into play, so it's a matter of checking that before writing the catalog entry.

For 2), Since the catalog tracks what `organization_id` held a given name, we should allow reclaiming of previous names.

On a broader note, It may make sense for us to use the catalog as a means of determining how many normalized names a given organization has used and limit the number of renames allowed before needing to request support. Otherwise once an organization is approved, they could "hop scotch" through a bunch of names to block them from use them without admin intervention. This is probably best addressed in a separate issue.

Resolving patch:
diff --git a/warehouse/organizations/services.py b/warehouse/organizations/services.py
--- a/warehouse/organizations/services.py
+++ b/warehouse/organizations/services.py
@@ -135,8 +135,19 @@ def add_catalog_entry(self, organization_id):
             organization_id=organization.id,
         )
 
-        self.db.add(catalog_entry)
-        self.db.flush()
+        try:
+            # Check if this organization name has already been used
+            catalog_entry = (
+                self.db.query(OrganizationNameCatalog)
+                .filter(
+                    OrganizationNameCatalog.normalized_name
+                    == organization.normalized_name,
+                )
+                .one()
+            )
+        except NoResultFound:
+            self.db.add(catalog_entry)
+            self.db.flush()
 
         return catalog_entry
 


Test patch:
Repository: pypi/warehouse

Issue:
Doom transaction if `request.user` is None
Fixes #12422.


Discussion:
This still raises a `RecursionError: maximum recursion depth exceeded while calling a Python object` when logged in and `RuntimeError: Cannot use request.session in a view without uses_session=True.` when unauth'd.
@ewdurbin Try this again, if it works I'll add the necessary tests.

Resolving patch:
diff --git a/warehouse/db.py b/warehouse/db.py
--- a/warehouse/db.py
+++ b/warehouse/db.py
@@ -152,7 +152,7 @@ def cleanup(request):
     from warehouse.admin.flags import AdminFlag, AdminFlagValue
 
     flag = session.query(AdminFlag).get(AdminFlagValue.READ_ONLY.value)
-    if flag and flag.enabled and not request.user.is_superuser:
+    if flag and flag.enabled:
         request.tm.doom()
 
     # Return our session now that it's created and registered


Test patch:
diff --git a/tests/unit/test_db.py b/tests/unit/test_db.py
--- a/tests/unit/test_db.py
+++ b/tests/unit/test_db.py
@@ -164,7 +164,11 @@ def test_create_session(monkeypatch, pyramid_services):
         (None, False, []),
         (pretend.stub(enabled=False), True, []),
         (pretend.stub(enabled=False), False, []),
-        (pretend.stub(enabled=True, description="flag description"), True, []),
+        (
+            pretend.stub(enabled=True, description="flag description"),
+            True,
+            [pretend.call()],
+        ),
         (
             pretend.stub(enabled=True, description="flag description"),
             False,
Repository: pypi/warehouse

Issue:
Banner shows the wrong message when removing a collaborator in an organization
When removing a collaborator from a project in an organization, the banner says 'Removed role'.

To recreate the error-

- Click on Your organizations
- Click on Manage for a specific organization
- Click on Projects
- Click on Manage for a specific project
- Click on Collaborators
- Click on Remove for a specific collaborator
- Enter the team name or username of the collaborator
- Click on Remove

The banner should say 'Removed collaborator'. 
![collaborator](https://user-images.githubusercontent.com/37237726/197766560-ca6d2200-185b-4905-90b5-e9b0cdaeb6e6.png)




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
@@ -4667,7 +4667,7 @@ def delete_project_role(project, request):
                 request, role.user, submitter=request.user, project_name=project.name
             )
 
-            request.session.flash("Removed role", queue="success")
+            request.session.flash("Removed collaborator", queue="success")
             if removing_self:
                 return HTTPSeeOther(request.route_path("manage.projects"))
     except NoResultFound:


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
@@ -8860,7 +8860,7 @@ def test_delete_role(self, db_request, monkeypatch):
             pretend.call(db_request, user, submitter=user_2, project_name="foobar")
         ]
         assert db_request.session.flash.calls == [
-            pretend.call("Removed role", queue="success")
+            pretend.call("Removed collaborator", queue="success")
         ]
         assert isinstance(result, HTTPSeeOther)
         assert result.headers["Location"] == "/the-redirect"
@@ -8956,7 +8956,7 @@ def test_delete_not_sole_owner_role(self, db_request, monkeypatch):
             pretend.call(db_request, user_2, submitter=user_2, project_name="foobar")
         ]
         assert db_request.session.flash.calls == [
-            pretend.call("Removed role", queue="success")
+            pretend.call("Removed collaborator", queue="success")
         ]
         assert isinstance(result, HTTPSeeOther)
         assert result.headers["Location"] == "/the-redirect"