SAP / PyRFC

Asynchronous, non-blocking SAP NW RFC SDK bindings for Python
http://sap.github.io/PyRFC
Apache License 2.0
510 stars 137 forks source link

pyrfc._pyrfc.wrapError KeyError: 0 (Python 2.7) #134

Closed guettli closed 4 years ago

guettli commented 4 years ago

On Python 2.7 I get this on connection.call(...):

Traceback (most recent call last):

  File "src/pyrfc/_pyrfc.pyx", line 414, in pyrfc._pyrfc.Connection.call
  File "src/pyrfc/_pyrfc.pyx", line 1649, in pyrfc._pyrfc.fillFunctionParameter
  File "src/pyrfc/_pyrfc.pyx", line 1700, in pyrfc._pyrfc.fillVariable
  File "src/pyrfc/_pyrfc.pyx", line 1676, in pyrfc._pyrfc.fillTable
  File "src/pyrfc/_pyrfc.pyx", line 1661, in pyrfc._pyrfc.fillStructureField
  File "src/pyrfc/_pyrfc.pyx", line 1786, in pyrfc._pyrfc.fillVariable
  File "src/pyrfc/_pyrfc.pyx", line 2241, in pyrfc._pyrfc.wrapError
KeyError: 0

It fails with 1.9.99 and works with 1.9.94.

I tried to create a minimal example, but failed. It works on the command line.

I will try again tomorrow.

guettli commented 4 years ago

In the group2error dict, there is no key 0. See: https://github.com/SAP/PyRFC/blob/404a14bfda3097926a77ac5bcee372ea3e4aab61/src/pyrfc/_pyrfc.pyx#L1795

I modified the code, recompiled with Cython (the first time in my live that I use Cython) and could print the content of the dict:

1: <class 'pyrfc._exception.ABAPApplicationError'>
2: <class 'pyrfc._exception.ABAPRuntimeError'>
3: <class 'pyrfc._exception.LogonError'>
4: <class 'pyrfc._exception.CommunicationError'>
5: <class 'pyrfc._exception.ExternalRuntimeError'>
6: <class 'pyrfc._exception.ExternalApplicationError'>
7: <class 'pyrfc._exception.ExternalAuthorizationError'>
guettli commented 4 years ago

I tried the latest version from git and the error does not happen any more. Thank you for constant updates!

guettli commented 4 years ago

I am sorry. It still happens.

guettli commented 4 years ago

Very strange. It works via command-line, but not via web-request (Apache, wsgi).

guettli commented 4 years ago

I wanted to see the error message. I modified the code like this:

diff --git a/src/pyrfc/_exception.py b/src/pyrfc/_exception.py
index 062811d..ff7a17d 100755
--- a/src/pyrfc/_exception.py
+++ b/src/pyrfc/_exception.py
@@ -92,6 +92,7 @@ class RFCLibError(RFCError):
         self.msg_v4 = msg_v4

     def __str__(self):
