Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Changed signature of method #28

Closed
silent-nekto opened this issue Apr 20, 2023 · 16 comments · Fixed by #39
Closed

Changed signature of method #28

silent-nekto opened this issue Apr 20, 2023 · 16 comments · Fixed by #39

Comments

@silent-nekto
Copy link

  File "c:\python38-32\lib\site-packages\signify\authenticode\authroot.py", line 338, in _parse_attributes
    _, v = ber_decoder.decode(value, recursiveFlag=0)
  File "c:\python38-32\lib\site-packages\pyasn1\codec\ber\decoder.py", line 2003, in __call__
    for asn1Object in streamingDecoder:
  File "c:\python38-32\lib\site-packages\pyasn1\codec\ber\decoder.py", line 1918, in __iter__
    for asn1Object in self._singleItemDecoder(
  File "c:\python38-32\lib\site-packages\pyasn1\codec\ber\decoder.py", line 1778, in __call__
    for value in concreteDecoder.valueDecoder(
  File "c:\python38-32\lib\site-packages\pyasn1\codec\ber\decoder.py", line 302, in valueDecoder
    for chunk in substrateFun(asn1Object, substrate, length, options):
TypeError: <lambda>() takes 3 positional arguments but 4 were given
@dmiller7
Copy link

I am also seeing this issue using pyasn1-0.5.0 and pysnmp-4.4.12 when I use getcmd(). https://pysnmp.readthedocs.io/en/latest/docs/hlapi/v3arch/asyncore/sync/manager/cmdgen/getcmd.html

If I revert to pyasn1==0.4.8 then the issue is resolved. Full error dump is:

Exception error was: poll error: Traceback (most recent call last):
;  File "/usr/local/lib/python3.8/dist-packages/pysnmp/carrier/asyncore/dispatch.py", line 45, in runDispatcher
    loop(timeout or self.getTimerResolution(),
;  File "/usr/lib/python3.8/asyncore.py", line 207, in loop
    poll_fun(timeout, map)
;  File "/usr/lib/python3.8/asyncore.py", line 188, in poll2
    readwrite(obj, flags)
;  File "/usr/lib/python3.8/asyncore.py", line 123, in readwrite
    obj.handle_error()
;  File "/usr/lib/python3.8/asyncore.py", line 108, in readwrite
    obj.handle_read_event()
;  File "/usr/lib/python3.8/asyncore.py", line 420, in handle_read_event
    self.handle_read()
;  File "/usr/local/lib/python3.8/dist-packages/pysnmp/carrier/asyncore/dgram/base.py", line 170, in handle_read
    self._cbFun(self, transportAddress, incomingMessage)
;  File "/usr/local/lib/python3.8/dist-packages/pysnmp/carrier/base.py", line 84, in _cbFun
    self.__recvCallables[recvId](
;  File "/usr/local/lib/python3.8/dist-packages/pysnmp/entity/engine.py", line 151, in __receiveMessageCbFun
    self.msgAndPduDsp.receiveMessage(
;  File "/usr/local/lib/python3.8/dist-packages/pysnmp/proto/rfc3412.py", line 291, in receiveMessage
    msgVersion = verdec.decodeMessageVersion(wholeMsg)
;  File "/usr/local/lib/python3.8/dist-packages/pysnmp/proto/api/verdec.py", line 15, in decodeMessageVersion
    seq, wholeMsg = decoder.decode(
;  File "/usr/local/lib/python3.8/dist-packages/pyasn1/codec/ber/decoder.py", line 2003, in __call__
    for asn1Object in streamingDecoder:
;  File "/usr/local/lib/python3.8/dist-packages/pyasn1/codec/ber/decoder.py", line 1918, in __iter__
    for asn1Object in self._singleItemDecoder(
;  File "/usr/local/lib/python3.8/dist-packages/pyasn1/codec/ber/decoder.py", line 1[77](https://gitlab.labs.liberty.biz/cal_centralaccesslab/scratchpad/lld_sprints/lld_sprint_nine/-/jobs/94045#L77)8, in __call__
    for value in concreteDecoder.valueDecoder(
;  File "/usr/local/lib/python3.8/dist-packages/pyasn1/codec/ber/decoder.py", line 654, in valueDecoder
    for chunk in substrateFun(asn1Object, substrate, length, options):
;TypeError: <lambda>() takes 3 positional arguments but 4 were given
caused by <class 'TypeError'>: <lambda>() takes 3 positional arguments but 4 were given

@haxtibal
Copy link

Changes in commit 93e11a2 leak into client code via pyasn1.codec.ber.decoder.decode(substrateFun=...) API. pysnmp uses that API in pysnmp.proto.api.verdec.decodeMessageVersion, but did not follow the change. The patch below applied to pysnmp fixes the issue for me:

diff --git a/pysnmp/proto/api/verdec.py b/pysnmp/proto/api/verdec.py
index 142a68c2..eadc1140 100644
--- a/pysnmp/proto/api/verdec.py
+++ b/pysnmp/proto/api/verdec.py
@@ -6,6 +6,7 @@
 #
 from pyasn1.codec.ber import decoder
 from pyasn1.codec.ber import eoo
+from pyasn1.codec.streaming import readFromStream
 from pyasn1.error import PyAsn1Error
 from pyasn1.type import univ
 
@@ -14,14 +15,14 @@ from pysnmp.proto.error import ProtocolError
 
 def decodeMessageVersion(wholeMsg):
     try:
-        seq, wholeMsg = decoder.decode(
+        wholeMsg, seq = decoder.decode(
             wholeMsg, asn1Spec=univ.Sequence(),
-            recursiveFlag=False, substrateFun=lambda a, b, c: (a, b[:c])
+            recursiveFlag=False, substrateFun=lambda a, b, c, d: readFromStream(b, c)
         )
 
         ver, wholeMsg = decoder.decode(
             wholeMsg, asn1Spec=univ.Integer(),
-            recursiveFlag=False, substrateFun=lambda a, b, c: (a, b[:c])
+            recursiveFlag=False, substrateFun=lambda a, b, c, d: readFromStream(b, c)
         )
 
         if eoo.endOfOctets.isSameTypeWith(ver):

But:

  • Note how seq and wholeMsg are swapped when decoding the Sequence type. This works but doesn't look right.
  • It's a fix to pysnmp, not to pyasn1. I don't know about the current state of pysnmp, and thus not where to file a PR.

@lextm
Copy link

lextm commented Apr 21, 2023

@haxtibal You can find primary forks in etingof/pysnmp#429

BTW, your patch for pysnmp doesn't works for older pyasn1 releases, so probably not likely to be accepted by the forks without modification. But it is a great start.

@ralphje
Copy link

ralphje commented Apr 22, 2023

The issue (for me at least) seems to be that https://github.com/pyasn1/pyasn1/blob/main/pyasn1/codec/ber/decoder.py#L1765 generates a substrateFun that is not compatible with the signature expected.

Although recursiveFlag is somehow marked as deprecated (not in docs though), there is currently also no cross-version compatible alternative for substrateFun either.

If I replace the affected line with the suggested lambda a, b, c, d: readFromStream(b, c), the output is still different, so I'm not sure what to do.

@droideck
Copy link

I don't have enough capacity now to work on pysnmp's backwards compatibility change (and, as far as I know, we don't have the option to update pysnmp now, as the maintainer has passed away). But PRs are welcome. :)

@ralphje if this PR #30 doesn't work for you, could you please post your test case and output in the PR's discussion?

@ralphje
Copy link

ralphje commented Apr 22, 2023

Of course.

The following is an example where recursion changes how the result is handled, even with #30 applied. The string 040e300c060a2b0601040182373c0302 is a BER encoded OctetString 300c060a2b0601040182373c0302

import pyasn1
print(pyasn1.__version__)

from pyasn1.codec.ber import decoder

result, rest = decoder.decode(
    bytes.fromhex("040e300c060a2b0601040182373c0302"),
    recursiveFlag=0,
)
print(f"{type(result)=}\n{bytes(result).hex()=}\n{rest.hex()=}")

This is the result:

0.4.8
type(result)=<class 'pyasn1.type.univ.OctetString'>
bytes(result).hex()=''
rest.hex()='300c060a2b0601040182373c0302'

0.5.0
type(result)=<class 'bytes'>
bytes(result).hex()='300c060a2b0601040182373c0302'
rest.hex()=''

@haxtibal
Copy link

haxtibal commented Apr 23, 2023

The following is an example where recursion changes how the result is handled, even with #30 applied.

Just took a closer look at how substrateFun semantics differ between 0.4.8 and 0.5.0.

0.4.8

  • takes 3 arguments: asn1Object, substrate, length, where substrate (seemingly ASN.1 speek for "serialized form of data" - does anybody know who coined the term?) is a bytes like object
  • must return a 2-Tuple (value, remainder)
  • no constraint on how much bytes substrateFun shall process

0.5.0

  • takes 4 arguments: asn1Object, substrate, length, options, where substrate is a byte stream supporting tell(), read(), write()
  • must return an iterator (preferably generator)
    • can yield SubstrateUnderrunError multiple times, to wait until buffer is large enough
    • must yield exactly one value in last iteration (preceding value yields would be ignored)
  • after exhausting the substrateFun iterator length bytes must have been processed, otherwise error is raised

This makes it harder to find a substrateFun for #30 that retains full compatibilty with 0.4.8. A naive implementation could be something like:

diff --git a/pyasn1/codec/ber/decoder.py b/pyasn1/codec/ber/decoder.py
index 070733f..f7f0861 100644
--- a/pyasn1/codec/ber/decoder.py
+++ b/pyasn1/codec/ber/decoder.py
@@ -1496,6 +1496,13 @@ class SingleItemDecoder(object):
         self._tagCache = {}
         self._tagSetCache = {}

+    @staticmethod
+    def _outerTypeSubstrateFun(asn1Object, substrate, length, _options):
+        yield asn1Object
+        unprocessed = substrate.read(length)  # advance stream position by length bytes to pass decoders error check
+        substrate.write(unprocessed)          # copy substrate after the cursor and seek back to start of copy,
+        substrate.seek(-length, 1)            # so that decoder will pick up the copy as unprocessed tail
+
     def __call__(self, substrate, asn1Spec=None,
                  tagSet=None, length=None, state=stDecodeTag,
                  decodeFun=None, substrateFun=None,
@@ -1762,7 +1769,7 @@ class SingleItemDecoder(object):

             if state is stDecodeValue:
                 if not options.get('recursiveFlag', True) and not substrateFun:  # deprecate this
-                    substrateFun = lambda a, b, c: (a, b[:c])
+                    substrateFun = self._outerTypeSubstrateFun

                 original_position = substrate.tell()

The diff makes 0.5.0 behave like 0.4.8 in @ralphje s example. Don't know, but I doubt that's how the new API was meant to be used.

openstack-mirroring pushed a commit to openstack/openstack that referenced this issue Apr 26, 2023
* Update requirements from branch 'master'
  to 3442fd6ffe1517716743205973e2c7b84777acea
  - Revert upgrade of pyasn1
    
    Version 0.5.0 of pyasn1 breaks compatiblity with pysnmp (which is
    expected) and pysnmplib (which is definitely not expected).
    
    For more information please look at:
    - pyasn1/pyasn1#28
    - ralphje/signify#37
    
    Change-Id: Ibd7a04c79aa710f98b1c781551464036ced4817f
openstack-mirroring pushed a commit to openstack/requirements that referenced this issue Apr 26, 2023
Version 0.5.0 of pyasn1 breaks compatiblity with pysnmp (which is
expected) and pysnmplib (which is definitely not expected).

For more information please look at:
- pyasn1/pyasn1#28
- ralphje/signify#37

Change-Id: Ibd7a04c79aa710f98b1c781551464036ced4817f
@lextm
Copy link

lextm commented May 8, 2023

According to this commit by Illya in 2020, the breaking change in pyasn1 seems to be expected and he intentionally forced pysnmp 4.4.13+ to avoid pyasn1 0.5+. Sadly pysnmp 4.4.13 was never released.

@ralphje
Copy link

ralphje commented May 8, 2023

From my understanding, this change seems to have more impact than expected during release, though given the situation around @etingof makes this entirely understandable.

If the change is intentional, the issue of backwards incompatibility in substrateFun should at least be addressed in the release notes with sufficient context to understand and adjust code accordingly to the change.

Additionally, as I have shown previously, the recursiveFlag changes behaviour significantly, which should also be addressed, apart from the bug that was fixed in #30.

As for now, to me it is unclear what the intended solution will be from the current pyasn1 package maintainers, and it is unclear whether future versions of pyasn1 will have the exact same behaviour as 0.5.0+#30 or that the backwards incompatibility issue may be partially remedied in a future patch. This currently hinders development in packages that depend on pyasn1, and impedes progress in upgrading to 0.5.0+.

At the very least, test cases should cover all of this to ensure future API stability.

AlbertodelaCruz added a commit to aleasoluciones/infsnmp3 that referenced this issue May 8, 2023
- Fix version due to backward incompatibility issues
  (pyasn1/pyasn1#28)
AlbertodelaCruz added a commit to aleasoluciones/infsnmp3 that referenced this issue May 8, 2023
- Fix version due to backward incompatibility issues
  (pyasn1/pyasn1#28)
rgacogne pushed a commit to rgacogne/pdns that referenced this issue May 12, 2023
@aletelecom
Copy link

I am also seeing this issue using pyasn1-0.5.0 and pysnmp-4.4.12 when I use getcmd(). https://pysnmp.readthedocs.io/en/latest/docs/hlapi/v3arch/asyncore/sync/manager/cmdgen/getcmd.html

If I revert to pyasn1==0.4.8 then the issue is resolved. Full error dump is:

Exception error was: poll error: Traceback (most recent call last):
;  File "/usr/local/lib/python3.8/dist-packages/pysnmp/carrier/asyncore/dispatch.py", line 45, in runDispatcher
    loop(timeout or self.getTimerResolution(),
;  File "/usr/lib/python3.8/asyncore.py", line 207, in loop
    poll_fun(timeout, map)
;  File "/usr/lib/python3.8/asyncore.py", line 188, in poll2
    readwrite(obj, flags)
;  File "/usr/lib/python3.8/asyncore.py", line 123, in readwrite
    obj.handle_error()
;  File "/usr/lib/python3.8/asyncore.py", line 108, in readwrite
    obj.handle_read_event()
;  File "/usr/lib/python3.8/asyncore.py", line 420, in handle_read_event
    self.handle_read()
;  File "/usr/local/lib/python3.8/dist-packages/pysnmp/carrier/asyncore/dgram/base.py", line 170, in handle_read
    self._cbFun(self, transportAddress, incomingMessage)
;  File "/usr/local/lib/python3.8/dist-packages/pysnmp/carrier/base.py", line 84, in _cbFun
    self.__recvCallables[recvId](
;  File "/usr/local/lib/python3.8/dist-packages/pysnmp/entity/engine.py", line 151, in __receiveMessageCbFun
    self.msgAndPduDsp.receiveMessage(
;  File "/usr/local/lib/python3.8/dist-packages/pysnmp/proto/rfc3412.py", line 291, in receiveMessage
    msgVersion = verdec.decodeMessageVersion(wholeMsg)
;  File "/usr/local/lib/python3.8/dist-packages/pysnmp/proto/api/verdec.py", line 15, in decodeMessageVersion
    seq, wholeMsg = decoder.decode(
;  File "/usr/local/lib/python3.8/dist-packages/pyasn1/codec/ber/decoder.py", line 2003, in __call__
    for asn1Object in streamingDecoder:
;  File "/usr/local/lib/python3.8/dist-packages/pyasn1/codec/ber/decoder.py", line 1918, in __iter__
    for asn1Object in self._singleItemDecoder(
;  File "/usr/local/lib/python3.8/dist-packages/pyasn1/codec/ber/decoder.py", line 1[77](https://gitlab.labs.liberty.biz/cal_centralaccesslab/scratchpad/lld_sprints/lld_sprint_nine/-/jobs/94045#L77)8, in __call__
    for value in concreteDecoder.valueDecoder(
;  File "/usr/local/lib/python3.8/dist-packages/pyasn1/codec/ber/decoder.py", line 654, in valueDecoder
    for chunk in substrateFun(asn1Object, substrate, length, options):
;TypeError: <lambda>() takes 3 positional arguments but 4 were given
caused by <class 'TypeError'>: <lambda>() takes 3 positional arguments but 4 were given

This solution worked for me.

@okainov
Copy link

okainov commented Jun 27, 2023

I'm getting the same issue... pinned the version to 0.4.8 for now, but that doesn't seem like a right way to fix it...

@aletelecom
Copy link

I'm getting the same issue... pinned the version to 0.4.8 for now, but that doesn't seem like a right way to fix it...

Could you elaborate?

@lextm
Copy link

lextm commented Jun 27, 2023

@okainov If you read my comment above, you will see the decision was made by the original developer and it cannot be wrong (at least not this moment).

New packages depending on pyasn1 should upgrade and adapt to the changes in 0.5.x, and for pysnmp users they need to pick up a reliable fork.

@seandilda
Copy link

the decision was made by the original developer and it cannot be wrong

While I have a lot of respect for Ilya, I'm not sure we can say the decision is necessarily right based solely on the fact that it came from him. As your previous comment points out, the decision was made over 3 years ago. It may be a good time to revisit that decision.

Most projects follow semantic versioning. Based on that, I think it is right to consider a breaking change between minor versions to be a bug.

@haxtibal
Copy link

I think it is right to consider a breaking change between minor versions to be a bug.

As pointed out in 93e11a2, API compatibility was considered by wrapping pyasn1.codec.ber.decoder.Decoder around the new pyasn1.codec.ber.decoder.StreamingDecoder

All these new feature are natively available through
StreamingDecoder class. Previously published API is implemented
as a thin wrapper on top of that ensuring backward compatibility.

This works, except for the corner case of substrateFun. I'd personally be ok with such a change, if it's understood well enough. I tried half a day or so, which was not enough to gain such understanding (benchmark: explain tests in tests/codec/ber/test_decoder.py).

@tiran
Copy link

tiran commented Jun 28, 2023

While I have a lot of respect for Ilya, I'm not sure we can say the decision is necessarily right based solely on the fact that it came from him. As your previous comment points out, the decision was made over 3 years ago. It may be a good time to revisit that decision.

Unfortunately Ilya passed away, so we are unable to figure out if the API change was deliberate or a mistake. I can only speculate that he either hadn't noticed the API breakage or he had plans to release new versions of pyasn1 and pysnmp stack at the same time. I agree with you that we should revisit breaking change and attempt to reconcile the API.

Most projects follow semantic versioning. Based on that, I think it is right to consider a breaking change between minor versions to be a bug.

<nit-picker-mode>
FWIW pyasn1 is much older than semantic versioning and never claimed to follow semantic versioning. Besides the breaking change in pyasn1 0.5 is not in violation of semver.

Major version zero (0.y.z) is for initial development. Anything MAY change at any time. The public API SHOULD NOT be considered stable.

</nit-picker-mode>

tl;dr Let's try to address the API breakage, PRs welcome!

haxtibal pushed a commit to haxtibal/pyasn1 that referenced this issue Jul 18, 2023
0.5.0 introduced streaming decoders with new API and decoder.decode was
intended to stay as a compatibility layer. This mostly worked, but
it broke when a substrateFun was used, because substrateFuns are also
expected to be streaming style since 0.5.0. If callers passed a
non-streaming variant, it broke, because of different signature and
semantics.

Now we add a wrapper to 'class Decoder' that converts non-streaming
substrateFuns to streaming ones as part of the compatibiltiy layer.

Fixes pyasn1#28.
haxtibal pushed a commit to haxtibal/pyasn1 that referenced this issue Jul 20, 2023
0.5.0 introduced streaming decoders with new API. decoder.decode() was
meant as a compatibility layer, but API broke anyways if users passed
a custom substrateFun to decoder.decode(). This happened because
substrateFun API and semantics also changed with 0.5.0.

To establish full backwards compatibility, we let decode.decode()
receive a 0.4.8 style non-streaming substrateFun, and transparently
convert it to a streaming substrateFun as expected by the innner
streaming decoders.

Fixes pyasn1#28.
haxtibal pushed a commit to haxtibal/pyasn1 that referenced this issue Jul 20, 2023
testPartialDecodeWithCustomSubstrateFun is inspired by
pysnmp 4.4.12, pysnmp.proto.api.verdec.decodeMessageVersion.

testPartialDecodeWithDefaultSubstrateFun is inspired by pyasn1#28
issuecomment-1518753039.

Both cases broke after pyasn1 0.5.0 was released and now work again.
haxtibal pushed a commit to haxtibal/pyasn1 that referenced this issue Jul 29, 2023
0.5.0 introduced streaming decoders with new API. decoder.decode() was
meant as a compatibility layer, but API broke anyways if users passed
a custom substrateFun to decoder.decode(). This happened because
substrateFun API and semantics also changed with 0.5.0.

To establish full backwards compatibility, we let decode.decode()
receive a v0.4 style non-streaming substrateFun, and transparently
convert it to a streaming substrateFun as expected by the innner
streaming decoders.

Fixes pyasn1#28.
haxtibal pushed a commit to haxtibal/pyasn1 that referenced this issue Jul 29, 2023
testPartialDecodeWithCustomSubstrateFun is inspired by
pysnmp 4.4.12, pysnmp.proto.api.verdec.decodeMessageVersion.

testPartialDecodeWithDefaultSubstrateFun is inspired by pyasn1#28
issuecomment-1518753039.

Both cases broke after pyasn1 0.5.0 was released and now work again.
droideck pushed a commit to haxtibal/pyasn1 that referenced this issue Aug 22, 2023
0.5.0 introduced streaming decoders with new API. decoder.decode() was
meant as a compatibility layer, but API broke anyways if users passed
a custom substrateFun to decoder.decode(). This happened because
substrateFun API and semantics also changed with 0.5.0.

To establish full backwards compatibility, we let decode.decode()
receive a v0.4 style non-streaming substrateFun, and transparently
convert it to a streaming substrateFun as expected by the innner
streaming decoders.

Fixes pyasn1#28.
droideck pushed a commit to haxtibal/pyasn1 that referenced this issue Aug 22, 2023
testPartialDecodeWithCustomSubstrateFun is inspired by
pysnmp 4.4.12, pysnmp.proto.api.verdec.decodeMessageVersion.

testPartialDecodeWithDefaultSubstrateFun is inspired by pyasn1#28
issuecomment-1518753039.

Both cases broke after pyasn1 0.5.0 was released and now work again.
haxtibal pushed a commit to haxtibal/pyasn1 that referenced this issue Sep 15, 2023
0.5.0 introduced streaming decoders with new API. decoder.decode() was
meant as a compatibility layer, but API broke anyways if users passed
a custom substrateFun to decoder.decode(). This happened because
substrateFun API and semantics also changed with 0.5.0.

To establish full backwards compatibility, we let decode.decode()
receive a v0.4 style non-streaming substrateFun, and transparently
convert it to a streaming substrateFun as expected by the innner
streaming decoders.

Fixes pyasn1#28.
haxtibal pushed a commit to haxtibal/pyasn1 that referenced this issue Sep 15, 2023
testPartialDecodeWithCustomSubstrateFun is inspired by
pysnmp 4.4.12, pysnmp.proto.api.verdec.decodeMessageVersion.

testPartialDecodeWithDefaultSubstrateFun is inspired by pyasn1#28
issuecomment-1518753039.

Both cases broke after pyasn1 0.5.0 was released and now work again.
haxtibal pushed a commit to haxtibal/pyasn1 that referenced this issue Sep 17, 2023
0.5.0 introduced streaming decoders with new API. decoder.decode() was
meant as a compatibility layer, but API broke anyways if users passed
a custom substrateFun to decoder.decode(). This happened because
substrateFun API and semantics also changed with 0.5.0.

To establish full backwards compatibility, we let decode.decode()
receive a v0.4 style non-streaming substrateFun, and transparently
convert it to a streaming substrateFun as expected by the innner
streaming decoders.

Fixes pyasn1#28.
haxtibal pushed a commit to haxtibal/pyasn1 that referenced this issue Sep 17, 2023
testPartialDecodeWithCustomSubstrateFun is inspired by
pysnmp 4.4.12, pysnmp.proto.api.verdec.decodeMessageVersion.

testPartialDecodeWithDefaultSubstrateFun is inspired by pyasn1#28
issuecomment-1518753039.

Both cases broke after pyasn1 0.5.0 was released and now work again.
haxtibal pushed a commit to haxtibal/pyasn1 that referenced this issue Nov 7, 2023
0.5.0 introduced streaming decoders with new API. decoder.decode() was
meant as a compatibility layer, but API broke anyways if users passed
a custom substrateFun to decoder.decode(). This happened because
substrateFun API and semantics also changed with 0.5.0.

To establish full backwards compatibility, we let decode.decode()
receive a v0.4 style non-streaming substrateFun, and transparently
convert it to a streaming substrateFun as expected by the innner
streaming decoders.

Fixes pyasn1#28.
haxtibal pushed a commit to haxtibal/pyasn1 that referenced this issue Nov 7, 2023
testPartialDecodeWithCustomSubstrateFun is inspired by
pysnmp 4.4.12, pysnmp.proto.api.verdec.decodeMessageVersion.

testPartialDecodeWithDefaultSubstrateFun is inspired by pyasn1#28
issuecomment-1518753039.

Both cases broke after pyasn1 0.5.0 was released and now work again.
haxtibal pushed a commit to haxtibal/pyasn1 that referenced this issue Nov 9, 2023
0.5.0 introduced streaming decoders with new API. decoder.decode() was
meant as a compatibility layer, but API broke anyways if users passed
a custom substrateFun to decoder.decode(). This happened because
substrateFun API and semantics also changed with 0.5.0.

To establish full backwards compatibility, we let decode.decode()
receive a v0.4 style non-streaming substrateFun, and transparently
convert it to a streaming substrateFun as expected by the innner
streaming decoders.

Fixes pyasn1#28.
haxtibal pushed a commit to haxtibal/pyasn1 that referenced this issue Nov 9, 2023
testPartialDecodeWithCustomSubstrateFun is inspired by
pysnmp 4.4.12, pysnmp.proto.api.verdec.decodeMessageVersion.

testPartialDecodeWithDefaultSubstrateFun is inspired by pyasn1#28
issuecomment-1518753039.

Both cases broke after pyasn1 0.5.0 was released and now work again.
haxtibal pushed a commit to haxtibal/pyasn1 that referenced this issue Nov 10, 2023
0.5.0 introduced streaming decoders with new API. decoder.decode() was
meant as a compatibility layer, but API broke anyways if users passed
a custom substrateFun to decoder.decode(). This happened because
substrateFun API and semantics also changed with 0.5.0.

To establish full backwards compatibility, we now let decode.decode()
accept both v0.4 and v0.5 substrateFuns. v0.4 functions are detected and
automatically wrapped to behave streaming-like. Detection of v0.4 style
works by checking for TypeError stemming from a call with wrong number
of arguments.

The try-except approach was chosen over 'import inspect' for performance
reasons. We avoid to interfere with user code TypeErrors by checking the
traceback depth.

Fixes pyasn1#28.
droideck pushed a commit that referenced this issue Nov 15, 2023
0.5.0 introduced streaming decoders with new API. decoder.decode() was
meant as a compatibility layer, but API broke anyways if users passed
a custom substrateFun to decoder.decode(). This happened because
substrateFun API and semantics also changed with 0.5.0.

To establish full backwards compatibility, we now let decode.decode()
accept both v0.4 and v0.5 substrateFuns. v0.4 functions are detected and
automatically wrapped to behave streaming-like. Detection of v0.4 style
works by checking for TypeError stemming from a call with wrong number
of arguments.

The try-except approach was chosen over 'import inspect' for performance
reasons. We avoid to interfere with user code TypeErrors by checking the
traceback depth.

Fixes #28.
romeroalx pushed a commit to romeroalx/pdns that referenced this issue Nov 17, 2023
romeroalx pushed a commit to romeroalx/pdns that referenced this issue Nov 20, 2023
romeroalx pushed a commit to romeroalx/pdns that referenced this issue Nov 20, 2023
romeroalx pushed a commit to romeroalx/pdns that referenced this issue Nov 20, 2023
romeroalx pushed a commit to romeroalx/pdns that referenced this issue Nov 20, 2023
romeroalx pushed a commit to romeroalx/pdns that referenced this issue Nov 20, 2023
romeroalx pushed a commit to romeroalx/pdns that referenced this issue Nov 20, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

10 participants