diff --git a/tests/unit/forklift/test_forms.py b/tests/unit/forklift/test_forms.py index 0ab337baeeda..4064bb00b1f5 100644 --- a/tests/unit/forklift/test_forms.py +++ b/tests/unit/forklift/test_forms.py @@ -10,45 +10,54 @@ # See the License for the specific language governing permissions and # limitations under the License. +import hashlib import pytest from webob.multidict import MultiDict -from wtforms.validators import ValidationError from warehouse.forklift.forms import UploadForm class TestUploadForm: + _sha256 = hashlib.sha256().hexdigest() + _blake2b = hashlib.blake2b(digest_size=32).hexdigest() + @pytest.mark.parametrize( "data", [ # Test for singular supported digests {"filetype": "sdist", "md5_digest": "bad"}, {"filetype": "bdist_wheel", "pyversion": "3.4", "md5_digest": "bad"}, - {"filetype": "sdist", "sha256_digest": "bad"}, - {"filetype": "bdist_wheel", "pyversion": "3.4", "sha256_digest": "bad"}, - {"filetype": "sdist", "blake2_256_digest": "bad"}, - {"filetype": "bdist_wheel", "pyversion": "3.4", "blake2_256_digest": "bad"}, + {"filetype": "sdist", "sha256_digest": _sha256}, + {"filetype": "bdist_wheel", "pyversion": "3.4", "sha256_digest": _sha256}, + {"filetype": "sdist", "blake2_256_digest": _blake2b}, + { + "filetype": "bdist_wheel", + "pyversion": "3.4", + "blake2_256_digest": _blake2b, + }, # Tests for multiple digests passing through { "filetype": "sdist", "md5_digest": "bad", - "sha256_digest": "bad", - "blake2_256_digest": "bad", + "sha256_digest": _sha256, + "blake2_256_digest": _blake2b, }, { "filetype": "bdist_wheel", "pyversion": "3.4", "md5_digest": "bad", - "sha256_digest": "bad", - "blake2_256_digest": "bad", + "sha256_digest": _sha256, + "blake2_256_digest": _blake2b, }, ], ) def test_full_validate_valid(self, data): + # `name` is required for any submission + data["name"] = "fake-package" form = UploadForm(MultiDict(data)) - form.full_validate() + assert form.validate(), form.errors @pytest.mark.parametrize( "data", @@ -59,6 +68,6 @@ def test_full_validate_valid(self, data): ], ) def test_full_validate_invalid(self, data): + data["name"] = "fake-package" form = UploadForm(MultiDict(data)) - with pytest.raises(ValidationError): - form.full_validate() + assert not form.validate() diff --git a/tests/unit/forklift/test_legacy.py b/tests/unit/forklift/test_legacy.py index 13f2921a19a8..38b91c21b966 100644 --- a/tests/unit/forklift/test_legacy.py +++ b/tests/unit/forklift/test_legacy.py @@ -591,8 +591,10 @@ def test_fails_invalid_version(self, pyramid_config, pyramid_request, version): "metadata_version": "1.2", "name": "example", "version": "1.0", - "filetype": "bdist_wat", + "filetype": "bdist_wheel", + "content": "fake binary content", }, + "Invalid value for pyversion. " "Error: Python version is required for binary distribution uploads.", ), ( @@ -614,6 +616,7 @@ def test_fails_invalid_version(self, pyramid_config, pyramid_request, version): "filetype": "sdist", "pyversion": "1.0", }, + "Invalid value for pyversion. " "Error: Use 'source' as Python version for an sdist.", ), # digest errors. @@ -623,6 +626,7 @@ def test_fails_invalid_version(self, pyramid_config, pyramid_request, version): "name": "example", "version": "1.0", "filetype": "sdist", + "content": "fake binary content", }, "Error: Include at least one message digest.", ), diff --git a/tests/unit/manage/test_forms.py b/tests/unit/manage/test_forms.py index 062d82fc8cf7..619f44cd4c21 100644 --- a/tests/unit/manage/test_forms.py +++ b/tests/unit/manage/test_forms.py @@ -899,14 +899,12 @@ def test_validate_name_with_fewer_than_max_applications(self, db_session): form.validate__max_apps(pretend.stub()) - assert form.errors == { - "__all__": [ - ( - "You have already submitted the maximum number of " - "Organization requests (3)." - ) - ] - } + assert form.form_errors == [ + ( + "You have already submitted the maximum number of " + "Organization requests (3)." + ) + ] assert organization_service.get_organization_applications_by_name.calls == [] assert organization_service.find_organizationid.calls == [] diff --git a/tests/unit/test_forms.py b/tests/unit/test_forms.py index 65cbb88b5c02..9db99ddd7dd1 100644 --- a/tests/unit/test_forms.py +++ b/tests/unit/test_forms.py @@ -14,9 +14,9 @@ import pytest from webob.multidict import MultiDict -from wtforms.validators import StopValidation, ValidationError +from wtforms.validators import ValidationError -from warehouse.forms import Form, PasswordStrengthValidator, SetLocaleForm, URIValidator +from warehouse.forms import PasswordStrengthValidator, SetLocaleForm, URIValidator class TestURIValidator: @@ -83,116 +83,6 @@ def test_invalid_password(self, password, expected): assert str(exc.value) == expected -def _raiser(exc): - raise exc - - -class TestForm: - def test_empty_form_no_errors(self): - form = Form() - assert form.errors == {} - - def test_errors_is_not_cached(self): - # Changed in wtforms==2.3.0 (https://github.com/wtforms/wtforms/pull/568) - form = Form() - assert form.errors == {} - form._form_errors.append("An Error") - assert form.errors == {"__all__": ["An Error"]} - - def test_form_level_validation_no_validators(self): - class TestForm(Form): - pass - - form = TestForm() - - assert form.validate() - assert form.errors == {} - - def test_form_level_validation_full_validate(self): - class TestForm(Form): - @pretend.call_recorder - def full_validate(self): - pass - - form = TestForm() - - assert form.validate() - assert form.errors == {} - assert form.full_validate.calls == [pretend.call(form)] - - def test_form_level_validation_full_validate_fails(self): - class TestForm(Form): - @pretend.call_recorder - def full_validate(self): - raise ValueError("A Value Error") - - form = TestForm() - - assert not form.validate() - assert form.errors == {"__all__": ["A Value Error"]} - assert form.full_validate.calls == [pretend.call(form)] - - @pytest.mark.parametrize("validator_funcs", [[], [lambda f: None]]) - def test_form_level_validation_meta_works(self, validator_funcs): - validator_funcs = [pretend.call_recorder(v) for v in validator_funcs] - - class TestForm(Form): - class Meta: - validators = validator_funcs - - form = TestForm() - - assert form.validate() - assert form.errors == {} - for v in validator_funcs: - assert v.calls == [pretend.call(form)] - - @pytest.mark.parametrize( - ("validator_funcs", "errors", "stop_after"), - [ - ( - [ - lambda f: _raiser(ValueError("An Error")), - lambda f: None, - lambda f: _raiser(ValueError("Another Error")), - lambda f: _raiser(StopValidation("Stop!")), - lambda f: _raiser(ValueError("This Won't Show.")), - ], - ["An Error", "Another Error", "Stop!"], - 3, - ), - ( - [ - lambda f: _raiser(ValueError("An Error")), - lambda f: None, - lambda f: _raiser(ValueError("Another Error")), - lambda f: _raiser(StopValidation), - lambda f: _raiser(ValueError("This Won't Show.")), - ], - ["An Error", "Another Error"], - 3, - ), - ], - ) - def test_form_level_validation_meta_fails( - self, validator_funcs, errors, stop_after - ): - validator_funcs = [pretend.call_recorder(v) for v in validator_funcs] - - class TestForm(Form): - class Meta: - validators = validator_funcs - - form = TestForm() - - assert not form.validate() - assert form.errors == {"__all__": errors} - for i, v in enumerate(validator_funcs): - assert v.calls == [pretend.call(form)] - if i >= stop_after: - break - - class TestSetLocaleForm: def test_validate(self): form = SetLocaleForm(MultiDict({"locale_id": "es"})) diff --git a/warehouse/accounts/forms.py b/warehouse/accounts/forms.py index 840dc81e193b..eefe8cbc679c 100644 --- a/warehouse/accounts/forms.py +++ b/warehouse/accounts/forms.py @@ -385,7 +385,7 @@ class HoneypotMixin: confirm_form = wtforms.StringField() -class UsernameSearchForm(forms.Form): +class UsernameSearchForm(wtforms.Form): username = wtforms.StringField( validators=[ wtforms.validators.InputRequired(), @@ -401,7 +401,7 @@ class RegistrationForm( # type: ignore[misc] NewEmailMixin, NewPasswordMixin, HoneypotMixin, - forms.Form, + wtforms.Form, ): full_name = wtforms.StringField( validators=[ @@ -439,7 +439,7 @@ def validate_g_recaptcha_response(self, field): raise wtforms.validators.ValidationError("Recaptcha error.") -class LoginForm(PasswordMixin, UsernameMixin, forms.Form): +class LoginForm(PasswordMixin, UsernameMixin, wtforms.Form): def __init__(self, *args, user_service, breach_service, **kwargs): super().__init__(*args, **kwargs) self.user_service = user_service @@ -480,7 +480,7 @@ def validate_password(self, field): ) -class _TwoFactorAuthenticationForm(forms.Form): +class _TwoFactorAuthenticationForm(wtforms.Form): def __init__(self, *args, request, user_id, user_service, **kwargs): super().__init__(*args, **kwargs) self.request = request @@ -544,7 +544,7 @@ def validate_credential(self, field): self.validated_credential = validated_credential -class ReAuthenticateForm(PasswordMixin, forms.Form): +class ReAuthenticateForm(PasswordMixin, wtforms.Form): __params__ = [ "username", "password", @@ -602,7 +602,7 @@ def validate_recovery_code_value(self, field): ) -class RequestPasswordResetForm(forms.Form): +class RequestPasswordResetForm(wtforms.Form): username_or_email = wtforms.StringField( validators=[ wtforms.validators.InputRequired(), @@ -632,5 +632,5 @@ def validate_username_or_email(self, field): ) -class ResetPasswordForm(NewPasswordMixin, forms.Form): +class ResetPasswordForm(NewPasswordMixin, wtforms.Form): pass diff --git a/warehouse/admin/templates/admin/banners/edit.html b/warehouse/admin/templates/admin/banners/edit.html index bcb98b4cd996..08654f407ef5 100644 --- a/warehouse/admin/templates/admin/banners/edit.html +++ b/warehouse/admin/templates/admin/banners/edit.html @@ -63,8 +63,8 @@

