From b4c6b2e5ccc735caaab5a438b0e34604534fe302 Mon Sep 17 00:00:00 2001 From: Jack Leightcap Date: Thu, 25 May 2023 16:35:58 -0400 Subject: [PATCH 1/5] DataRequired -> InputRequired Signed-off-by: Jack Leightcap --- tests/unit/accounts/test_forms.py | 156 +++++++++++++----------- tests/unit/admin/views/test_banners.py | 4 +- tests/unit/admin/views/test_sponsors.py | 10 +- tests/unit/manage/test_forms.py | 62 ++++++---- warehouse/accounts/forms.py | 30 ++--- warehouse/accounts/views.py | 7 +- warehouse/admin/views/banners.py | 8 +- warehouse/admin/views/sponsors.py | 4 +- warehouse/admin/views/users.py | 2 +- warehouse/forklift/legacy.py | 8 +- warehouse/forms.py | 4 +- warehouse/manage/forms.py | 32 ++--- warehouse/oidc/forms.py | 10 +- warehouse/views.py | 3 +- 14 files changed, 185 insertions(+), 155 deletions(-) diff --git a/tests/unit/accounts/test_forms.py b/tests/unit/accounts/test_forms.py index 2077264264a3..0ab21038a8d7 100644 --- a/tests/unit/accounts/test_forms.py +++ b/tests/unit/accounts/test_forms.py @@ -17,6 +17,8 @@ import pytest import wtforms +from webob.multidict import MultiDict + from warehouse import recaptcha from warehouse.accounts import forms from warehouse.accounts.interfaces import ( @@ -36,7 +38,9 @@ def test_creation(self): user_service = pretend.stub() breach_service = pretend.stub() form = forms.LoginForm( - request=request, user_service=user_service, breach_service=breach_service + request=request, + user_service=user_service, + breach_service=breach_service, ) assert form.request is request @@ -84,7 +88,7 @@ def test_validate_password_no_user(self): ) breach_service = pretend.stub() form = forms.LoginForm( - data={"username": "my_username"}, + formdata=MultiDict({"username": "my_username"}), request=request, user_service=user_service, breach_service=breach_service, @@ -110,7 +114,7 @@ def test_validate_password_disabled_for_compromised_pw(self, db_session): ) breach_service = pretend.stub(failure_message="Bad Password!") form = forms.LoginForm( - data={"username": "my_username"}, + formdata=MultiDict({"username": "my_username"}), request=request, user_service=user_service, breach_service=breach_service, @@ -141,7 +145,7 @@ def test_validate_password_ok(self): check_password=pretend.call_recorder(lambda pw, tags: False) ) form = forms.LoginForm( - data={"username": "my_username"}, + formdata=MultiDict({"username": "my_username"}), request=request, user_service=user_service, breach_service=breach_service, @@ -183,7 +187,7 @@ def test_validate_password_notok(self, db_session): ) breach_service = pretend.stub() form = forms.LoginForm( - data={"username": "my_username"}, + formdata=MultiDict({"username": "my_username"}), request=request, user_service=user_service, breach_service=breach_service, @@ -225,7 +229,7 @@ def test_validate_password_too_many_failed(self): ) breach_service = pretend.stub() form = forms.LoginForm( - data={"username": "my_username"}, + formdata=MultiDict({"username": "my_username"}), request=request, user_service=user_service, breach_service=breach_service, @@ -267,7 +271,7 @@ def test_password_breached(self, monkeypatch): ) form = forms.LoginForm( - data={"password": "password"}, + MultiDict({"password": "password"}), request=request, user_service=user_service, breach_service=breach_service, @@ -299,7 +303,7 @@ def test_validate_password_ok_ip_banned(self): check_password=pretend.call_recorder(lambda pw, tags: False) ) form = forms.LoginForm( - data={"username": "my_username"}, + formdata=MultiDict({"username": "my_username"}), request=request, user_service=user_service, breach_service=breach_service, @@ -332,7 +336,7 @@ def test_validate_password_notok_ip_banned(self, db_session): ) breach_service = pretend.stub() form = forms.LoginForm( - data={"username": "my_username"}, + formdata=MultiDict({"username": "my_username"}), request=request, user_service=user_service, breach_service=breach_service, @@ -354,7 +358,7 @@ def test_create(self): breach_service = pretend.stub() form = forms.RegistrationForm( - data={}, + formdata=MultiDict(), user_service=user_service, recaptcha_service=recaptcha_service, breach_service=breach_service, @@ -365,7 +369,7 @@ def test_create(self): def test_password_confirm_required_error(self): form = forms.RegistrationForm( - data={"password_confirm": ""}, + formdata=MultiDict({"password_confirm": ""}), user_service=pretend.stub( find_userid_by_email=pretend.call_recorder(lambda _: pretend.stub()) ), @@ -381,7 +385,9 @@ def test_passwords_mismatch_error(self, pyramid_config): find_userid_by_email=pretend.call_recorder(lambda _: pretend.stub()) ) form = forms.RegistrationForm( - data={"new_password": "password", "password_confirm": "mismatch"}, + formdata=MultiDict( + {"new_password": "password", "password_confirm": "mismatch"} + ), user_service=user_service, recaptcha_service=pretend.stub(enabled=True), breach_service=pretend.stub(check_password=lambda pw, tags=None: False), @@ -398,10 +404,12 @@ def test_passwords_match_success(self): find_userid_by_email=pretend.call_recorder(lambda _: pretend.stub()) ) form = forms.RegistrationForm( - data={ - "new_password": "MyStr0ng!shPassword", - "password_confirm": "MyStr0ng!shPassword", - }, + formdata=MultiDict( + { + "new_password": "MyStr0ng!shPassword", + "password_confirm": "MyStr0ng!shPassword", + } + ), user_service=user_service, recaptcha_service=pretend.stub(enabled=True), breach_service=pretend.stub(check_password=lambda pw, tags=None: False), @@ -413,7 +421,7 @@ def test_passwords_match_success(self): def test_email_required_error(self): form = forms.RegistrationForm( - data={"email": ""}, + formdata=MultiDict({"email": ""}), user_service=pretend.stub( find_userid_by_email=pretend.call_recorder(lambda _: pretend.stub()) ), @@ -427,7 +435,7 @@ def test_email_required_error(self): @pytest.mark.parametrize("email", ["bad", "foo]bar@example.com", ""]) def test_invalid_email_error(self, pyramid_config, email): form = forms.RegistrationForm( - data={"email": email}, + formdata=MultiDict({"email": email}), user_service=pretend.stub( find_userid_by_email=pretend.call_recorder(lambda _: None) ), @@ -442,7 +450,7 @@ def test_invalid_email_error(self, pyramid_config, email): def test_exotic_email_success(self): form = forms.RegistrationForm( - data={"email": "foo@n--tree.net"}, + formdata=MultiDict({"email": "foo@n--tree.net"}), user_service=pretend.stub( find_userid_by_email=pretend.call_recorder(lambda _: None) ), @@ -455,7 +463,7 @@ def test_exotic_email_success(self): def test_email_exists_error(self, pyramid_config): form = forms.RegistrationForm( - data={"email": "foo@bar.com"}, + formdata=MultiDict({"email": "foo@bar.com"}), user_service=pretend.stub( find_userid_by_email=pretend.call_recorder(lambda _: pretend.stub()) ), @@ -472,7 +480,7 @@ def test_email_exists_error(self, pyramid_config): def test_prohibited_email_error(self, pyramid_config): form = forms.RegistrationForm( - data={"email": "foo@bearsarefuzzy.com"}, + formdata=MultiDict({"email": "foo@bearsarefuzzy.com"}), user_service=pretend.stub( find_userid_by_email=pretend.call_recorder(lambda _: None) ), @@ -489,7 +497,7 @@ def test_prohibited_email_error(self, pyramid_config): def test_recaptcha_disabled(self): form = forms.RegistrationForm( - data={"g_recpatcha_response": ""}, + formdata=MultiDict({"g_recpatcha_response": ""}), user_service=pretend.stub(), recaptcha_service=pretend.stub( enabled=False, @@ -504,7 +512,7 @@ def test_recaptcha_disabled(self): def test_recaptcha_required_error(self): form = forms.RegistrationForm( - data={"g_recaptcha_response": ""}, + formdata=MultiDict({"g_recaptcha_response": ""}), user_service=pretend.stub(), recaptcha_service=pretend.stub( enabled=True, @@ -517,7 +525,7 @@ def test_recaptcha_required_error(self): def test_recaptcha_error(self): form = forms.RegistrationForm( - data={"g_recaptcha_response": "asd"}, + formdata=MultiDict({"g_recaptcha_response": "asd"}), user_service=pretend.stub(), recaptcha_service=pretend.stub( verify_response=pretend.raiser(recaptcha.RecaptchaError), @@ -530,7 +538,7 @@ def test_recaptcha_error(self): def test_username_exists(self, pyramid_config): form = forms.RegistrationForm( - data={"username": "foo"}, + formdata=MultiDict({"username": "foo"}), user_service=pretend.stub( find_userid=pretend.call_recorder(lambda name: 1), username_is_prohibited=lambda a: False, @@ -550,7 +558,7 @@ def test_username_exists(self, pyramid_config): def test_username_prohibted(self, pyramid_config): form = forms.RegistrationForm( - data={"username": "foo"}, + formdata=MultiDict({"username": "foo"}), user_service=pretend.stub( username_is_prohibited=lambda a: True, ), @@ -570,7 +578,7 @@ def test_username_prohibted(self, pyramid_config): @pytest.mark.parametrize("username", ["_foo", "bar_", "foo^bar"]) def test_username_is_valid(self, username, pyramid_config): form = forms.RegistrationForm( - data={"username": username}, + formdata=MultiDict({"username": username}), user_service=pretend.stub( find_userid=pretend.call_recorder(lambda _: None), username_is_prohibited=lambda a: False, @@ -598,7 +606,7 @@ def test_password_strength(self): ) for pwd, valid in cases: form = forms.RegistrationForm( - data={"new_password": pwd, "password_confirm": pwd}, + formdata=MultiDict({"new_password": pwd, "password_confirm": pwd}), user_service=pretend.stub(), recaptcha_service=pretend.stub( enabled=False, @@ -611,7 +619,7 @@ def test_password_strength(self): def test_password_breached(self): form = forms.RegistrationForm( - data={"new_password": "password"}, + formdata=MultiDict({"new_password": "password"}), user_service=pretend.stub( find_userid=pretend.call_recorder(lambda _: None) ), @@ -635,7 +643,7 @@ def test_password_breached(self): def test_name_too_long(self, pyramid_config): form = forms.RegistrationForm( - data={"full_name": "hello " * 50}, + formdata=MultiDict({"full_name": "hello " * 50}), user_service=pretend.stub( find_userid=pretend.call_recorder(lambda _: None) ), @@ -700,7 +708,7 @@ def test_validate_username_or_email_with_none(self): class TestResetPasswordForm: def test_password_confirm_required_error(self): form = forms.ResetPasswordForm( - data={"password_confirm": ""}, + formdata=MultiDict({"password_confirm": ""}), breach_service=pretend.stub(check_password=lambda pw, tags=None: False), ) @@ -709,13 +717,15 @@ def test_password_confirm_required_error(self): def test_passwords_mismatch_error(self, pyramid_config): form = forms.ResetPasswordForm( - data={ - "new_password": "password", - "password_confirm": "mismatch", - "username": "username", - "full_name": "full_name", - "email": "email", - }, + formdata=MultiDict( + { + "new_password": "password", + "password_confirm": "mismatch", + "username": "username", + "full_name": "full_name", + "email": "email", + } + ), breach_service=pretend.stub(check_password=lambda pw, tags=None: False), ) @@ -731,13 +741,15 @@ def test_passwords_mismatch_error(self, pyramid_config): ) def test_password_strength(self, password, expected): form = forms.ResetPasswordForm( - data={ - "new_password": password, - "password_confirm": password, - "username": "username", - "full_name": "full_name", - "email": "email", - }, + formdata=MultiDict( + { + "new_password": password, + "password_confirm": password, + "username": "username", + "full_name": "full_name", + "email": "email", + } + ), breach_service=pretend.stub(check_password=lambda pw, tags=None: False), ) @@ -745,13 +757,15 @@ def test_password_strength(self, password, expected): def test_passwords_match_success(self): form = forms.ResetPasswordForm( - data={ - "new_password": "MyStr0ng!shPassword", - "password_confirm": "MyStr0ng!shPassword", - "username": "username", - "full_name": "full_name", - "email": "email", - }, + formdata=MultiDict( + { + "new_password": "MyStr0ng!shPassword", + "password_confirm": "MyStr0ng!shPassword", + "username": "username", + "full_name": "full_name", + "email": "email", + } + ), breach_service=pretend.stub(check_password=lambda pw, tags=None: False), ) @@ -759,13 +773,15 @@ def test_passwords_match_success(self): def test_password_breached(self): form = forms.ResetPasswordForm( - data={ - "new_password": "MyStr0ng!shPassword", - "password_confirm": "MyStr0ng!shPassword", - "username": "username", - "full_name": "full_name", - "email": "email", - }, + formdata=MultiDict( + { + "new_password": "MyStr0ng!shPassword", + "password_confirm": "MyStr0ng!shPassword", + "username": "username", + "full_name": "full_name", + "email": "email", + } + ), user_service=pretend.stub( find_userid=pretend.call_recorder(lambda _: None) ), @@ -800,8 +816,8 @@ def test_totp_secret_exists(self, pyramid_config): request = pretend.stub(remote_addr="1.2.3.4") form = forms.TOTPAuthenticationForm( + formdata=MultiDict({"totp_value": ""}), request=request, - data={"totp_value": ""}, user_id=pretend.stub(), user_service=pretend.stub(get_user=get_user), ) @@ -810,7 +826,7 @@ def test_totp_secret_exists(self, pyramid_config): form = forms.TOTPAuthenticationForm( request=request, - data={"totp_value": "not_a_real_value"}, + formdata=MultiDict({"totp_value": "not_a_real_value"}), user_id=pretend.stub(), user_service=pretend.stub( check_totp_value=lambda *a: True, get_user=get_user @@ -821,7 +837,7 @@ def test_totp_secret_exists(self, pyramid_config): form = forms.TOTPAuthenticationForm( request=request, - data={"totp_value": "1 2 3 4 5 6 7"}, + formdata=MultiDict({"totp_value": "1 2 3 4 5 6 7"}), user_id=pretend.stub(), user_service=pretend.stub( check_totp_value=lambda *a: True, get_user=get_user @@ -835,8 +851,8 @@ def test_totp_secret_exists(self, pyramid_config): get_user=get_user, ) form = forms.TOTPAuthenticationForm( + formdata=MultiDict({"totp_value": "123456"}), request=request, - data={"totp_value": "123456"}, user_id=1, user_service=user_service, ) @@ -851,8 +867,8 @@ def test_totp_secret_exists(self, pyramid_config): ] form = forms.TOTPAuthenticationForm( + formdata=MultiDict({"totp_value": "123456"}), request=request, - data={"totp_value": "123456"}, user_id=pretend.stub(), user_service=pretend.stub( check_totp_value=lambda *a: True, get_user=get_user @@ -862,7 +878,7 @@ def test_totp_secret_exists(self, pyramid_config): form = forms.TOTPAuthenticationForm( request=request, - data={"totp_value": " 1 2 3 4 5 6 "}, + formdata=MultiDict({"totp_value": " 1 2 3 4 5 6 "}), user_id=pretend.stub(), user_service=pretend.stub( check_totp_value=lambda *a: True, get_user=get_user @@ -872,7 +888,7 @@ def test_totp_secret_exists(self, pyramid_config): form = forms.TOTPAuthenticationForm( request=request, - data={"totp_value": "123 456"}, + formdata=MultiDict({"totp_value": "123 456"}), user_id=pretend.stub(), user_service=pretend.stub( check_totp_value=lambda *a: True, get_user=get_user @@ -1001,8 +1017,8 @@ def test_creation(self): def test_missing_value(self): request = pretend.stub() form = forms.RecoveryCodeAuthenticationForm( + formdata=MultiDict({"recovery_code_value": ""}), request=request, - data={"recovery_code_value": ""}, user_id=pretend.stub(), user_service=pretend.stub(), ) @@ -1033,8 +1049,8 @@ def test_invalid_recovery_code( get_user=pretend.call_recorder(lambda userid: user), ) form = forms.RecoveryCodeAuthenticationForm( + formdata=MultiDict({"recovery_code_value": "deadbeef00001111"}), request=request, - data={"recovery_code_value": "deadbeef00001111"}, user_id=1, user_service=user_service, ) @@ -1053,8 +1069,8 @@ def test_valid_recovery_code(self, monkeypatch): request = pretend.stub(remote_addr="1.2.3.4") user = pretend.stub(id=pretend.stub(), username="foobar") form = forms.RecoveryCodeAuthenticationForm( + formdata=MultiDict({"recovery_code_value": "deadbeef00001111"}), request=request, - data={"recovery_code_value": "deadbeef00001111"}, user_id=pretend.stub(), user_service=pretend.stub( check_recovery_code=pretend.call_recorder(lambda *a, **kw: True), @@ -1089,7 +1105,7 @@ def test_recovery_code_string_validation( user = pretend.stub(id=pretend.stub(), username="foobar") form = forms.RecoveryCodeAuthenticationForm( request=request, - data={"recovery_code_value": input_string}, + formdata=MultiDict({"recovery_code_value": input_string}), user_id=pretend.stub(), user_service=pretend.stub( check_recovery_code=pretend.call_recorder(lambda *a, **kw: True), diff --git a/tests/unit/admin/views/test_banners.py b/tests/unit/admin/views/test_banners.py index 29e81cbe9335..71d26441929d 100644 --- a/tests/unit/admin/views/test_banners.py +++ b/tests/unit/admin/views/test_banners.py @@ -218,13 +218,13 @@ def test_preview_banner(self, db_request): class TestBannerForm: def test_required_fields(self, banner_data): - form = views.BannerForm(data={}) + form = views.BannerForm(formdata=MultiDict()) assert form.validate() is False assert set(form.errors) == set(banner_data) def test_valid_data(self, banner_data): - form = views.BannerForm(data=banner_data) + form = views.BannerForm(formdata=MultiDict(banner_data)) assert form.validate() is True data = form.data defaults = { diff --git a/tests/unit/admin/views/test_sponsors.py b/tests/unit/admin/views/test_sponsors.py index 4a9fce60b45a..9e1baea092f2 100644 --- a/tests/unit/admin/views/test_sponsors.py +++ b/tests/unit/admin/views/test_sponsors.py @@ -260,29 +260,29 @@ def test_required_fields(self): assert field in form.errors def test_valid_data(self): - form = views.SponsorForm(data=self.data) + form = views.SponsorForm(formdata=MultiDict(self.data)) assert form.validate() is True def test_white_logo_is_required_for_footer_display(self): self.data["footer"] = True # don't validate without logo - form = views.SponsorForm(data=self.data) + form = views.SponsorForm(formdata=MultiDict(self.data)) assert form.validate() is False assert "white_logo" in form.errors self.data["white_logo_url"] = "http://domain.com/white-logo.jpg" - form = views.SponsorForm(data=self.data) + form = views.SponsorForm(formdata=MultiDict(self.data)) assert form.validate() is True def test_white_logo_is_required_for_infra_display(self): self.data["infra_sponsor"] = True # don't validate without logo - form = views.SponsorForm(data=self.data) + form = views.SponsorForm(formdata=MultiDict(self.data)) assert form.validate() is False assert "white_logo" in form.errors self.data["white_logo_url"] = "http://domain.com/white-logo.jpg" - form = views.SponsorForm(data=self.data) + form = views.SponsorForm(formdata=MultiDict(self.data)) assert form.validate() is True diff --git a/tests/unit/manage/test_forms.py b/tests/unit/manage/test_forms.py index d13e071a0ad0..c29a0c6601e4 100644 --- a/tests/unit/manage/test_forms.py +++ b/tests/unit/manage/test_forms.py @@ -57,7 +57,7 @@ def test_validate_username_with_user(self): [ ("", "Select role"), ("invalid", "Not a valid choice."), - (None, "Not a valid choice."), + (None, "Select role"), ], ) def test_validate_role_name_fails(self, value, expected): @@ -81,7 +81,7 @@ def test_creation(self): def test_email_exists_error(self, pyramid_config): user_id = pretend.stub() form = forms.AddEmailForm( - data={"email": "foo@bar.com"}, + formdata=MultiDict({"email": "foo@bar.com"}), user_id=user_id, user_service=pretend.stub(find_userid_by_email=lambda _: user_id), ) @@ -95,7 +95,7 @@ def test_email_exists_error(self, pyramid_config): def test_email_exists_other_account_error(self, pyramid_config): form = forms.AddEmailForm( - data={"email": "foo@bar.com"}, + formdata=MultiDict({"email": "foo@bar.com"}), user_id=pretend.stub(), user_service=pretend.stub(find_userid_by_email=lambda _: pretend.stub()), ) @@ -109,7 +109,7 @@ def test_email_exists_other_account_error(self, pyramid_config): def test_prohibited_email_error(self, pyramid_config): form = forms.AddEmailForm( - data={"email": "foo@bearsarefuzzy.com"}, + formdata=MultiDict({"email": "foo@bearsarefuzzy.com"}), user_service=pretend.stub(find_userid_by_email=lambda _: None), user_id=pretend.stub(), ) @@ -148,7 +148,7 @@ def test_verify_totp_invalid(self, monkeypatch): monkeypatch.setattr(otp, "verify_totp", verify_totp) form = forms.ProvisionTOTPForm( - data={"totp_value": "123456"}, totp_secret=pretend.stub() + formdata=MultiDict({"totp_value": "123456"}), totp_secret=pretend.stub() ) assert not form.validate() assert form.totp_value.errors.pop() == "Invalid TOTP code. Try again?" @@ -158,7 +158,7 @@ def test_verify_totp_valid(self, monkeypatch): monkeypatch.setattr(otp, "verify_totp", verify_totp) form = forms.ProvisionTOTPForm( - data={"totp_value": "123456"}, totp_secret=pretend.stub() + formdata=MultiDict({"totp_value": "123456"}), totp_secret=pretend.stub() ) assert form.validate() @@ -182,10 +182,9 @@ def test_validate_confirm_password(self): ), ) form = forms.DeleteTOTPForm( - username="username", + formdata=MultiDict({"username": "username", "password": "password"}), request=request, user_service=user_service, - password="password", ) assert form.validate() @@ -218,7 +217,7 @@ def test_verify_assertion_invalid_json(self): ) form = forms.ProvisionWebAuthnForm( - data={"credential": "invalid json", "label": "fake label"}, + formdata=MultiDict({"credential": "invalid json", "label": "fake label"}), user_service=user_service, user_id=pretend.stub(), challenge=pretend.stub(), @@ -239,7 +238,7 @@ def test_verify_assertion_invalid(self): get_webauthn_by_label=pretend.call_recorder(lambda *a: None), ) form = forms.ProvisionWebAuthnForm( - data={"credential": "{}", "label": "fake label"}, + formdata=MultiDict({"credential": "{}", "label": "fake label"}), user_service=user_service, user_id=pretend.stub(), challenge=pretend.stub(), @@ -255,7 +254,7 @@ def test_verify_label_missing(self): verify_webauthn_credential=lambda *a, **kw: pretend.stub() ) form = forms.ProvisionWebAuthnForm( - data={"credential": "{}"}, + formdata=MultiDict({"credential": "{}"}), user_service=user_service, user_id=pretend.stub(), challenge=pretend.stub(), @@ -272,7 +271,7 @@ def test_verify_label_already_in_use(self): get_webauthn_by_label=pretend.call_recorder(lambda *a: pretend.stub()), ) form = forms.ProvisionWebAuthnForm( - data={"credential": "{}", "label": "fake label"}, + formdata=MultiDict({"credential": "{}", "label": "fake label"}), user_service=user_service, user_id=pretend.stub(), challenge=pretend.stub(), @@ -290,7 +289,7 @@ def test_creates_validated_credential(self): get_webauthn_by_label=pretend.call_recorder(lambda *a: None), ) form = forms.ProvisionWebAuthnForm( - data={"credential": "{}", "label": "fake label"}, + formdata=MultiDict({"credential": "{}", "label": "fake label"}), user_service=user_service, user_id=pretend.stub(), challenge=pretend.stub(), @@ -323,7 +322,7 @@ def test_validate_label_not_in_use(self): get_webauthn_by_label=pretend.call_recorder(lambda *a: None) ) form = forms.DeleteWebAuthnForm( - data={"label": "fake label"}, + formdata=MultiDict({"label": "fake label"}), user_service=user_service, user_id=pretend.stub(), ) @@ -337,7 +336,7 @@ def test_creates_webauthn_attribute(self): get_webauthn_by_label=pretend.call_recorder(lambda *a: fake_webauthn) ) form = forms.DeleteWebAuthnForm( - data={"label": "fake label"}, + formdata=MultiDict({"label": "fake label"}), user_service=user_service, user_id=pretend.stub(), ) @@ -363,7 +362,7 @@ def test_creation(self): def test_validate_description_missing(self): form = forms.CreateMacaroonForm( - data={"token_scope": "scope:user"}, + formdata=MultiDict({"token_scope": "scope:user"}), user_id=pretend.stub(), macaroon_service=pretend.stub(), project_names=pretend.stub(), @@ -374,7 +373,7 @@ def test_validate_description_missing(self): def test_validate_description_in_use(self): form = forms.CreateMacaroonForm( - data={"description": "dummy", "token_scope": "scope:user"}, + formdata=MultiDict({"description": "dummy", "token_scope": "scope:user"}), user_id=pretend.stub(), macaroon_service=pretend.stub( get_macaroon_by_description=lambda *a: pretend.stub() @@ -387,7 +386,7 @@ def test_validate_description_in_use(self): def test_validate_token_scope_missing(self): form = forms.CreateMacaroonForm( - data={"description": "dummy"}, + formdata=MultiDict({"description": "dummy"}), user_id=pretend.stub(), macaroon_service=pretend.stub(get_macaroon_by_description=lambda *a: None), project_names=pretend.stub(), @@ -398,7 +397,9 @@ def test_validate_token_scope_missing(self): def test_validate_token_scope_unspecified(self): form = forms.CreateMacaroonForm( - data={"description": "dummy", "token_scope": "scope:unspecified"}, + formdata=MultiDict( + {"description": "dummy", "token_scope": "scope:unspecified"} + ), user_id=pretend.stub(), macaroon_service=pretend.stub(get_macaroon_by_description=lambda *a: None), project_names=pretend.stub(), @@ -412,7 +413,7 @@ def test_validate_token_scope_unspecified(self): ) def test_validate_token_scope_invalid_format(self, scope): form = forms.CreateMacaroonForm( - data={"description": "dummy", "token_scope": scope}, + formdata=MultiDict({"description": "dummy", "token_scope": scope}), user_id=pretend.stub(), macaroon_service=pretend.stub(get_macaroon_by_description=lambda *a: None), project_names=pretend.stub(), @@ -423,7 +424,9 @@ def test_validate_token_scope_invalid_format(self, scope): def test_validate_token_scope_invalid_project(self): form = forms.CreateMacaroonForm( - data={"description": "dummy", "token_scope": "scope:project:foo"}, + formdata=MultiDict( + {"description": "dummy", "token_scope": "scope:project:foo"} + ), user_id=pretend.stub(), macaroon_service=pretend.stub(get_macaroon_by_description=lambda *a: None), project_names=["bar"], @@ -434,7 +437,7 @@ def test_validate_token_scope_invalid_project(self): def test_validate_token_scope_valid_user(self): form = forms.CreateMacaroonForm( - data={"description": "dummy", "token_scope": "scope:user"}, + formdata=MultiDict({"description": "dummy", "token_scope": "scope:user"}), user_id=pretend.stub(), macaroon_service=pretend.stub(get_macaroon_by_description=lambda *a: None), project_names=pretend.stub(), @@ -444,7 +447,9 @@ def test_validate_token_scope_valid_user(self): def test_validate_token_scope_valid_project(self): form = forms.CreateMacaroonForm( - data={"description": "dummy", "token_scope": "scope:project:foo"}, + formdata=MultiDict( + {"description": "dummy", "token_scope": "scope:project:foo"} + ), user_id=pretend.stub(), macaroon_service=pretend.stub(get_macaroon_by_description=lambda *a: None), project_names=["foo"], @@ -478,7 +483,7 @@ def test_validate_macaroon_id_invalid(self): remote_addr="1.2.3.4", banned=pretend.stub(by_ip=lambda ip_address: False) ) form = forms.DeleteMacaroonForm( - data={"macaroon_id": pretend.stub(), "password": "password"}, + formdata=MultiDict({"macaroon_id": pretend.stub(), "password": "password"}), request=request, macaroon_service=macaroon_service, user_service=user_service, @@ -499,10 +504,15 @@ def test_validate_macaroon_id(self): remote_addr="1.2.3.4", banned=pretend.stub(by_ip=lambda ip_address: False) ) form = forms.DeleteMacaroonForm( - data={"macaroon_id": pretend.stub(), "password": "password"}, + formdata=MultiDict( + { + "macaroon_id": pretend.stub(), + "username": "username", + "password": "password", + } + ), request=request, macaroon_service=macaroon_service, - username="username", user_service=user_service, ) diff --git a/warehouse/accounts/forms.py b/warehouse/accounts/forms.py index 365e6530ce4f..f2e920dcfcb1 100644 --- a/warehouse/accounts/forms.py +++ b/warehouse/accounts/forms.py @@ -48,7 +48,7 @@ class UsernameMixin: - username = wtforms.StringField(validators=[wtforms.validators.DataRequired()]) + username = wtforms.StringField(validators=[wtforms.validators.InputRequired()]) def validate_username(self, field): userid = self.user_service.find_userid(field.data) @@ -62,7 +62,7 @@ def validate_username(self, field): class TOTPValueMixin: totp_value = wtforms.StringField( validators=[ - wtforms.validators.DataRequired(), + wtforms.validators.InputRequired(), wtforms.validators.Regexp( rf"^ *([0-9] *){{{TOTP_LENGTH}}}$", message=_( @@ -75,13 +75,13 @@ class TOTPValueMixin: class WebAuthnCredentialMixin: - credential = wtforms.StringField(wtforms.validators.DataRequired()) + credential = wtforms.StringField(wtforms.validators.InputRequired()) class RecoveryCodeValueMixin: recovery_code_value = wtforms.StringField( validators=[ - wtforms.validators.DataRequired(), + wtforms.validators.InputRequired(), wtforms.validators.Regexp( rf"^ *([0-9a-f] *){{{2*RECOVERY_CODE_BYTES}}}$", message=_( @@ -96,7 +96,7 @@ class RecoveryCodeValueMixin: class NewUsernameMixin: username = wtforms.StringField( validators=[ - wtforms.validators.DataRequired(), + wtforms.validators.InputRequired(), wtforms.validators.Length( max=50, message=_("Choose a username with 50 characters or less.") ), @@ -131,7 +131,7 @@ def validate_username(self, field): class PasswordMixin: password = wtforms.PasswordField( validators=[ - wtforms.validators.DataRequired(), + wtforms.validators.InputRequired(), wtforms.validators.Length( max=MAX_PASSWORD_SIZE, message=_("Password too long."), @@ -179,7 +179,7 @@ def validate_password(self, field): class NewPasswordMixin: new_password = wtforms.PasswordField( validators=[ - wtforms.validators.DataRequired(), + wtforms.validators.InputRequired(), wtforms.validators.Length( max=MAX_PASSWORD_SIZE, message=_("Password too long."), @@ -192,7 +192,7 @@ class NewPasswordMixin: password_confirm = wtforms.PasswordField( validators=[ - wtforms.validators.DataRequired(), + wtforms.validators.InputRequired(), wtforms.validators.Length( max=MAX_PASSWORD_SIZE, message=_("Password too long."), @@ -207,8 +207,8 @@ class NewPasswordMixin: # PasswordStrengthValidator of the new_password field, to ensure that the # newly set password doesn't contain any of them full_name = wtforms.StringField() # May be empty - username = wtforms.StringField(validators=[wtforms.validators.DataRequired()]) - email = wtforms.StringField(validators=[wtforms.validators.DataRequired()]) + username = wtforms.StringField(validators=[wtforms.validators.InputRequired()]) + email = wtforms.StringField(validators=[wtforms.validators.InputRequired()]) def __init__(self, *args, breach_service, **kwargs): super().__init__(*args, **kwargs) @@ -226,7 +226,7 @@ def validate_new_password(self, field): class NewEmailMixin: email = wtforms.fields.EmailField( validators=[ - wtforms.validators.DataRequired(), + wtforms.validators.InputRequired(), wtforms.validators.Regexp( r".+@.+\..+", message=_("The email address isn't valid. Try again.") ), @@ -420,13 +420,13 @@ class ReAuthenticateForm(PasswordMixin, forms.Form): __params__ = ["username", "password", "next_route", "next_route_matchdict"] username = wtforms.fields.HiddenField( - validators=[wtforms.validators.DataRequired()] + validators=[wtforms.validators.InputRequired()] ) next_route = wtforms.fields.HiddenField( - validators=[wtforms.validators.DataRequired()] + validators=[wtforms.validators.InputRequired()] ) next_route_matchdict = wtforms.fields.HiddenField( - validators=[wtforms.validators.DataRequired()] + validators=[wtforms.validators.InputRequired()] ) def __init__(self, *args, user_service, **kwargs): @@ -467,7 +467,7 @@ def validate_recovery_code_value(self, field): class RequestPasswordResetForm(forms.Form): username_or_email = wtforms.StringField( - validators=[wtforms.validators.DataRequired()] + validators=[wtforms.validators.InputRequired()] ) def __init__(self, *args, user_service, **kwargs): diff --git a/warehouse/accounts/views.py b/warehouse/accounts/views.py index a2709c58be41..50a46be1bfe8 100644 --- a/warehouse/accounts/views.py +++ b/warehouse/accounts/views.py @@ -29,6 +29,7 @@ from pyramid.view import view_config, view_defaults from sqlalchemy.exc import NoResultFound from webauthn.helpers import bytes_to_base64url +from webob.multidict import MultiDict from warehouse.accounts import REDIRECT_FIELD_NAME from warehouse.accounts.forms import ( @@ -557,10 +558,12 @@ def register(request, _form_class=RegistrationForm): # the form contains an auto-generated field from recaptcha with # hyphens in it. make it play nice with wtforms. - post_body = {key.replace("-", "_"): value for key, value in request.POST.items()} + post_body = MultiDict( + {key.replace("-", "_"): value for key, value in request.POST.items()} + ) form = _form_class( - data=post_body, + formdata=post_body, user_service=user_service, recaptcha_service=recaptcha_service, breach_service=breach_service, diff --git a/warehouse/admin/views/banners.py b/warehouse/admin/views/banners.py index f90aa0cec5d7..e7df2e57d29e 100644 --- a/warehouse/admin/views/banners.py +++ b/warehouse/admin/views/banners.py @@ -148,18 +148,18 @@ class BannerForm(Form): name = wtforms.fields.StringField( validators=[ wtforms.validators.Length(max=100), - wtforms.validators.DataRequired(), + wtforms.validators.InputRequired(), ], ) text = wtforms.fields.StringField( validators=[ wtforms.validators.Length(max=280), - wtforms.validators.DataRequired(), + wtforms.validators.InputRequired(), ], ) link_url = wtforms.fields.StringField( validators=[ - wtforms.validators.DataRequired(), + wtforms.validators.InputRequired(), URIValidator(), ] ) @@ -179,4 +179,4 @@ class BannerForm(Form): active = wtforms.fields.BooleanField( validators=[wtforms.validators.Optional()], default=False ) - end = wtforms.fields.DateField(validators=[wtforms.validators.DataRequired()]) + end = wtforms.fields.DateField(validators=[wtforms.validators.InputRequired()]) diff --git a/warehouse/admin/views/sponsors.py b/warehouse/admin/views/sponsors.py index c9da0ce7cf07..b2d3451c166d 100644 --- a/warehouse/admin/views/sponsors.py +++ b/warehouse/admin/views/sponsors.py @@ -30,7 +30,7 @@ class SponsorForm(Form): name = wtforms.fields.StringField( validators=[ wtforms.validators.Length(max=100), - wtforms.validators.DataRequired(), + wtforms.validators.InputRequired(), ], ) service = wtforms.fields.StringField( @@ -39,7 +39,7 @@ class SponsorForm(Form): link_url = wtforms.fields.StringField( validators=[ - wtforms.validators.DataRequired(), + wtforms.validators.InputRequired(), URIValidator(), ] ) diff --git a/warehouse/admin/views/users.py b/warehouse/admin/views/users.py index a35197f7bcae..36afac203a1b 100644 --- a/warehouse/admin/views/users.py +++ b/warehouse/admin/views/users.py @@ -74,7 +74,7 @@ def user_list(request): class EmailForm(forms.Form): - email = wtforms.fields.EmailField(validators=[wtforms.validators.DataRequired()]) + email = wtforms.fields.EmailField(validators=[wtforms.validators.InputRequired()]) primary = wtforms.fields.BooleanField() verified = wtforms.fields.BooleanField() public = wtforms.fields.BooleanField() diff --git a/warehouse/forklift/legacy.py b/warehouse/forklift/legacy.py index c5b0c4ab7a7d..104f90cd675c 100644 --- a/warehouse/forklift/legacy.py +++ b/warehouse/forklift/legacy.py @@ -421,7 +421,7 @@ class MetadataForm(forms.Form): metadata_version = wtforms.StringField( description="Metadata-Version", validators=[ - wtforms.validators.DataRequired(), + wtforms.validators.InputRequired(), wtforms.validators.AnyOf( # Note: This isn't really Metadata 2.0, however bdist_wheel # claims it is producing a Metadata 2.0 metadata when in @@ -436,7 +436,7 @@ class MetadataForm(forms.Form): name = wtforms.StringField( description="Name", validators=[ - wtforms.validators.DataRequired(), + wtforms.validators.InputRequired(), wtforms.validators.Regexp( PROJECT_NAME_RE, re.IGNORECASE, @@ -450,7 +450,7 @@ class MetadataForm(forms.Form): version = wtforms.StringField( description="Version", validators=[ - wtforms.validators.DataRequired(), + wtforms.validators.InputRequired(), wtforms.validators.Regexp( r"^(?!\s).*(? Date: Thu, 25 May 2023 17:02:03 -0400 Subject: [PATCH 2/5] `make translations` Signed-off-by: William Woodruff --- warehouse/locale/messages.pot | 108 +++++++++++++++++----------------- 1 file changed, 54 insertions(+), 54 deletions(-) diff --git a/warehouse/locale/messages.pot b/warehouse/locale/messages.pot index f0a619bb8480..ada718c24b40 100644 --- a/warehouse/locale/messages.pot +++ b/warehouse/locale/messages.pot @@ -1,10 +1,10 @@ -#: warehouse/views.py:140 +#: warehouse/views.py:141 msgid "" "Two-factor authentication must be enabled on your account to perform this" " action." msgstr "" -#: warehouse/views.py:265 +#: warehouse/views.py:266 msgid "Locale updated" msgstr "" @@ -100,216 +100,216 @@ msgstr "" msgid "No user found with that username or email" msgstr "" -#: warehouse/accounts/views.py:99 +#: warehouse/accounts/views.py:100 msgid "" "There have been too many unsuccessful login attempts. You have been " "locked out for {}. Please try again later." msgstr "" -#: warehouse/accounts/views.py:116 +#: warehouse/accounts/views.py:117 msgid "" "Too many emails have been added to this account without verifying them. " "Check your inbox and follow the verification links. (IP: ${ip})" msgstr "" -#: warehouse/accounts/views.py:128 +#: warehouse/accounts/views.py:129 msgid "" "Too many password resets have been requested for this account without " "completing them. Check your inbox and follow the verification links. (IP:" " ${ip})" msgstr "" -#: warehouse/accounts/views.py:268 warehouse/accounts/views.py:332 -#: warehouse/accounts/views.py:334 warehouse/accounts/views.py:361 -#: warehouse/accounts/views.py:363 warehouse/accounts/views.py:429 +#: warehouse/accounts/views.py:269 warehouse/accounts/views.py:333 +#: warehouse/accounts/views.py:335 warehouse/accounts/views.py:362 +#: warehouse/accounts/views.py:364 warehouse/accounts/views.py:430 msgid "Invalid or expired two factor login." msgstr "" -#: warehouse/accounts/views.py:326 +#: warehouse/accounts/views.py:327 msgid "Already authenticated" msgstr "" -#: warehouse/accounts/views.py:405 +#: warehouse/accounts/views.py:406 msgid "Successful WebAuthn assertion" msgstr "" -#: warehouse/accounts/views.py:461 warehouse/manage/views/__init__.py:816 +#: warehouse/accounts/views.py:462 warehouse/manage/views/__init__.py:816 msgid "Recovery code accepted. The supplied code cannot be used again." msgstr "" -#: warehouse/accounts/views.py:547 +#: warehouse/accounts/views.py:548 msgid "" "New user registration temporarily disabled. See https://pypi.org/help" "#admin-intervention for details." msgstr "" -#: warehouse/accounts/views.py:679 +#: warehouse/accounts/views.py:682 msgid "Expired token: request a new password reset link" msgstr "" -#: warehouse/accounts/views.py:681 +#: warehouse/accounts/views.py:684 msgid "Invalid token: request a new password reset link" msgstr "" -#: warehouse/accounts/views.py:683 warehouse/accounts/views.py:786 -#: warehouse/accounts/views.py:886 warehouse/accounts/views.py:1059 +#: warehouse/accounts/views.py:686 warehouse/accounts/views.py:789 +#: warehouse/accounts/views.py:889 warehouse/accounts/views.py:1062 msgid "Invalid token: no token supplied" msgstr "" -#: warehouse/accounts/views.py:687 +#: warehouse/accounts/views.py:690 msgid "Invalid token: not a password reset token" msgstr "" -#: warehouse/accounts/views.py:692 +#: warehouse/accounts/views.py:695 msgid "Invalid token: user not found" msgstr "" -#: warehouse/accounts/views.py:703 +#: warehouse/accounts/views.py:706 msgid "Invalid token: user has logged in since this token was requested" msgstr "" -#: warehouse/accounts/views.py:721 +#: warehouse/accounts/views.py:724 msgid "" "Invalid token: password has already been changed since this token was " "requested" msgstr "" -#: warehouse/accounts/views.py:754 +#: warehouse/accounts/views.py:757 msgid "You have reset your password" msgstr "" -#: warehouse/accounts/views.py:782 +#: warehouse/accounts/views.py:785 msgid "Expired token: request a new email verification link" msgstr "" -#: warehouse/accounts/views.py:784 +#: warehouse/accounts/views.py:787 msgid "Invalid token: request a new email verification link" msgstr "" -#: warehouse/accounts/views.py:790 +#: warehouse/accounts/views.py:793 msgid "Invalid token: not an email verification token" msgstr "" -#: warehouse/accounts/views.py:799 +#: warehouse/accounts/views.py:802 msgid "Email not found" msgstr "" -#: warehouse/accounts/views.py:802 +#: warehouse/accounts/views.py:805 msgid "Email already verified" msgstr "" -#: warehouse/accounts/views.py:820 +#: warehouse/accounts/views.py:823 msgid "You can now set this email as your primary address" msgstr "" -#: warehouse/accounts/views.py:824 +#: warehouse/accounts/views.py:827 msgid "This is your primary address" msgstr "" -#: warehouse/accounts/views.py:829 +#: warehouse/accounts/views.py:832 msgid "Email address ${email_address} verified. ${confirm_message}." msgstr "" -#: warehouse/accounts/views.py:882 +#: warehouse/accounts/views.py:885 msgid "Expired token: request a new organization invitation" msgstr "" -#: warehouse/accounts/views.py:884 +#: warehouse/accounts/views.py:887 msgid "Invalid token: request a new organization invitation" msgstr "" -#: warehouse/accounts/views.py:890 +#: warehouse/accounts/views.py:893 msgid "Invalid token: not an organization invitation token" msgstr "" -#: warehouse/accounts/views.py:894 +#: warehouse/accounts/views.py:897 msgid "Organization invitation is not valid." msgstr "" -#: warehouse/accounts/views.py:903 +#: warehouse/accounts/views.py:906 msgid "Organization invitation no longer exists." msgstr "" -#: warehouse/accounts/views.py:956 +#: warehouse/accounts/views.py:959 msgid "Invitation for '${organization_name}' is declined." msgstr "" -#: warehouse/accounts/views.py:1021 +#: warehouse/accounts/views.py:1024 msgid "You are now ${role} of the '${organization_name}' organization." msgstr "" -#: warehouse/accounts/views.py:1055 +#: warehouse/accounts/views.py:1058 msgid "Expired token: request a new project role invitation" msgstr "" -#: warehouse/accounts/views.py:1057 +#: warehouse/accounts/views.py:1060 msgid "Invalid token: request a new project role invitation" msgstr "" -#: warehouse/accounts/views.py:1063 +#: warehouse/accounts/views.py:1066 msgid "Invalid token: not a collaboration invitation token" msgstr "" -#: warehouse/accounts/views.py:1067 +#: warehouse/accounts/views.py:1070 msgid "Role invitation is not valid." msgstr "" -#: warehouse/accounts/views.py:1082 +#: warehouse/accounts/views.py:1085 msgid "Role invitation no longer exists." msgstr "" -#: warehouse/accounts/views.py:1115 +#: warehouse/accounts/views.py:1118 msgid "Invitation for '${project_name}' is declined." msgstr "" -#: warehouse/accounts/views.py:1183 +#: warehouse/accounts/views.py:1186 msgid "You are now ${role} of the '${project_name}' project." msgstr "" -#: warehouse/accounts/views.py:1401 warehouse/accounts/views.py:1421 -#: warehouse/accounts/views.py:1556 warehouse/manage/views/__init__.py:1225 +#: warehouse/accounts/views.py:1404 warehouse/accounts/views.py:1424 +#: warehouse/accounts/views.py:1559 warehouse/manage/views/__init__.py:1225 #: warehouse/manage/views/__init__.py:1244 msgid "" "Trusted publishers are temporarily disabled. See https://pypi.org/help" "#admin-intervention for details." msgstr "" -#: warehouse/accounts/views.py:1435 +#: warehouse/accounts/views.py:1438 msgid "" "You must have a verified email in order to register a pending trusted " "publisher. See https://pypi.org/help#openid-connect for details." msgstr "" -#: warehouse/accounts/views.py:1448 +#: warehouse/accounts/views.py:1451 msgid "You can't register more than 3 pending trusted publishers at once." msgstr "" -#: warehouse/accounts/views.py:1464 warehouse/manage/views/__init__.py:1263 +#: warehouse/accounts/views.py:1467 warehouse/manage/views/__init__.py:1263 msgid "" "There have been too many attempted trusted publisher registrations. Try " "again later." msgstr "" -#: warehouse/accounts/views.py:1478 warehouse/manage/views/__init__.py:1277 +#: warehouse/accounts/views.py:1481 warehouse/manage/views/__init__.py:1277 msgid "The trusted publisher could not be registered" msgstr "" -#: warehouse/accounts/views.py:1497 +#: warehouse/accounts/views.py:1500 msgid "" "This trusted publisher has already been registered. Please contact PyPI's" " admins if this wasn't intentional." msgstr "" -#: warehouse/accounts/views.py:1533 +#: warehouse/accounts/views.py:1536 msgid "Registered a new publishing publisher to create " msgstr "" -#: warehouse/accounts/views.py:1570 warehouse/accounts/views.py:1583 -#: warehouse/accounts/views.py:1590 +#: warehouse/accounts/views.py:1573 warehouse/accounts/views.py:1586 +#: warehouse/accounts/views.py:1593 msgid "Invalid publisher ID" msgstr "" -#: warehouse/accounts/views.py:1596 +#: warehouse/accounts/views.py:1599 msgid "Removed trusted publisher for project " msgstr "" From 8b2207a691c15dab80df71047af556a801130738 Mon Sep 17 00:00:00 2001 From: William Woodruff Date: Thu, 25 May 2023 17:19:55 -0400 Subject: [PATCH 3/5] pyproject: exclude webob.* from mypy There's no current tracking issue for supporting type hints in WebOb. Signed-off-by: William Woodruff --- pyproject.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/pyproject.toml b/pyproject.toml index 868a78724bb8..9196c436d4fc 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -48,6 +48,7 @@ module = [ "sqlalchemy.*", # https://docs.sqlalchemy.org/en/14/orm/extensions/mypy.html "transaction.*", "venusian.*", + "webob.*", "whitenoise.*", "wtforms.*", # https://github.com/wtforms/wtforms/issues/618 "yara.*", From 408a8de52342bd913e91c236aa834bc7696f4280 Mon Sep 17 00:00:00 2001 From: William Woodruff Date: Thu, 25 May 2023 17:25:29 -0400 Subject: [PATCH 4/5] pyproject: tracking issue Signed-off-by: William Woodruff --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 9196c436d4fc..b5b94dec1310 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -48,7 +48,7 @@ module = [ "sqlalchemy.*", # https://docs.sqlalchemy.org/en/14/orm/extensions/mypy.html "transaction.*", "venusian.*", - "webob.*", + "webob.*", # https://github.com/python/typeshed/pull/9874 "whitenoise.*", "wtforms.*", # https://github.com/wtforms/wtforms/issues/618 "yara.*", From 0f08460b7f3457d7de79f4e56bd1b7e2b0a354e5 Mon Sep 17 00:00:00 2001 From: William Woodruff Date: Thu, 25 May 2023 17:33:35 -0400 Subject: [PATCH 5/5] tests: mash a type into place Signed-off-by: William Woodruff --- tests/unit/admin/views/test_banners.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/unit/admin/views/test_banners.py b/tests/unit/admin/views/test_banners.py index 71d26441929d..18586e6fdf29 100644 --- a/tests/unit/admin/views/test_banners.py +++ b/tests/unit/admin/views/test_banners.py @@ -232,4 +232,7 @@ def test_valid_data(self, banner_data): "active": False, "link_label": Banner.DEFAULT_BTN_LABEL, } + + # Mash the `end` into a date object to match the form's coerced result. + banner_data["end"] = datetime.date.fromisoformat(banner_data["end"]) assert data == {**banner_data, **defaults}