+        return repr(self.__dict__)
         return "{} (rc={}): key={}, message={} [MSG: class={}, type={}, number={}, v1-4:={};{};{};{}]".format(
             self.code2txt.get(self.code, u"???"),
             self.code,
diff --git a/src/pyrfc/_pyrfc.pyx b/src/pyrfc/_pyrfc.pyx
index 9753d68..8543fc7 100755
--- a/src/pyrfc/_pyrfc.pyx
+++ b/src/pyrfc/_pyrfc.pyx
@@ -2230,7 +2230,8 @@ cdef wrapVariable(RFCTYPE typ, RFC_FUNCTION_HANDLE container, SAP_UC* cName, uns
         raise RFCError('Unknown RFC type %d when wrapping %s' % (typ, wrapString(cName)))

 cdef wrapError(RFC_ERROR_INFO* errorInfo):
-    group2error = { ABAP_APPLICATION_FAILURE: ABAPApplicationError,
+    group2error = { 0: ExternalRuntimeError,
+                    ABAP_APPLICATION_FAILURE: ABAPApplicationError,
                     ABAP_RUNTIME_FAILURE: ABAPRuntimeError,
                     LOGON_FAILURE: LogonError,
                     COMMUNICATION_FAILURE: CommunicationError,

This is very very strange. I was able to reproduce the error in a small command line too.

The first time I call it:

Traceback (most recent call last):
  File "/home/modlink_cok_q/src/modlink/modlink/models/remote.py", line 107, in call
    return self.connection.call(*[bytes(arg) for arg in args], **kwargs)
  File "src/pyrfc/_pyrfc.pyx", line 414, in pyrfc._pyrfc.Connection.call
  File "src/pyrfc/_pyrfc.pyx", line 1649, in pyrfc._pyrfc.fillFunctionParameter
  File "src/pyrfc/_pyrfc.pyx", line 1695, in pyrfc._pyrfc.fillVariable
  File "src/pyrfc/_pyrfc.pyx", line 1661, in pyrfc._pyrfc.fillStructureField
  File "src/pyrfc/_pyrfc.pyx", line 1786, in pyrfc._pyrfc.fillVariable
  File "src/pyrfc/_pyrfc.pyx", line 2244, in pyrfc._pyrfc.wrapError
  File "src/pyrfc/_pyrfc.pyx", line 2262, in pyrfc._pyrfc.wrapString
RFCError: wrapString uclen: 3 utf8_size: 10

The second time I call it (no modification was done):

Traceback (most recent call last):
  File "/home/modlink_cok_q/src/modlink/modlink/models/remote.py", line 107, in call
    return self.connection.call(*[bytes(arg) for arg in args], **kwargs)
  File "src/pyrfc/_pyrfc.pyx", line 414, in pyrfc._pyrfc.Connection.call
  File "src/pyrfc/_pyrfc.pyx", line 1649, in pyrfc._pyrfc.fillFunctionParameter
  File "src/pyrfc/_pyrfc.pyx", line 1695, in pyrfc._pyrfc.fillVariable
  File "src/pyrfc/_pyrfc.pyx", line 1661, in pyrfc._pyrfc.fillStructureField
  File "src/pyrfc/_pyrfc.pyx", line 1786, in pyrfc._pyrfc.fillVariable
ExternalRuntimeError: {'msg_v2': u'\u7fd2', 'msg_v3': u'\u9946\u7fd2', 'code': 7, 'msg_v4': '', 'msg_type': u'\u4f18\u0670\uca2e\u9410\u0442', 'msg_number': u'\uca2e\u9410\u0442', 'msg_class': u'\uff60\u9946\u7fd2', 'msg_v1': '', 'key': u'\u2f40\u0444', 'message': "''"}

I have no clue what is going on here. This looks like random data from memory addresses.

guettli commented 4 years ago

I can reproduce the issue now:

Python 2.7 and Django==1.11.15

# -*- coding: utf-8 -*
from __future__ import absolute_import, division, print_function, unicode_literals

# https://github.com/SAP/PyRFC/issues/134
import json
from pyrfc import Connection

conn = Connection(...)

data = json.loads('''
{"RFCTABLE": [], "IMPORTSTRUCT": {"RFCDATE": "", "RFCFLOAT": 1.1, "RFCDATA1": "", "RFCDATA2": "", "RFCTIME": "", "RFCCHAR1": "", "RFCHEX3": "", "RFCCHAR2": "", "RFCCHAR4": ""}}
''')
import django

django.setup() ## >> if uncommented it works

result = conn.call(b'STFC_STRUCTURE', **data)

print(result)

If I uncomment the django.setup() line it works. I have no clue what this could be, since no django code gets called during conn.call().

bsrdjan commented 4 years ago

Please check with 2.0.0. If does not work, could you please add print data before calling STFC_STRUCTURE?

guettli commented 4 years ago

Works with 2.0.0. Thank you.