Create banner

- {% if form.errors.__all__ %} - {% for error in form.errors.__all__ %} + {% if form.form_errors %} + {% for error in form.form_errors %}
{{ error }}
{% endfor %} {% endif %} diff --git a/warehouse/admin/templates/admin/sponsors/edit.html b/warehouse/admin/templates/admin/sponsors/edit.html index 91aa5bf01680..ca0d041bb23d 100644 --- a/warehouse/admin/templates/admin/sponsors/edit.html +++ b/warehouse/admin/templates/admin/sponsors/edit.html @@ -57,8 +57,8 @@

Create sponsor

- {% if form.errors.__all__ %} - {% for error in form.errors.__all__ %} + {% if form.form_errors %} + {% for error in form.form_errors %}
{{ error }}
{% endfor %} {% endif %} diff --git a/warehouse/admin/templates/admin/users/detail.html b/warehouse/admin/templates/admin/users/detail.html index 8c39d1aaacf4..ae738e6618d4 100644 --- a/warehouse/admin/templates/admin/users/detail.html +++ b/warehouse/admin/templates/admin/users/detail.html @@ -435,8 +435,8 @@

Edit User

- {% if form.errors.__all__ %} - {% for error in form.errors.__all__ %} + {% if form.form_errors %} + {% for error in form.form_errors %}
{{ error }}
{% endfor %} {% endif %} @@ -509,8 +509,8 @@

