From 62412e4cf4bf5466680ac29db4a11cee69ec0a83 Mon Sep 17 00:00:00 2001 From: gpotter2 Date: Fri, 12 Apr 2019 19:18:50 +0200 Subject: [PATCH 1/6] Add AliasField --- scapy/fields.py | 15 +++++++++++++++ scapy/main.py | 14 +++++++++++--- scapy/packet.py | 43 +++++++++++++++++++++++++++++++++++++++---- test/fields.uts | 27 +++++++++++++++++++++++++++ 4 files changed, 92 insertions(+), 7 deletions(-) diff --git a/scapy/fields.py b/scapy/fields.py index 62f81e742f6..90b37c5a16c 100644 --- a/scapy/fields.py +++ b/scapy/fields.py @@ -244,6 +244,21 @@ def __getattr__(self, attr): return getattr(self.fld, attr) +class AliasField(Field): + __slots__ = ["pointer", "deprecated"] + + def __init__(self, name, pointer, deprecated=False): + Field.__init__(self, name, 0, fmt="!") + self.pointer = pointer + self.deprecated = deprecated + + def getfield(self, pkt, s): + return s, None + + def addfield(self, pkt, s, val): + return s + + class MultipleTypeField(object): """MultipleTypeField are used for fields that can be implemented by various Field subclasses, depending on conditions on the packet. diff --git a/scapy/main.py b/scapy/main.py index 433a465b435..371f73b8389 100644 --- a/scapy/main.py +++ b/scapy/main.py @@ -17,10 +17,11 @@ import gzip import glob import importlib +import io import logging -from random import choice import types -import io +import warnings +from random import choice # Never add any global import, in main.py, that would trigger a warning message # noqa: E501 # before the console handlers gets added in interact() @@ -83,7 +84,11 @@ def _read_config_file(cf, _globals=globals(), _locals=locals(), interactive=True """ log_loading.debug("Loading config file [%s]", cf) try: - exec(compile(open(cf).read(), cf, 'exec'), _globals, _locals) + with open(cf) as cfgf: + exec( + compile(cfgf.read(), cf, 'exec'), + _globals, _locals + ) except IOError as e: if interactive: raise @@ -473,6 +478,9 @@ def interact(mydict=None, argv=None, mybanner=None, loglevel=logging.INFO): ) log_scapy.addHandler(console_handler) + # We're in interactive mode, let's throw the DeprecationWarnings + warnings.simplefilter("always") + from scapy.config import conf conf.interactive = True conf.color_theme = DefaultTheme() diff --git a/scapy/packet.py b/scapy/packet.py index c2596480cda..4dc25ae710b 100644 --- a/scapy/packet.py +++ b/scapy/packet.py @@ -14,9 +14,11 @@ import itertools import copy import types +import warnings from scapy.fields import StrField, ConditionalField, Emph, PacketListField, \ - BitField, MultiEnumField, EnumField, FlagsField, MultipleTypeField + BitField, MultiEnumField, EnumField, FlagsField, MultipleTypeField, \ + AliasField from scapy.config import conf, _version_checker from scapy.compat import raw, orb, bytes_encode from scapy.base_classes import BasePacket, Gen, SetGen, Packet_metaclass, \ @@ -51,9 +53,10 @@ def __repr__(self): class Packet(six.with_metaclass(Packet_metaclass, BasePacket, _CanvasDumpExtended)): __slots__ = [ - "time", "sent_time", "name", "default_fields", - "overload_fields", "overloaded_fields", "fields", "fieldtype", - "packetfields", + "time", "sent_time", "name", + "default_fields", "fields", "fieldtype", + "overload_fields", "overloaded_fields", + "packetfields", "alias_fields", "original", "explicit", "raw_packet_cache", "raw_packet_cache_fields", "_pkt", "post_transforms", # then payload and underlayer @@ -80,6 +83,7 @@ class Packet(six.with_metaclass(Packet_metaclass, BasePacket, class_default_fields = dict() class_default_fields_ref = dict() class_fieldtype = dict() + class_alias_fields = dict() @classmethod def from_hexcap(cls): @@ -131,6 +135,7 @@ def __init__(self, _pkt=b"", post_transform=None, _internal=0, _underlayer=None, self.overloaded_fields = {} self.fields = {} self.fieldtype = {} + self.alias_fields = {} self.packetfields = [] self.payload = NoPayload() self.init_fields() @@ -153,6 +158,8 @@ def __init__(self, _pkt=b"", post_transform=None, _internal=0, _underlayer=None, value = fields.pop(fname) except KeyError: continue + if fname in self.alias_fields: + fname = self._resolve_alias(fname) self.fields[fname] = self.get_field(fname).any2i(self, value) # The remaining fields are unknown for fname, _ in fields: @@ -179,6 +186,9 @@ def do_init_fields(self, flist): Initialize each fields of the fields_desc dict """ for f in flist: + if isinstance(f, AliasField): + self.alias_fields[f.name] = (f.pointer, f.deprecated) + continue self.default_fields[f.name] = copy.deepcopy(f.default) self.fieldtype[f.name] = f if f.holds_packets: @@ -201,6 +211,7 @@ def do_init_cached_fields(self): self.default_fields = Packet.class_default_fields[cls_name] self.fieldtype = Packet.class_fieldtype[cls_name] self.packetfields = Packet.class_packetfields[cls_name] + self.alias_fields = Packet.class_alias_fields[cls_name] # Deepcopy default references for fname in Packet.class_default_fields_ref[cls_name]: @@ -223,6 +234,7 @@ def prepare_cached_fields(self, flist): Packet.class_default_fields[cls_name] = dict() Packet.class_default_fields_ref[cls_name] = list() Packet.class_fieldtype[cls_name] = dict() + Packet.class_alias_fields[cls_name] = dict() Packet.class_packetfields[cls_name] = list() # Fields initialization @@ -236,6 +248,12 @@ def prepare_cached_fields(self, flist): self.do_init_fields(self.fields_desc) break + if isinstance(f, AliasField): + self.class_alias_fields[cls_name][f.name] = ( + f.pointer, f.deprecated + ) + continue + tmp_copy = copy.deepcopy(f.default) Packet.class_default_fields[cls_name][f.name] = tmp_copy Packet.class_fieldtype[cls_name][f.name] = f @@ -307,7 +325,18 @@ def copy(self): clone.time = self.time return clone + def _resolve_alias(self, attr): + new_attr, dpr = self.alias_fields[attr] + if dpr: + warnings.warn( + "%s has been deprecated in favor of %s" % (attr, new_attr), + DeprecationWarning + ) + return new_attr + def getfieldval(self, attr): + if attr in self.alias_fields: + attr = self._resolve_alias(attr) if attr in self.fields: return self.fields[attr] if attr in self.overloaded_fields: @@ -317,6 +346,8 @@ def getfieldval(self, attr): return self.payload.getfieldval(attr) def getfield_and_val(self, attr): + if attr in self.alias_fields: + attr = self._resolve_alias(attr) if attr in self.fields: return self.get_field(attr), self.fields[attr] if attr in self.overloaded_fields: @@ -334,6 +365,8 @@ def __getattr__(self, attr): return v def setfieldval(self, attr, val): + if attr in self.alias_fields: + attr = self._resolve_alias(attr) if attr in self.default_fields: fld = self.get_field(attr) if fld is None: @@ -1172,6 +1205,8 @@ def _show_or_dump(self, dump=False, indent=3, lvl="", label_lvl="", first_call=T for f in self.fields_desc: if isinstance(f, ConditionalField) and not f._evalcond(self): continue + if isinstance(f, AliasField): + continue if isinstance(f, Emph) or f in conf.emph: ncol = ct.emph_field_name vcol = ct.emph_field_value diff --git a/test/fields.uts b/test/fields.uts index 0659b0e5073..ce65c1228a7 100644 --- a/test/fields.uts +++ b/test/fields.uts @@ -1809,6 +1809,33 @@ r = m.m2i(None, data_129["str_with_fx"]) assert(r == data_129["extended"]) +############ +############ ++ AliasField + += AliasField: basic test + +class TestPacket(Packet): + fields_desc = [ + ByteField("a", 0), + LEShortField("b", 15), + AliasField("B", "b"), + AliasField("dpr", "a", deprecated=True) + ] + +pkt = TestPacket(a=2, B=3) +assert pkt.B == 3 +assert pkt.b == 3 +assert pkt.a == 2 + +import warnings + +with warnings.catch_warnings(record=True) as w: + warnings.simplefilter("always") + assert pkt.dpr == 2 + assert len(w) == 1 + assert issubclass(w[-1].category, DeprecationWarning) + ############ ############ + FCSField From 86f106ea49ecc21c10f04cd917e35aecb163b4a6 Mon Sep 17 00:00:00 2001 From: gpotter2 Date: Wed, 17 Apr 2019 17:24:03 +0200 Subject: [PATCH 2/6] Alias/Deprecation v2 --- scapy/fields.py | 15 --------------- scapy/packet.py | 37 +++++++++++++------------------------ test/fields.uts | 12 ++++++++---- 3 files changed, 21 insertions(+), 43 deletions(-) diff --git a/scapy/fields.py b/scapy/fields.py index 90b37c5a16c..62f81e742f6 100644 --- a/scapy/fields.py +++ b/scapy/fields.py @@ -244,21 +244,6 @@ def __getattr__(self, attr): return getattr(self.fld, attr) -class AliasField(Field): - __slots__ = ["pointer", "deprecated"] - - def __init__(self, name, pointer, deprecated=False): - Field.__init__(self, name, 0, fmt="!") - self.pointer = pointer - self.deprecated = deprecated - - def getfield(self, pkt, s): - return s, None - - def addfield(self, pkt, s, val): - return s - - class MultipleTypeField(object): """MultipleTypeField are used for fields that can be implemented by various Field subclasses, depending on conditions on the packet. diff --git a/scapy/packet.py b/scapy/packet.py index 4dc25ae710b..c9854c70f78 100644 --- a/scapy/packet.py +++ b/scapy/packet.py @@ -17,8 +17,7 @@ import warnings from scapy.fields import StrField, ConditionalField, Emph, PacketListField, \ - BitField, MultiEnumField, EnumField, FlagsField, MultipleTypeField, \ - AliasField + BitField, MultiEnumField, EnumField, FlagsField, MultipleTypeField from scapy.config import conf, _version_checker from scapy.compat import raw, orb, bytes_encode from scapy.base_classes import BasePacket, Gen, SetGen, Packet_metaclass, \ @@ -56,7 +55,7 @@ class Packet(six.with_metaclass(Packet_metaclass, BasePacket, "time", "sent_time", "name", "default_fields", "fields", "fieldtype", "overload_fields", "overloaded_fields", - "packetfields", "alias_fields", + "packetfields", "original", "explicit", "raw_packet_cache", "raw_packet_cache_fields", "_pkt", "post_transforms", # then payload and underlayer @@ -73,6 +72,7 @@ class Packet(six.with_metaclass(Packet_metaclass, BasePacket, ] name = None fields_desc = [] + alias_fields = None overload_fields = {} payload_guess = [] show_indent = 1 @@ -83,7 +83,6 @@ class Packet(six.with_metaclass(Packet_metaclass, BasePacket, class_default_fields = dict() class_default_fields_ref = dict() class_fieldtype = dict() - class_alias_fields = dict() @classmethod def from_hexcap(cls): @@ -135,7 +134,6 @@ def __init__(self, _pkt=b"", post_transform=None, _internal=0, _underlayer=None, self.overloaded_fields = {} self.fields = {} self.fieldtype = {} - self.alias_fields = {} self.packetfields = [] self.payload = NoPayload() self.init_fields() @@ -158,11 +156,15 @@ def __init__(self, _pkt=b"", post_transform=None, _internal=0, _underlayer=None, value = fields.pop(fname) except KeyError: continue - if fname in self.alias_fields: - fname = self._resolve_alias(fname) self.fields[fname] = self.get_field(fname).any2i(self, value) # The remaining fields are unknown - for fname, _ in fields: + for fname in fields: + if self.alias_fields and fname in self.alias_fields: + # Resolve deprecated fields + value = fields[fname] + fname = self._resolve_alias(fname) + self.fields[fname] = self.get_field(fname).any2i(self, value) + continue raise AttributeError(fname) if isinstance(post_transform, list): self.post_transforms = post_transform @@ -186,9 +188,6 @@ def do_init_fields(self, flist): Initialize each fields of the fields_desc dict """ for f in flist: - if isinstance(f, AliasField): - self.alias_fields[f.name] = (f.pointer, f.deprecated) - continue self.default_fields[f.name] = copy.deepcopy(f.default) self.fieldtype[f.name] = f if f.holds_packets: @@ -211,7 +210,6 @@ def do_init_cached_fields(self): self.default_fields = Packet.class_default_fields[cls_name] self.fieldtype = Packet.class_fieldtype[cls_name] self.packetfields = Packet.class_packetfields[cls_name] - self.alias_fields = Packet.class_alias_fields[cls_name] # Deepcopy default references for fname in Packet.class_default_fields_ref[cls_name]: @@ -234,7 +232,6 @@ def prepare_cached_fields(self, flist): Packet.class_default_fields[cls_name] = dict() Packet.class_default_fields_ref[cls_name] = list() Packet.class_fieldtype[cls_name] = dict() - Packet.class_alias_fields[cls_name] = dict() Packet.class_packetfields[cls_name] = list() # Fields initialization @@ -248,12 +245,6 @@ def prepare_cached_fields(self, flist): self.do_init_fields(self.fields_desc) break - if isinstance(f, AliasField): - self.class_alias_fields[cls_name][f.name] = ( - f.pointer, f.deprecated - ) - continue - tmp_copy = copy.deepcopy(f.default) Packet.class_default_fields[cls_name][f.name] = tmp_copy Packet.class_fieldtype[cls_name][f.name] = f @@ -335,7 +326,7 @@ def _resolve_alias(self, attr): return new_attr def getfieldval(self, attr): - if attr in self.alias_fields: + if self.alias_fields and attr in self.alias_fields: attr = self._resolve_alias(attr) if attr in self.fields: return self.fields[attr] @@ -346,7 +337,7 @@ def getfieldval(self, attr): return self.payload.getfieldval(attr) def getfield_and_val(self, attr): - if attr in self.alias_fields: + if self.alias_fields and attr in self.alias_fields: attr = self._resolve_alias(attr) if attr in self.fields: return self.get_field(attr), self.fields[attr] @@ -365,7 +356,7 @@ def __getattr__(self, attr): return v def setfieldval(self, attr, val): - if attr in self.alias_fields: + if self.alias_fields and attr in self.alias_fields: attr = self._resolve_alias(attr) if attr in self.default_fields: fld = self.get_field(attr) @@ -1205,8 +1196,6 @@ def _show_or_dump(self, dump=False, indent=3, lvl="", label_lvl="", first_call=T for f in self.fields_desc: if isinstance(f, ConditionalField) and not f._evalcond(self): continue - if isinstance(f, AliasField): - continue if isinstance(f, Emph) or f in conf.emph: ncol = ct.emph_field_name vcol = ct.emph_field_value diff --git a/test/fields.uts b/test/fields.uts index ce65c1228a7..b2fb56261b9 100644 --- a/test/fields.uts +++ b/test/fields.uts @@ -1811,17 +1811,20 @@ assert(r == data_129["extended"]) ############ ############ -+ AliasField ++ Aliases in Packet +~ alias -= AliasField: basic test += Aliases: Deprecation test class TestPacket(Packet): fields_desc = [ ByteField("a", 0), LEShortField("b", 15), - AliasField("B", "b"), - AliasField("dpr", "a", deprecated=True) ] + alias_fields = { + "dpr": ["a", True], + "B": ["b", False] + } pkt = TestPacket(a=2, B=3) assert pkt.B == 3 @@ -1836,6 +1839,7 @@ with warnings.catch_warnings(record=True) as w: assert len(w) == 1 assert issubclass(w[-1].category, DeprecationWarning) + ############ ############ + FCSField From 7edd90f9e98ed2b64676170b56f452b641a744b3 Mon Sep 17 00:00:00 2001 From: gpotter2 Date: Wed, 17 Apr 2019 18:01:17 +0200 Subject: [PATCH 3/6] Force Deprecation warnings --- scapy/packet.py | 21 ++++++++++----------- test/fields.uts | 12 ++++++------ 2 files changed, 16 insertions(+), 17 deletions(-) diff --git a/scapy/packet.py b/scapy/packet.py index c9854c70f78..ae3e5ee6a7a 100644 --- a/scapy/packet.py +++ b/scapy/packet.py @@ -72,7 +72,7 @@ class Packet(six.with_metaclass(Packet_metaclass, BasePacket, ] name = None fields_desc = [] - alias_fields = None + deprecated_fields = None overload_fields = {} payload_guess = [] show_indent = 1 @@ -159,7 +159,7 @@ def __init__(self, _pkt=b"", post_transform=None, _internal=0, _underlayer=None, self.fields[fname] = self.get_field(fname).any2i(self, value) # The remaining fields are unknown for fname in fields: - if self.alias_fields and fname in self.alias_fields: + if self.deprecated_fields and fname in self.deprecated_fields: # Resolve deprecated fields value = fields[fname] fname = self._resolve_alias(fname) @@ -317,16 +317,15 @@ def copy(self): return clone def _resolve_alias(self, attr): - new_attr, dpr = self.alias_fields[attr] - if dpr: - warnings.warn( - "%s has been deprecated in favor of %s" % (attr, new_attr), - DeprecationWarning - ) + new_attr = self.deprecated_fields[attr] + warnings.warn( + "%s has been deprecated in favor of %s" % (attr, new_attr), + DeprecationWarning + ) return new_attr def getfieldval(self, attr): - if self.alias_fields and attr in self.alias_fields: + if self.deprecated_fields and attr in self.deprecated_fields: attr = self._resolve_alias(attr) if attr in self.fields: return self.fields[attr] @@ -337,7 +336,7 @@ def getfieldval(self, attr): return self.payload.getfieldval(attr) def getfield_and_val(self, attr): - if self.alias_fields and attr in self.alias_fields: + if self.deprecated_fields and attr in self.deprecated_fields: attr = self._resolve_alias(attr) if attr in self.fields: return self.get_field(attr), self.fields[attr] @@ -356,7 +355,7 @@ def __getattr__(self, attr): return v def setfieldval(self, attr, val): - if self.alias_fields and attr in self.alias_fields: + if self.deprecated_fields and attr in self.deprecated_fields: attr = self._resolve_alias(attr) if attr in self.default_fields: fld = self.get_field(attr) diff --git a/test/fields.uts b/test/fields.uts index b2fb56261b9..069484b2156 100644 --- a/test/fields.uts +++ b/test/fields.uts @@ -1811,19 +1811,19 @@ assert(r == data_129["extended"]) ############ ############ -+ Aliases in Packet -~ alias ++ Deprecated fields in Packet +~ deprecated -= Aliases: Deprecation test += Field Deprecation test class TestPacket(Packet): fields_desc = [ ByteField("a", 0), LEShortField("b", 15), ] - alias_fields = { - "dpr": ["a", True], - "B": ["b", False] + deprecated_fields = { + "dpr": "a", + "B": "b", } pkt = TestPacket(a=2, B=3) From b913c7ba03060007c22c6c4f9fd170a4cfc5ee53 Mon Sep 17 00:00:00 2001 From: gpotter2 Date: Thu, 23 May 2019 17:43:22 +0200 Subject: [PATCH 4/6] Update RadioTap fields name for consistency --- scapy/layers/dot11.py | 13 +++++++++---- test/regression.uts | 1 + 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/scapy/layers/dot11.py b/scapy/layers/dot11.py index 397d4ff8d52..f1b924db026 100644 --- a/scapy/layers/dot11.py +++ b/scapy/layers/dot11.py @@ -247,6 +247,11 @@ def guess_payload_class(self, pay): class RadioTap(Packet): name = "RadioTap dummy" + deprecated_fields = { + "Channel": "ChannelFrequency", # 2.4.3 + "ChannelFlags2": "ChannelPlusFlags", # 2.4.3 + "ChannelNumber": "ChannelPlusNumber" # 2.4.3 + } fields_desc = [ ByteField('version', 0), ByteField('pad', 0), @@ -278,7 +283,7 @@ class RadioTap(Packet): # Channel ConditionalField( _RadiotapReversePadField( - LEShortField("Channel", 0) + LEShortField("ChannelFrequency", 0) ), lambda pkt: pkt.present and pkt.present.Channel), ConditionalField( @@ -323,14 +328,14 @@ class RadioTap(Packet): # ChannelPlus ConditionalField( _RadiotapReversePadField( - FlagsField("ChannelFlags2", None, -32, _rt_channelflags2) + FlagsField("ChannelPlusFlags", None, -32, _rt_channelflags2) ), lambda pkt: pkt.present and pkt.present.ChannelPlus), ConditionalField( - LEShortField("ChannelFrequency", 0), + LEShortField("ChannelPlusFrequency", 0), lambda pkt: pkt.present and pkt.present.ChannelPlus), ConditionalField( - ByteField("ChannelNumber", 0), + ByteField("ChannelPlusNumber", 0), lambda pkt: pkt.present and pkt.present.ChannelPlus), # MCS ConditionalField( diff --git a/test/regression.uts b/test/regression.uts index 07c08b5efc4..bfcb5f141cd 100644 --- a/test/regression.uts +++ b/test/regression.uts @@ -1076,6 +1076,7 @@ r = RadioTap(data) r = RadioTap(raw(r)) assert r.dBm_AntSignal == -59 assert r.ChannelFrequency == 5785 +assert r.ChannelPlusFrequency == 5785 assert r.present == 3410027 assert r.A_MPDU_ref == 2821 assert r.KnownVHT == 511 From 76fa84510c62f34a0d00d339312aa34eed6cf007 Mon Sep 17 00:00:00 2001 From: gpotter2 Date: Tue, 25 Jun 2019 15:09:08 +0200 Subject: [PATCH 5/6] Add version tag --- scapy/layers/dot11.py | 6 +++--- scapy/packet.py | 7 ++++--- test/fields.uts | 4 ++-- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/scapy/layers/dot11.py b/scapy/layers/dot11.py index f1b924db026..ab18230a95c 100644 --- a/scapy/layers/dot11.py +++ b/scapy/layers/dot11.py @@ -248,9 +248,9 @@ def guess_payload_class(self, pay): class RadioTap(Packet): name = "RadioTap dummy" deprecated_fields = { - "Channel": "ChannelFrequency", # 2.4.3 - "ChannelFlags2": "ChannelPlusFlags", # 2.4.3 - "ChannelNumber": "ChannelPlusNumber" # 2.4.3 + "Channel": ("ChannelFrequency", "2.4.3"), + "ChannelFlags2": ("ChannelPlusFlags", "2.4.3"), + "ChannelNumber": ("ChannelPlusNumber", "2.4.3"), } fields_desc = [ ByteField('version', 0), diff --git a/scapy/packet.py b/scapy/packet.py index ae3e5ee6a7a..a4711d24282 100644 --- a/scapy/packet.py +++ b/scapy/packet.py @@ -317,10 +317,11 @@ def copy(self): return clone def _resolve_alias(self, attr): - new_attr = self.deprecated_fields[attr] + new_attr, version = self.deprecated_fields[attr] warnings.warn( - "%s has been deprecated in favor of %s" % (attr, new_attr), - DeprecationWarning + "%s has been deprecated in favor of %s since %s !" % ( + attr, new_attr, version + ), DeprecationWarning ) return new_attr diff --git a/test/fields.uts b/test/fields.uts index 069484b2156..87e0d630b3f 100644 --- a/test/fields.uts +++ b/test/fields.uts @@ -1822,8 +1822,8 @@ class TestPacket(Packet): LEShortField("b", 15), ] deprecated_fields = { - "dpr": "a", - "B": "b", + "dpr": ("a", "1.0"), + "B": ("b", "1.0"), } pkt = TestPacket(a=2, B=3) From 32d22d57fc0bd7d570c1c184c0a812d110a5eb4d Mon Sep 17 00:00:00 2001 From: Gabriel Date: Tue, 25 Jun 2019 18:14:49 +0200 Subject: [PATCH 6/6] Simplification Co-Authored-By: Pierre Lalet --- scapy/packet.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scapy/packet.py b/scapy/packet.py index a4711d24282..1cfe85c5894 100644 --- a/scapy/packet.py +++ b/scapy/packet.py @@ -72,7 +72,7 @@ class Packet(six.with_metaclass(Packet_metaclass, BasePacket, ] name = None fields_desc = [] - deprecated_fields = None + deprecated_fields = {} overload_fields = {} payload_guess = [] show_indent = 1 @@ -159,7 +159,7 @@ def __init__(self, _pkt=b"", post_transform=None, _internal=0, _underlayer=None, self.fields[fname] = self.get_field(fname).any2i(self, value) # The remaining fields are unknown for fname in fields: - if self.deprecated_fields and fname in self.deprecated_fields: + if fname in self.deprecated_fields: # Resolve deprecated fields value = fields[fname] fname = self._resolve_alias(fname)