FirebirdSQL / python3-driver

Firebird driver for Python that uses new Firebird API
https://www.firebirdsql.org/en/devel-python-driver/
MIT License
26 stars 10 forks source link

exeption returns non ascii-127 symbols #4

Closed AlexDeeep closed 2 years ago

AlexDeeep commented 2 years ago

Hello, Pavel

I have an error if procedure execution returns exeption with non ascii-127 symbols and i call rollback for transaction:

File "C:\Program Files\Python\Python39\lib\site-packages\firebird\driver\interfaces.py", line 1292, in format_status return buffer.value.decode() UnicodeDecodeError: 'utf-8' codec can't decode byte 0xcd in position 34: invalid continuation byte

My fdb encoding is cp1251, but for connection i forced to use UTF-8 charset, otherwise it crashes in other cases myconnect = fdb.connect(database=dbpath, user=uname, password=upass, charset='UTF8')

My fast local solution is modifying function format_status, :

    def format_status(self, status: iStatus) -> str:
        "Replaces `fb_interpret()`. Size of buffer, passed into this method, should not be less than 50 bytes."
        buffer = create_string_buffer(1024)
        self.vtable.formatStatus(self, buffer, 1024, status)
        try:
            ret = buffer.value.decode()
        except:
            ret = buffer.value.decode(encoding='cp1251')
        return ret

Would you create a global variable for connection to specify database encoding for cases like this

pcisar commented 2 years ago

Interesting. It's certainly a flaw in driver, as it should be able to handle non-ascii error messages. I'll add optional encoding parameter to iUtil_v2.format_status(). However, this function is called from iVersioned "internal" __report() that's called from _check() function, that is used to verify result of the call from all interfaces where applicable. So, I'm going to add the encoding property to iVersioned (with default None), and also to Connection class (with default as connection charset). The tricky part will be the "distribution" of encoding to interfaces (descending from iVersioned) used internally by Connection (and other end user classes). As it's pointless to set it on ALL classes and interfaces, I have to assess each one, which will take time. But you can count that it will appear in next driver release.

pcisar commented 2 years ago

Well, I decided to handle it differently. The firebird.driver.fbapi defined sys_encoding with value locale.getpreferredencoding() that was used in exception_from_status to decode the error message. I used this method also for iUtil.format_status, and for convenience renamed the variable to "err_encoding". Both decode calls now also define errors="replace" to prevent exceptions there. So, if locale.getpreferredencoding() would not return the proper value (for example because the remote server uses different encoding that client), you may change the value of firebird.driver.fbapi.err_encoding.