1

Please note that I've found similar issues to mine, but none of the fixes apply. Also, please note that this code works in python 2.7, but not 3.7.

The issue is that I have the following model:

class Client(Base, UserMixin):
    """
    Represents a client in the database.

    :param id: primary key of test in database
    :param uuid: String representation of UUID Version 4 (Random). If client
    does not specify, it will generate one on the server. This can be used to
    check if things have been uploaded.
    :param username: the username for the client, must be unique system-wide.
    :param password: the bcrypt password hash for the client.
    """
    __tablename__ = 'clients'

    __form_keys__ = {'username', 'password', 'is_system_administrator'}
    __keys__ = __form_keys__ | {'id', 'uuid', 'client_id'}
    __hidden_keys__ = {'username', 'password'}

    username = Column(String(255), unique=True, nullable=False)

    password = Column(BINARY(60), nullable=False)

where, as per the requirements of bcrypt, the password is encoded using a BINARY datatype and then hashed later.

When I try inserting into the table, I get the error that:

sqlalchemy.exc.StatementError: (builtins.TypeError) string argument without an encoding
[SQL: INSERT INTO clients (uuid, username, password, is_system_administrator) VALUES (%(uuid)s, %(username)s, %(password)s, %(is_system_administrator)s)]
[parameters: [{'is_system_administrator': True, 'password': '$2a$12$ED6YdEPAb5pt0wTMno9M/OhpCNXo1CyPxmZuUK.YHdxrahW67DEDS', 'username': 'username'}]]

Where my problem differs from answers I've found, is that for example here sqlalchemy-insert-string-argument-without-an-encoding, the executed query is assembled directly using the model's columns, so it's easy to do the encoding at this stage.

I've tried, unsuccessfully, to figure out where to encode this, and I even tried switch the data type from BINARY to TEXT (the backend is MySQL), but nothing helped.

I'm not exactly sure how to proceed.

horcle_buzz
  • 2,101
  • 3
  • 30
  • 59

1 Answers1

1

I was able to reproduce your issue using

session.add(
    Client(
        is_system_administrator=True,
        password="$2a$12$ED6YdEPAb5pt0wTMno9M/OhpCNXo1CyPxmZuUK.YHdxrahW67DEDS",
        username="username",
    )
)

However, this seems to work

session.add(
    Client(
        is_system_administrator=True,
        password=bytes(
            "$2a$12$ED6YdEPAb5pt0wTMno9M/OhpCNXo1CyPxmZuUK.YHdxrahW67DEDS",
            "ascii",
        ),
        username="username",
    )
)
Gord Thompson
  • 116,920
  • 32
  • 215
  • 418