spulec / freezegun

Let your Python tests travel through time
Apache License 2.0
4.17k stars 269 forks source link

Failed processing pyformat-parameters; Python 'fakedatetime' cannot be converted to a MySQL type #434

Open lclpedro opened 2 years ago

lclpedro commented 2 years ago

I'm getting this error with the mysql connector, does anyone know why this is happening, if there is any specific reason?

Error occurred:

raise errors.ProgrammingError(
E   sqlalchemy.exc.ProgrammingError: (mysql.connector.errors.ProgrammingError) Failed processing pyformat-parameters; Python 'fakedatetime' cannot be converted to a MySQL type
E   [SQL: INSERT INTO place (place_uuid, use_cash, delivery_instructions, address_id, storage_id, business_id, personal_data_id, status, created_at, updated_at) VALUES (%(place_uuid)s, %(use_cash)s, %(delivery_instructions)s, %(address_id)s, %(storage_id)s, %(business_id)s, %(personal_data_id)s, %(status)s, %(created_at)s, %(updated_at)s)]
E   [parameters: {'place_uuid': 'c7e8da32-bbf7-43b3-baf8-862b19e05087', 'use_cash': 0, 'delivery_instructions': None, 'address_id': 2, 'storage_id': 1, 'business_id': 1, 'personal_data_id': 1, 'status': 'pending', 'created_at': FakeDatetime(2021, 12, 5, 0, 0), 'updated_at': FakeDatetime(2021, 12, 5, 0, 0)}]
E   (Background on this error at: https://sqlalche.me/e/14/f405)

Test..


@pytest.fixture
@freeze_time("2021-12-04")
def fake_base_another_day(client: TestClient, with_body: dict):
    with_body["personalData"]["cpf"] = "08697524300"  # Fake
    with_body["personalData"]["firstName"] = "lalala Ferreira"
    with_body["personalData"]["lastName"] = "da Conceição"
    with_body["personalData"]["email"] = "lalala@teleworm.us"
    with_body["personalData"]["phone"] = "123123123123"
    with_body["personalData"]["address"]["city"] = "Curitiba"
    with_body["personalData"]["address"]["state"] = "PR"
    with_body["placeDetails"]["addressType"] = "residential"
    client.post(
        URL_REGISTRATION, json=with_body, headers={"authorization": pytest.TOKEN}
    )
lclpedro commented 2 years ago

Resolved with code, in head of the test..

datetime.now().__class__.__name__ = "datetime"
datetime.now().date().__class__.__name__ = "date"
@pytest.fixture
@freeze_time("2021-12-04")
def fake_base_another_day(client: TestClient, with_body: dict):

    datetime.now().__class__.__name__ = "datetime"
    datetime.now().date().__class__.__name__ = "date"

    with_body["personalData"]["cpf"] = "08697524300"  # Fake
    with_body["personalData"]["firstName"] = "lalala Ferreira"
    with_body["personalData"]["lastName"] = "da Conceição"
    with_body["personalData"]["email"] = "lalala@teleworm.us"
    with_body["personalData"]["phone"] = "123123123123"
    with_body["personalData"]["address"]["city"] = "Curitiba"
    with_body["personalData"]["address"]["state"] = "PR"
    with_body["placeDetails"]["addressType"] = "residential"
    client.post(
        URL_REGISTRATION, json=with_body, headers={"authorization": pytest.TOKEN}
    )
diogohudson commented 2 years ago

WIth Django, the same thing here.

@pytest.mark.django_db
def test_purge_old_data_success(user_01, user_02, freezer):
    """Test if notification are purged as expected."""

    origin = NotificationOrigin.FROM_GROUP.value
    subject = "subject"
    body = "body"
    now = timezone.now()

    # datetime.now().__class__.__name__ = "datetime"
    # datetime.now().date().__class__.__name__ = "date"

    freezer.move_to(now - timedelta(days=30))
    for _ in range(5):
        Notification.objects.create(
            user_receiver=user_02, origin=origin, subject=subject, body=body,
            created_at=str(datetime.now()),
            updated_at=str(datetime.now())
        )

This is the message:

self = <mysql.connector.django.base.DjangoMySQLConverter object at 0xffff8ce99ae0>, value = FakeDatetime(2022, 9, 1, 23, 5, 0, 127073)

    def to_mysql(self, value):
        """Convert Python data type to MySQL"""
        type_name = value.__class__.__name__.lower()
        try:
            return getattr(self, f"_{type_name}_to_mysql")(value)
        except AttributeError:
            if self.str_fallback:
                return str(value).encode()
>           raise TypeError(
                f"Python '{type_name}' cannot be converted to a MySQL type"
            ) from None
E           TypeError: Python 'fakedatetime' cannot be converted to a MySQL type