Emails

- {% if form.errors.__all__ %} - {% for error in form.errors.__all__ %} + {% if form.form_errors %} + {% for error in form.form_errors %}
{{ error }}
{% endfor %} {% endif %} @@ -570,8 +570,8 @@

Add a new email

- {% if add_email_form.errors.__all__ %} - {% for error in add_email_form.errors.__all__ %} + {% if add_email_form.form_errors %} + {% for error in add_email_form.form_errors %}
{{ error }}
{% endfor %} {% endif %} diff --git a/warehouse/admin/views/banners.py b/warehouse/admin/views/banners.py index 4c77af43f7f6..c3428e9b5484 100644 --- a/warehouse/admin/views/banners.py +++ b/warehouse/admin/views/banners.py @@ -18,7 +18,7 @@ from warehouse.authnz import Permissions from warehouse.banners.models import Banner -from warehouse.forms import Form, URIValidator +from warehouse.forms import URIValidator @view_config( @@ -145,7 +145,7 @@ def preview_banner(request): raise HTTPNotFound -class BannerForm(Form): +class BannerForm(wtforms.Form): name = wtforms.fields.StringField( validators=[ wtforms.validators.Length(max=100), diff --git a/warehouse/admin/views/sponsors.py b/warehouse/admin/views/sponsors.py index 414b606f212d..1a78131f3182 100644 --- a/warehouse/admin/views/sponsors.py +++ b/warehouse/admin/views/sponsors.py @@ -23,11 +23,11 @@ from warehouse.admin.interfaces import ISponsorLogoStorage from warehouse.authnz import Permissions -from warehouse.forms import Form, URIValidator +from warehouse.forms import URIValidator from warehouse.sponsors.models import Sponsor -class SponsorForm(Form): +class SponsorForm(wtforms.Form): name = wtforms.fields.StringField( validators=[ wtforms.validators.Length(max=100), diff --git a/warehouse/admin/views/users.py b/warehouse/admin/views/users.py index 108bbcdc98f2..1d495d934eef 100644 --- a/warehouse/admin/views/users.py +++ b/warehouse/admin/views/users.py @@ -26,7 +26,6 @@ from sqlalchemy import or_, select from sqlalchemy.orm import joinedload -from warehouse import forms from warehouse.accounts.interfaces import IEmailBreachedService, IUserService from warehouse.accounts.models import ( DisableReason, @@ -88,7 +87,7 @@ def user_list(request): return {"users": users, "query": q} -class EmailForm(forms.Form): +class EmailForm(wtforms.Form): email = wtforms.fields.EmailField(validators=[wtforms.validators.InputRequired()]) primary = wtforms.fields.BooleanField() verified = wtforms.fields.BooleanField() @@ -96,7 +95,7 @@ class EmailForm(forms.Form): unverify_reason = wtforms.fields.StringField(render_kw={"readonly": True}) -class EmailsForm(forms.Form): +class EmailsForm(wtforms.Form): emails = wtforms.fields.FieldList(wtforms.fields.FormField(EmailForm)) def validate_emails(self, field): @@ -108,7 +107,7 @@ def validate_emails(self, field): ) -class UserForm(forms.Form): +class UserForm(wtforms.Form): name = wtforms.StringField( validators=[wtforms.validators.Optional(), wtforms.validators.Length(max=100)] ) diff --git a/warehouse/forklift/forms.py b/warehouse/forklift/forms.py index b0aa6f733831..a908568917fe 100644 --- a/warehouse/forklift/forms.py +++ b/warehouse/forklift/forms.py @@ -15,7 +15,6 @@ import wtforms import wtforms.validators -from warehouse import forms from warehouse.utils.project import PROJECT_NAME_RE _filetype_extension_mapping = { @@ -31,7 +30,7 @@ # Any additional validations (such as duplicate filenames, etc) should # occur elsewhere so that they can happen after we've authorized the request # to upload for the given project. -class UploadForm(forms.Form): +class UploadForm(wtforms.Form): # The name field is duplicated out of the general metadata handling, to be # part of the upload form as well so that we can use it prior to extracting # the metadata from the uploaded artifact. @@ -87,25 +86,38 @@ class UploadForm(forms.Form): ] ) - def full_validate(self): + def validate(self, _extra_validators=None) -> bool: + """ + Perform validation on combinations of fields. + """ + + # Validate all defined fields first. + success = super().validate() + if not success: + return False + # All non source releases *must* have a pyversion if ( self.filetype.data and self.filetype.data != "sdist" and not self.pyversion.data ): - raise wtforms.validators.ValidationError( + assert isinstance(self.pyversion.errors, list) + self.pyversion.errors.append( "Python version is required for binary distribution uploads." ) + return False # All source releases *must* have a pyversion of "source" if self.filetype.data == "sdist": if not self.pyversion.data: self.pyversion.data = "source" elif self.pyversion.data != "source": - raise wtforms.validators.ValidationError( + assert isinstance(self.pyversion.errors, list) + self.pyversion.errors.append( "Use 'source' as Python version for an sdist." ) + return False # We *must* have at least one digest to verify against. if ( @@ -113,6 +125,7 @@ def full_validate(self): and not self.sha256_digest.data and not self.blake2_256_digest.data ): - raise wtforms.validators.ValidationError( - "Include at least one message digest." - ) + self.form_errors.append("Include at least one message digest.") + return False + + return success diff --git a/warehouse/forms.py b/warehouse/forms.py index b6f791b9eb59..6cb625b2dfda 100644 --- a/warehouse/forms.py +++ b/warehouse/forms.py @@ -11,7 +11,7 @@ # limitations under the License. from wtforms import Form as BaseForm, StringField -from wtforms.validators import InputRequired, StopValidation, ValidationError +from wtforms.validators import InputRequired, ValidationError from zxcvbn import zxcvbn from warehouse.i18n import KNOWN_LOCALES @@ -75,47 +75,7 @@ def __call__(self, form, field): raise ValidationError(msg) -class Form(BaseForm): - def __init__(self, *args, **kwargs): - super().__init__(*args, **kwargs) - self._form_errors = [] - - def validate(self, *args, **kwargs): - success = super().validate(*args, **kwargs) - - # Determine what form level validators we have to run. - form_validators = getattr(self.meta, "validators", []) - full_validate = getattr(self, "full_validate", None) - if full_validate is not None: - form_validators.append(full_validate.__func__) - - # Attempt run any form level validators now. - self._form_errors = [] - for validator in form_validators: - try: - validator(self) - except StopValidation as exc: - success = False - if exc.args and exc.args[0]: - self._form_errors.append(exc.args[0]) - break - except ValueError as exc: - success = False - self._form_errors.append(exc.args[0]) - - return success - - @property - def errors(self): - errors = super().errors - - if self._form_errors: - errors["__all__"] = self._form_errors - - return errors - - -class SetLocaleForm(Form): +class SetLocaleForm(BaseForm): __params__ = ["locale_id"] locale_id = StringField(validators=[InputRequired(message="Missing locale ID")]) diff --git a/warehouse/locale/messages.pot b/warehouse/locale/messages.pot index ef49b8ed89c2..5b1ff832fa8f 100644 --- a/warehouse/locale/messages.pot +++ b/warehouse/locale/messages.pot @@ -91,7 +91,7 @@ msgid "" msgstr "" #: warehouse/accounts/forms.py:410 warehouse/manage/forms.py:139 -#: warehouse/manage/forms.py:728 +#: warehouse/manage/forms.py:730 msgid "The name is too long. Choose a name with 100 characters or less." msgstr "" @@ -373,8 +373,8 @@ msgstr "" msgid "Select project" msgstr "" -#: warehouse/manage/forms.py:495 warehouse/oidc/forms/_core.py:23 -#: warehouse/oidc/forms/gitlab.py:44 +#: warehouse/manage/forms.py:495 warehouse/oidc/forms/_core.py:22 +#: warehouse/oidc/forms/gitlab.py:43 msgid "Specify project name" msgstr "" @@ -388,59 +388,59 @@ msgstr "" msgid "This project name has already been used. Choose a different project name." msgstr "" -#: warehouse/manage/forms.py:576 +#: warehouse/manage/forms.py:578 msgid "" "The organization name is too long. Choose a organization name with 100 " "characters or less." msgstr "" -#: warehouse/manage/forms.py:588 +#: warehouse/manage/forms.py:590 msgid "" "The organization URL is too long. Choose a organization URL with 400 " "characters or less." msgstr "" -#: warehouse/manage/forms.py:595 +#: warehouse/manage/forms.py:597 msgid "The organization URL must start with http:// or https://" msgstr "" -#: warehouse/manage/forms.py:606 +#: warehouse/manage/forms.py:608 msgid "" "The organization description is too long. Choose a organization " "description with 400 characters or less." msgstr "" -#: warehouse/manage/forms.py:641 +#: warehouse/manage/forms.py:643 msgid "You have already submitted the maximum number of " msgstr "" -#: warehouse/manage/forms.py:671 +#: warehouse/manage/forms.py:673 msgid "Choose a team name with 50 characters or less." msgstr "" -#: warehouse/manage/forms.py:677 +#: warehouse/manage/forms.py:679 msgid "" "The team name is invalid. Team names cannot start or end with a space, " "period, underscore, hyphen, or slash. Choose a different team name." msgstr "" -#: warehouse/manage/forms.py:705 +#: warehouse/manage/forms.py:707 msgid "This team name has already been used. Choose a different team name." msgstr "" -#: warehouse/manage/forms.py:724 +#: warehouse/manage/forms.py:726 msgid "Specify your alternate repository name" msgstr "" -#: warehouse/manage/forms.py:738 +#: warehouse/manage/forms.py:740 msgid "Specify your alternate repository URL" msgstr "" -#: warehouse/manage/forms.py:742 +#: warehouse/manage/forms.py:744 msgid "The URL is too long. Choose a URL with 400 characters or less." msgstr "" -#: warehouse/manage/forms.py:756 +#: warehouse/manage/forms.py:758 msgid "" "The description is too long. Choose a description with 400 characters or " "less." @@ -624,136 +624,136 @@ msgstr "" msgid "Expired invitation for '${username}' deleted." msgstr "" -#: warehouse/oidc/forms/_core.py:25 warehouse/oidc/forms/gitlab.py:46 +#: warehouse/oidc/forms/_core.py:24 warehouse/oidc/forms/gitlab.py:45 msgid "Invalid project name" msgstr "" -#: warehouse/oidc/forms/_core.py:46 +#: warehouse/oidc/forms/_core.py:45 msgid "" "This project already exists, use the project's publishing settings here to create a Trusted Publisher for it." msgstr "" -#: warehouse/oidc/forms/_core.py:66 +#: warehouse/oidc/forms/_core.py:65 msgid "Specify a publisher ID" msgstr "" -#: warehouse/oidc/forms/_core.py:67 +#: warehouse/oidc/forms/_core.py:66 msgid "Publisher must be specified by ID" msgstr "" -#: warehouse/oidc/forms/activestate.py:48 +#: warehouse/oidc/forms/activestate.py:47 msgid "Double dashes are not allowed in the name" msgstr "" -#: warehouse/oidc/forms/activestate.py:55 +#: warehouse/oidc/forms/activestate.py:54 msgid "Leading or trailing dashes are not allowed in the name" msgstr "" -#: warehouse/oidc/forms/activestate.py:79 -#: warehouse/oidc/forms/activestate.py:92 +#: warehouse/oidc/forms/activestate.py:78 +#: warehouse/oidc/forms/activestate.py:91 msgid "Unexpected error from ActiveState. Try again in a few minutes" msgstr "" -#: warehouse/oidc/forms/activestate.py:87 -#: warehouse/oidc/forms/activestate.py:103 -#: warehouse/oidc/forms/activestate.py:112 +#: warehouse/oidc/forms/activestate.py:86 +#: warehouse/oidc/forms/activestate.py:102 +#: warehouse/oidc/forms/activestate.py:111 msgid "Unexpected error from ActiveState. Try again" msgstr "" -#: warehouse/oidc/forms/activestate.py:122 +#: warehouse/oidc/forms/activestate.py:121 msgid "Specify ActiveState organization name" msgstr "" -#: warehouse/oidc/forms/activestate.py:130 +#: warehouse/oidc/forms/activestate.py:129 msgid "Specify ActiveState project name" msgstr "" -#: warehouse/oidc/forms/activestate.py:134 +#: warehouse/oidc/forms/activestate.py:133 msgid "Invalid ActiveState project name" msgstr "" -#: warehouse/oidc/forms/activestate.py:157 +#: warehouse/oidc/forms/activestate.py:156 msgid "ActiveState organization not found" msgstr "" -#: warehouse/oidc/forms/activestate.py:177 +#: warehouse/oidc/forms/activestate.py:176 msgid "ActiveState actor not found" msgstr "" -#: warehouse/oidc/forms/github.py:33 +#: warehouse/oidc/forms/github.py:32 msgid "Specify GitHub repository owner (username or organization)" msgstr "" -#: warehouse/oidc/forms/github.py:40 +#: warehouse/oidc/forms/github.py:39 msgid "Specify repository name" msgstr "" -#: warehouse/oidc/forms/github.py:42 +#: warehouse/oidc/forms/github.py:41 msgid "Invalid repository name" msgstr "" -#: warehouse/oidc/forms/github.py:49 +#: warehouse/oidc/forms/github.py:48 msgid "Specify workflow filename" msgstr "" -#: warehouse/oidc/forms/github.py:84 +#: warehouse/oidc/forms/github.py:83 msgid "Unknown GitHub user or organization." msgstr "" -#: warehouse/oidc/forms/github.py:94 +#: warehouse/oidc/forms/github.py:93 msgid "GitHub has rate-limited this action. Try again in a few minutes." msgstr "" -#: warehouse/oidc/forms/github.py:104 +#: warehouse/oidc/forms/github.py:103 msgid "Unexpected error from GitHub. Try again." msgstr "" -#: warehouse/oidc/forms/github.py:111 +#: warehouse/oidc/forms/github.py:110 msgid "Unexpected connection error from GitHub. Try again in a few minutes." msgstr "" -#: warehouse/oidc/forms/github.py:121 +#: warehouse/oidc/forms/github.py:120 msgid "Unexpected timeout from GitHub. Try again in a few minutes." msgstr "" -#: warehouse/oidc/forms/github.py:133 +#: warehouse/oidc/forms/github.py:132 msgid "Invalid GitHub user or organization name." msgstr "" -#: warehouse/oidc/forms/github.py:149 +#: warehouse/oidc/forms/github.py:148 msgid "Workflow name must end with .yml or .yaml" msgstr "" -#: warehouse/oidc/forms/github.py:154 +#: warehouse/oidc/forms/github.py:153 msgid "Workflow filename must be a filename only, without directories" msgstr "" -#: warehouse/oidc/forms/gitlab.py:33 +#: warehouse/oidc/forms/gitlab.py:32 msgid "Specify GitLab namespace (username or group/subgroup)" msgstr "" -#: warehouse/oidc/forms/gitlab.py:37 +#: warehouse/oidc/forms/gitlab.py:36 msgid "Invalid GitLab username or group/subgroup name." msgstr "" -#: warehouse/oidc/forms/gitlab.py:54 +#: warehouse/oidc/forms/gitlab.py:53 msgid "Specify top-level pipeline file path" msgstr "" -#: warehouse/oidc/forms/gitlab.py:63 +#: warehouse/oidc/forms/gitlab.py:62 msgid "Invalid environment name" msgstr "" -#: warehouse/oidc/forms/gitlab.py:78 +#: warehouse/oidc/forms/gitlab.py:77 msgid "Top-level pipeline file path must end with .yml or .yaml" msgstr "" -#: warehouse/oidc/forms/gitlab.py:82 +#: warehouse/oidc/forms/gitlab.py:81 msgid "Top-level pipeline file path cannot start or end with /" msgstr "" -#: warehouse/packaging/forms.py:27 +#: warehouse/packaging/forms.py:26 msgid "Provide an Inspector link to specific lines of code." msgstr "" diff --git a/warehouse/manage/forms.py b/warehouse/manage/forms.py index e2588ec576c7..58539de2c435 100644 --- a/warehouse/manage/forms.py +++ b/warehouse/manage/forms.py @@ -67,7 +67,7 @@ def validate_username(self, field): ) -class CreateRoleForm(RoleNameMixin, UsernameMixin, forms.Form): +class CreateRoleForm(RoleNameMixin, UsernameMixin, wtforms.Form): def __init__(self, *args, user_service, **kwargs): super().__init__(*args, **kwargs) self.user_service = user_service @@ -76,7 +76,7 @@ def __init__(self, *args, user_service, **kwargs): class CreateInternalRoleForm( RoleNameMixin, TeamProjectRoleNameMixin, - forms.Form, + wtforms.Form, ): is_team = wtforms.RadioField( "Team or member?", @@ -121,15 +121,15 @@ def __init__(self, *args, team_choices, user_choices, user_service, **kwargs): self.team_project_role_name.validators = [] -class ChangeRoleForm(RoleNameMixin, forms.Form): +class ChangeRoleForm(RoleNameMixin, wtforms.Form): pass -class ChangeTeamProjectRoleForm(TeamProjectRoleNameMixin, forms.Form): +class ChangeTeamProjectRoleForm(TeamProjectRoleNameMixin, wtforms.Form): pass -class SaveAccountForm(forms.Form): +class SaveAccountForm(wtforms.Form): __params__ = ["name", "public_email"] name = wtforms.StringField( @@ -164,7 +164,7 @@ def validate_public_email(self, field): ) -class AddEmailForm(NewEmailMixin, forms.Form): +class AddEmailForm(NewEmailMixin, wtforms.Form): __params__ = ["email"] def __init__(self, *args, user_service, user_id, **kwargs): @@ -173,7 +173,7 @@ def __init__(self, *args, user_service, user_id, **kwargs): self.user_id = user_id -class ChangePasswordForm(PasswordMixin, NewPasswordMixin, forms.Form): +class ChangePasswordForm(PasswordMixin, NewPasswordMixin, wtforms.Form): __params__ = ["password", "new_password", "password_confirm"] def __init__(self, *args, user_service, **kwargs): @@ -181,7 +181,7 @@ def __init__(self, *args, user_service, **kwargs): self.user_service = user_service -class ConfirmPasswordForm(UsernameMixin, PasswordMixin, forms.Form): +class ConfirmPasswordForm(UsernameMixin, PasswordMixin, wtforms.Form): __params__ = ["confirm_password"] def __init__(self, *args, user_service, **kwargs): @@ -194,7 +194,7 @@ class DeleteTOTPForm(ConfirmPasswordForm): pass -class ProvisionTOTPForm(TOTPValueMixin, forms.Form): +class ProvisionTOTPForm(TOTPValueMixin, wtforms.Form): __params__ = ["totp_value"] def __init__(self, *args, totp_secret, **kwargs): @@ -213,7 +213,7 @@ def validate_totp_value(self, field): raise wtforms.validators.ValidationError("Invalid TOTP code. Try again?") -class DeleteWebAuthnForm(forms.Form): +class DeleteWebAuthnForm(wtforms.Form): __params__ = ["confirm_device_name"] label = wtforms.StringField( @@ -239,7 +239,7 @@ def validate_label(self, field): self.webauthn = webauthn -class ProvisionWebAuthnForm(WebAuthnCredentialMixin, forms.Form): +class ProvisionWebAuthnForm(WebAuthnCredentialMixin, wtforms.Form): __params__ = ["label", "credential"] label = wtforms.StringField( @@ -288,7 +288,7 @@ def validate_label(self, field): raise wtforms.validators.ValidationError(f"Label '{label}' already in use") -class CreateMacaroonForm(forms.Form): +class CreateMacaroonForm(wtforms.Form): __params__ = ["description", "token_scope"] def __init__( @@ -361,7 +361,7 @@ def validate_token_scope(self, field): self.validated_scope = {"projects": [scope_value]} -class DeleteMacaroonForm(UsernameMixin, PasswordMixin, forms.Form): +class DeleteMacaroonForm(UsernameMixin, PasswordMixin, wtforms.Form): __params__ = ["confirm_password", "macaroon_id"] macaroon_id = wtforms.StringField( @@ -458,7 +458,7 @@ def validate_name(self, field): ) -class AddOrganizationProjectForm(forms.Form): +class AddOrganizationProjectForm(wtforms.Form): __params__ = ["add_existing_project", "existing_project_name", "new_project_name"] add_existing_project = wtforms.RadioField( @@ -509,7 +509,7 @@ def validate_new_project_name(self, field): ) -class TransferOrganizationProjectForm(forms.Form): +class TransferOrganizationProjectForm(wtforms.Form): __params__ = ["organization"] organization = wtforms.SelectField( @@ -527,7 +527,9 @@ def __init__(self, *args, organization_choices, **kwargs): ] -class CreateOrganizationRoleForm(OrganizationRoleNameMixin, UsernameMixin, forms.Form): +class CreateOrganizationRoleForm( + OrganizationRoleNameMixin, UsernameMixin, wtforms.Form +): def __init__(self, *args, orgtype, organization_service, user_service, **kwargs): super().__init__(*args, **kwargs) if orgtype != OrganizationType.Company: @@ -541,7 +543,7 @@ def __init__(self, *args, orgtype, organization_service, user_service, **kwargs) self.user_service = user_service -class ChangeOrganizationRoleForm(OrganizationRoleNameMixin, forms.Form): +class ChangeOrganizationRoleForm(OrganizationRoleNameMixin, wtforms.Form): def __init__(self, *args, orgtype, **kwargs): super().__init__(*args, **kwargs) if orgtype != OrganizationType.Company: @@ -553,7 +555,7 @@ def __init__(self, *args, orgtype, **kwargs): ] -class SaveOrganizationNameForm(OrganizationNameMixin, forms.Form): +class SaveOrganizationNameForm(OrganizationNameMixin, wtforms.Form): __params__ = ["name"] def __init__( @@ -565,7 +567,7 @@ def __init__( self.user = user -class SaveOrganizationForm(forms.Form): +class SaveOrganizationForm(wtforms.Form): __params__ = ["display_name", "link_url", "description", "orgtype"] display_name = wtforms.StringField( @@ -637,7 +639,7 @@ def validate__max_apps(self, field): self.max_applications is not None and len(self.user.organization_applications) >= self.max_applications ): - self._form_errors.append( + self.form_errors.append( _( "You have already submitted the maximum number of " f"Organization requests ({self.max_applications})." @@ -647,7 +649,7 @@ def validate__max_apps(self, field): return True -class CreateTeamRoleForm(forms.Form): +class CreateTeamRoleForm(wtforms.Form): username = wtforms.SelectField( "Select user", choices=[("", "Select user")], @@ -660,7 +662,7 @@ def __init__(self, *args, user_choices, **kwargs): self.username.choices += [(name, name) for name in sorted(user_choices)] -class SaveTeamForm(forms.Form): +class SaveTeamForm(wtforms.Form): __params__ = ["name"] name = wtforms.StringField( @@ -713,7 +715,7 @@ class CreateTeamForm(SaveTeamForm): __params__ = SaveTeamForm.__params__ -class AddAlternateRepositoryForm(forms.Form): +class AddAlternateRepositoryForm(wtforms.Form): """Form to add an Alternate Repository Location for a Project.""" __params__ = ["display_name", "link_url", "description"] diff --git a/warehouse/oidc/forms/_core.py b/warehouse/oidc/forms/_core.py index c56a29177788..d3c9f29992a2 100644 --- a/warehouse/oidc/forms/_core.py +++ b/warehouse/oidc/forms/_core.py @@ -12,7 +12,6 @@ import markupsafe import wtforms -from warehouse import forms from warehouse.i18n import localize as _ from warehouse.utils.project import PROJECT_NAME_RE @@ -58,7 +57,7 @@ def provider(self) -> str: # pragma: no cover raise NotImplementedError -class DeletePublisherForm(forms.Form): +class DeletePublisherForm(wtforms.Form): __params__ = ["publisher_id"] publisher_id = wtforms.StringField( diff --git a/warehouse/oidc/forms/activestate.py b/warehouse/oidc/forms/activestate.py index 204125d150ee..3d3b387d526a 100644 --- a/warehouse/oidc/forms/activestate.py +++ b/warehouse/oidc/forms/activestate.py @@ -19,7 +19,6 @@ import sentry_sdk import wtforms -from warehouse import forms from warehouse.i18n import localize as _ from warehouse.oidc.forms._core import PendingPublisherMixin @@ -113,7 +112,7 @@ def _activestate_gql_api_call( ) -class ActiveStatePublisherBase(forms.Form): +class ActiveStatePublisherBase(wtforms.Form): __params__ = ["organization", "project", "actor"] organization = wtforms.StringField( diff --git a/warehouse/oidc/forms/github.py b/warehouse/oidc/forms/github.py index 4f4caa71e248..0b545f5c7afa 100644 --- a/warehouse/oidc/forms/github.py +++ b/warehouse/oidc/forms/github.py @@ -16,7 +16,6 @@ import sentry_sdk import wtforms -from warehouse import forms from warehouse.i18n import localize as _ from warehouse.oidc.forms._core import PendingPublisherMixin @@ -24,7 +23,7 @@ _VALID_GITHUB_OWNER = re.compile(r"^[a-zA-Z0-9][a-zA-Z0-9-]*$") -class GitHubPublisherBase(forms.Form): +class GitHubPublisherBase(wtforms.Form): __params__ = ["owner", "repository", "workflow_filename", "environment"] owner = wtforms.StringField( diff --git a/warehouse/oidc/forms/gitlab.py b/warehouse/oidc/forms/gitlab.py index 1afd60c19ceb..b709f641e724 100644 --- a/warehouse/oidc/forms/gitlab.py +++ b/warehouse/oidc/forms/gitlab.py @@ -14,7 +14,6 @@ import wtforms -from warehouse import forms from warehouse.i18n import localize as _ from warehouse.oidc.forms._core import PendingPublisherMixin @@ -24,7 +23,7 @@ _VALID_GITLAB_ENVIRONMENT = re.compile(r"^[a-zA-Z0-9\-_/${} ]+$") -class GitLabPublisherBase(forms.Form): +class GitLabPublisherBase(wtforms.Form): __params__ = ["namespace", "project", "workflow_filepath", "environment"] namespace = wtforms.StringField( diff --git a/warehouse/oidc/forms/google.py b/warehouse/oidc/forms/google.py index 5efa6824f265..f2e59add912d 100644 --- a/warehouse/oidc/forms/google.py +++ b/warehouse/oidc/forms/google.py @@ -12,11 +12,10 @@ import wtforms -from warehouse import forms from warehouse.oidc.forms._core import PendingPublisherMixin -class GooglePublisherBase(forms.Form): +class GooglePublisherBase(wtforms.Form): __params__ = ["email", "sub"] email = wtforms.fields.EmailField( diff --git a/warehouse/packaging/forms.py b/warehouse/packaging/forms.py index cfcb4bd9ae61..dd2a8484673c 100644 --- a/warehouse/packaging/forms.py +++ b/warehouse/packaging/forms.py @@ -12,11 +12,10 @@ import wtforms -from warehouse import forms from warehouse.i18n import localize as _ -class SubmitMalwareObservationForm(forms.Form): +class SubmitMalwareObservationForm(wtforms.Form): """Form to submit details about a Project with Malware""" inspector_link = wtforms.fields.URLField( diff --git a/warehouse/templates/accounts/login.html b/warehouse/templates/accounts/login.html index f3c5f20d3d1f..5e8b167a8e4e 100644 --- a/warehouse/templates/accounts/login.html +++ b/warehouse/templates/accounts/login.html @@ -36,9 +36,9 @@

{% trans title=title %}Log in to {{ title }}{% endtrans % {% endif %} - {% if form.errors.__all__ %} + {% if form.form_errors %} diff --git a/warehouse/templates/accounts/recovery-code.html b/warehouse/templates/accounts/recovery-code.html index a51e07b3ed1a..4e7850428903 100644 --- a/warehouse/templates/accounts/recovery-code.html +++ b/warehouse/templates/accounts/recovery-code.html @@ -27,9 +27,9 @@

{% trans %}Login using recovery codes{% endtrans %}

- {% if form.errors.__all__ %} + {% if form.form_errors %} diff --git a/warehouse/templates/accounts/register.html b/warehouse/templates/accounts/register.html index ca8d54e28134..4431ab585c3d 100644 --- a/warehouse/templates/accounts/register.html +++ b/warehouse/templates/accounts/register.html @@ -51,9 +51,9 @@

{% trans title=title %}Create an account on {{ title }}{% - {% if form.errors.__all__ %} + {% if form.form_errors %} diff --git a/warehouse/templates/accounts/request-password-reset.html b/warehouse/templates/accounts/request-password-reset.html index 38f0875a6d68..80c7cff35ee4 100644 --- a/warehouse/templates/accounts/request-password-reset.html +++ b/warehouse/templates/accounts/request-password-reset.html @@ -26,9 +26,9 @@

{% trans %}Password reset{% endtrans %}

{% trans %}To reset your password, enter your username or email.{% endtrans %}

- {% if form.errors.__all__ %} + {% if form.form_errors %} diff --git a/warehouse/templates/accounts/reset-password.html b/warehouse/templates/accounts/reset-password.html index c537e2961826..5ee16b77bdb2 100644 --- a/warehouse/templates/accounts/reset-password.html +++ b/warehouse/templates/accounts/reset-password.html @@ -24,9 +24,9 @@

{% trans %}Reset your password{% endtrans %}

- {% if form.errors.__all__ %} + {% if form.form_errors %} diff --git a/warehouse/templates/accounts/two-factor.html b/warehouse/templates/accounts/two-factor.html index 2b00364dba09..0f6cc45c0676 100644 --- a/warehouse/templates/accounts/two-factor.html +++ b/warehouse/templates/accounts/two-factor.html @@ -86,9 +86,9 @@

{% trans %}Authenticate with an app{% endtrans %}

- {% if totp_form.errors.__all__ %} + {% if totp_form.form_errors %} diff --git a/warehouse/templates/manage/account/recovery_codes-burn.html b/warehouse/templates/manage/account/recovery_codes-burn.html index 34cf75681659..e2d563335295 100644 --- a/warehouse/templates/manage/account/recovery_codes-burn.html +++ b/warehouse/templates/manage/account/recovery_codes-burn.html @@ -55,9 +55,9 @@

{{ title - {% if form.errors.__all__ %} + {% if form.form_errors %} diff --git a/warehouse/templates/manage/manage_base.html b/warehouse/templates/manage/manage_base.html index e5d0b5ce3d62..9e852bab4316 100644 --- a/warehouse/templates/manage/manage_base.html +++ b/warehouse/templates/manage/manage_base.html @@ -465,9 +465,9 @@

{% endmacro %} {% macro form_errors(form) %} - {% if form.errors.__all__ %} + {% if form.form_errors %} diff --git a/warehouse/templates/re-auth.html b/warehouse/templates/re-auth.html index c9099ce802c2..6265528bf2fe 100644 --- a/warehouse/templates/re-auth.html +++ b/warehouse/templates/re-auth.html @@ -36,9 +36,9 @@

{% trans title=title %}Confirm password to continue{% end {{ form.next_route_query }} {{ form.username }} - {% if form.errors.__all__ %} + {% if form.form_errors %}