Skip to content

Commit b49af41

Browse files
akshaycborguedou
authored andcommitted
#2158 - Add Hinty for plist.py - Adds mypy from Issue #2158 (#2358)
* #2158 - Add Hinty for plist.py * Import MATPLOTLIB from extlib.py * Add Line2D and update for review comments * Add regression test changes for new matplotlib.lines import * Remove unnecessary space * Add new line to restart appveyer build
1 parent 3ad5b80 commit b49af41

File tree

5 files changed

+75
-20
lines changed

5 files changed

+75
-20
lines changed

.config/mypy/mypy.ini

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,10 @@ ignore_missing_imports = True
1212
[mypy-scapy.modules.six,scapy.modules.six.moves,scapy.libs.winpcapy]
1313
ignore_errors = True
1414
ignore_missing_imports = True
15+
16+
[mypy-pyx]
17+
ignore_missing_imports = True
18+
19+
[mypy-matplotlib.lines]
20+
ignore_missing_imports = True
21+

.config/mypy/mypy_enabled.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,5 @@
66

77
scapy/__init__.py
88
scapy/main.py
9-
scapy/contrib/http2.py
9+
scapy/contrib/http2.py
10+
scapy/plist.py

scapy/extlib.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
try:
2121
from matplotlib import get_backend as matplotlib_get_backend
2222
from matplotlib import pyplot as plt
23+
from matplotlib.lines import Line2D
2324
MATPLOTLIB = 1
2425
if "inline" in matplotlib_get_backend():
2526
MATPLOTLIB_INLINED = 1
@@ -29,6 +30,7 @@
2930
# RuntimeError to catch gtk "Cannot open display" error
3031
except (ImportError, RuntimeError):
3132
plt = None
33+
Line2D = None
3234
MATPLOTLIB = 0
3335
MATPLOTLIB_INLINED = 0
3436
MATPLOTLIB_DEFAULT_PLOT_KARGS = dict()

scapy/plist.py

Lines changed: 56 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,16 @@
1616
from scapy.compat import lambda_tuple_converter
1717
from scapy.config import conf
1818
from scapy.base_classes import BasePacket, BasePacketList, _CanvasDumpExtended
19+
from scapy.fields import IPField, ShortEnumField, PacketField
1920
from scapy.utils import do_graph, hexdump, make_table, make_lined_table, \
2021
make_tex_table, issubtype
21-
from scapy.extlib import plt, MATPLOTLIB_INLINED, MATPLOTLIB_DEFAULT_PLOT_KARGS
22+
from scapy.extlib import plt, Line2D, \
23+
MATPLOTLIB_INLINED, MATPLOTLIB_DEFAULT_PLOT_KARGS
2224
from functools import reduce
2325
import scapy.modules.six as six
2426
from scapy.modules.six.moves import range, zip
25-
27+
from scapy.compat import Optional, List, Union, Tuple, Dict, Any, Callable
28+
from scapy.packet import Packet
2629
#############
2730
# Results #
2831
#############
@@ -46,18 +49,23 @@ def __init__(self, res=None, name="PacketList", stats=None):
4649
self.listname = name
4750

4851
def __len__(self):
52+
# type: () -> int
4953
return len(self.res)
5054

5155
def _elt2pkt(self, elt):
56+
# type: (Packet) -> Packet
5257
return elt
5358

5459
def _elt2sum(self, elt):
60+
# type: (Packet) -> str
5561
return elt.summary()
5662

5763
def _elt2show(self, elt):
64+
# type: (Packet) -> str
5865
return self._elt2sum(elt)
5966

6067
def __repr__(self):
68+
# type: () -> str
6169
stats = {x: 0 for x in self.stats}
6270
other = 0
6371
for r in self.res:
@@ -85,6 +93,7 @@ def __repr__(self):
8593
ct.punct(">"))
8694

8795
def __getstate__(self):
96+
# type: () -> Dict[str, Union[List[PacketField], List[Packet], str]]
8897
"""
8998
Creates a basic representation of the instance, used in
9099
conjunction with __setstate__() e.g. by pickle
@@ -99,6 +108,7 @@ def __getstate__(self):
99108
return state
100109

101110
def __setstate__(self, state):
111+
# type: (Dict[str, Union[List[PacketField], List[Packet], str]]) -> None # noqa: E501
102112
"""
103113
Sets instance attributes to values given by state, used in
104114
conjunction with __getstate__() e.g. by pickle
@@ -110,6 +120,7 @@ def __setstate__(self, state):
110120
self.listname = state['listname']
111121

112122
def __getattr__(self, attr):
123+
# type: (str) -> Any
113124
return getattr(self.res, attr)
114125

115126
def __getitem__(self, item):
@@ -122,10 +133,12 @@ def __getitem__(self, item):
122133
return self.res.__getitem__(item)
123134

124135
def __add__(self, other):
136+
# type: (PacketList) -> PacketList
125137
return self.__class__(self.res + other.res,
126138
name="%s+%s" % (self.listname, other.listname))
127139

128140
def summary(self, prn=None, lfilter=None):
141+
# type: (Optional[Callable], Optional[Callable]) -> None
129142
"""prints a summary of each packet
130143
131144
:param prn: function to apply to each packet instead of
@@ -143,6 +156,7 @@ def summary(self, prn=None, lfilter=None):
143156
print(prn(r))
144157

145158
def nsummary(self, prn=None, lfilter=None):
159+
# type: (Optional[Callable], Optional[Callable]) -> None
146160
"""prints a summary of each packet with the packet's number
147161
148162
:param prn: function to apply to each packet instead of
@@ -165,29 +179,35 @@ def display(self): # Deprecated. Use show()
165179
self.show()
166180

167181
def show(self, *args, **kargs):
182+
# type: (Any, Any) -> None
168183
"""Best way to display the packet list. Defaults to nsummary() method""" # noqa: E501
169184
return self.nsummary(*args, **kargs)
170185

171186
def filter(self, func):
187+
# type: (Callable) -> PacketList
172188
"""Returns a packet list filtered by a truth function. This truth
173189
function has to take a packet as the only argument and return a boolean value.""" # noqa: E501
174190
return self.__class__([x for x in self.res if func(x)],
175191
name="filtered %s" % self.listname)
176192

177193
def make_table(self, *args, **kargs):
194+
# type: (Any, Any) -> None
178195
"""Prints a table using a function that returns for each packet its head column value, head row value and displayed value # noqa: E501
179196
ex: p.make_table(lambda x:(x[IP].dst, x[TCP].dport, x[TCP].sprintf("%flags%")) """ # noqa: E501
180197
return make_table(self.res, *args, **kargs)
181198

182199
def make_lined_table(self, *args, **kargs):
200+
# type: (Any, Any) -> None
183201
"""Same as make_table, but print a table with lines"""
184202
return make_lined_table(self.res, *args, **kargs)
185203

186204
def make_tex_table(self, *args, **kargs):
205+
# type: (Any, Any) -> None
187206
"""Same as make_table, but print a table with LaTeX syntax"""
188207
return make_tex_table(self.res, *args, **kargs)
189208

190209
def plot(self, f, lfilter=None, plot_xy=False, **kargs):
210+
# type: (Callable, Optional[Callable], bool, Any) -> Line2D
191211
"""Applies a function to each packet to get a value that will be plotted
192212
with matplotlib. A list of matplotlib.lines.Line2D is returned.
193213
@@ -219,6 +239,7 @@ def plot(self, f, lfilter=None, plot_xy=False, **kargs):
219239
return lines
220240

221241
def diffplot(self, f, delay=1, lfilter=None, **kargs):
242+
# type: (Callable, int, Optional[Callable], Any) -> Line2D
222243
"""diffplot(f, delay=1, lfilter=None)
223244
Applies a function to couples (l[i],l[i+delay])
224245
@@ -246,6 +267,7 @@ def diffplot(self, f, delay=1, lfilter=None, **kargs):
246267
return lines
247268

248269
def multiplot(self, f, lfilter=None, plot_xy=False, **kargs):
270+
# type: (Callable, Optional[Callable], bool, Any) -> Line2D
249271
"""Uses a function that returns a label and a value for this label, then
250272
plots all the values label by label.
251273
@@ -263,7 +285,7 @@ def multiplot(self, f, lfilter=None, plot_xy=False, **kargs):
263285
lst_pkts = (f(*e) for e in self.res if lfilter(*e))
264286

265287
# Apply the function f to the packets
266-
d = {}
288+
d = {} # type: Dict[str, List[float]]
267289
for k, v in lst_pkts:
268290
d.setdefault(k, []).append(v)
269291

@@ -286,11 +308,13 @@ def multiplot(self, f, lfilter=None, plot_xy=False, **kargs):
286308
return lines
287309

288310
def rawhexdump(self):
311+
# type: (Optional[Callable]) -> None
289312
"""Prints an hexadecimal dump of each packet in the list"""
290313
for p in self:
291314
hexdump(self._elt2pkt(p))
292315

293316
def hexraw(self, lfilter=None):
317+
# type: (Optional[Callable]) -> None
294318
"""Same as nsummary(), except that if a packet has a Raw layer, it will be hexdumped # noqa: E501
295319
lfilter: a truth function that decides whether a packet must be displayed""" # noqa: E501
296320
for i, res in enumerate(self.res):
@@ -304,6 +328,7 @@ def hexraw(self, lfilter=None):
304328
hexdump(p.getlayer(conf.raw_layer).load)
305329

306330
def hexdump(self, lfilter=None):
331+
# type: (Optional[Callable]) -> None
307332
"""Same as nsummary(), except that packets are also hexdumped
308333
lfilter: a truth function that decides whether a packet must be displayed""" # noqa: E501
309334
for i, res in enumerate(self.res):
@@ -316,6 +341,7 @@ def hexdump(self, lfilter=None):
316341
hexdump(p)
317342

318343
def padding(self, lfilter=None):
344+
# type: (Optional[Callable]) -> None
319345
"""Same as hexraw(), for Padding layer"""
320346
for i, res in enumerate(self.res):
321347
p = self._elt2pkt(res)
@@ -327,6 +353,7 @@ def padding(self, lfilter=None):
327353
hexdump(p.getlayer(conf.padding_layer).load)
328354

329355
def nzpadding(self, lfilter=None):
356+
# type: (Optional[Callable]) -> None
330357
"""Same as padding() but only non null padding"""
331358
for i, res in enumerate(self.res):
332359
p = self._elt2pkt(res)
@@ -389,6 +416,7 @@ def getsrcdst(pkt):
389416
return do_graph(gr, **kargs)
390417

391418
def afterglow(self, src=None, event=None, dst=None, **kargs):
419+
# type: (Optional[Callable], Optional[Callable], Optional[Callable], Any) -> None # noqa: E501
392420
"""Experimental clone attempt of http://sourceforge.net/projects/afterglow
393421
each datum is reduced as src -> event -> dst and the data are graphed.
394422
by default we have IP.src -> IP.dport -> IP.dst"""
@@ -398,9 +426,9 @@ def afterglow(self, src=None, event=None, dst=None, **kargs):
398426
event = lambda x: x['IP'].dport
399427
if dst is None:
400428
dst = lambda x: x['IP'].dst
401-
sl = {}
402-
el = {}
403-
dl = {}
429+
sl = {} # type: Dict[IPField, Tuple[int, List[ShortEnumField]]]
430+
el = {} # type: Dict[ShortEnumField, Tuple[int, List[IPField]]]
431+
dl = {} # type: Dict[IPField, ShortEnumField]
404432
for i in self.res:
405433
try:
406434
s, e, d = src(i), event(i), dst(i)
@@ -468,6 +496,7 @@ def minmax(x):
468496
return do_graph(gr, **kargs)
469497

470498
def canvas_dump(self, **kargs):
499+
# type: (Any) -> Any # Using Any since pyx is imported later
471500
import pyx
472501
d = pyx.document.document()
473502
len_res = len(self.res)
@@ -483,6 +512,7 @@ def canvas_dump(self, **kargs):
483512
return d
484513

485514
def sr(self, multi=0):
515+
# type: (int) -> Tuple[SndRcvList, PacketList]
486516
"""sr([multi=1]) -> (SndRcvList, PacketList)
487517
Matches packets in the list and return ( (matched couples), (unmatched packets) )""" # noqa: E501
488518
remain = self.res[:]
@@ -545,6 +575,7 @@ def session_extractor(p):
545575
return dict(sessions)
546576

547577
def replace(self, *args, **kargs):
578+
# type: (Any, Any) -> PacketList
548579
"""
549580
lst.replace(<field>,[<oldvalue>,]<newvalue>)
550581
lst.replace( (fld,[ov],nv),(fld,[ov,]nv),...)
@@ -577,7 +608,13 @@ def replace(self, *args, **kargs):
577608
x.append(p)
578609
return x
579610

580-
def getlayer(self, cls, nb=None, flt=None, name=None, stats=None):
611+
def getlayer(self, cls, # type: Packet
612+
nb=None, # type: Optional[int]
613+
flt=None, # type: Optional[Dict[str, Any]]
614+
name=None, # type: Optional[str]
615+
stats=None # type: Optional[List[Packet]]
616+
):
617+
# type: (...) -> PacketList
581618
"""Returns the packet list from a given layer.
582619
583620
See ``Packet.getlayer`` for more info.
@@ -604,7 +641,7 @@ def getlayer(self, cls, nb=None, flt=None, name=None, stats=None):
604641
if stats is None:
605642
stats = self.stats
606643

607-
getlayer_arg = {}
644+
getlayer_arg = {} # type: Dict[str, Any]
608645
if flt is not None:
609646
getlayer_arg.update(flt)
610647
getlayer_arg['cls'] = cls
@@ -619,6 +656,7 @@ def getlayer(self, cls, nb=None, flt=None, name=None, stats=None):
619656
)
620657

621658
def convert_to(self, other_cls, name=None, stats=None):
659+
# type: (Packet, Optional[str], Optional[List[Packet]]) -> PacketList
622660
"""Converts all packets to another type.
623661
624662
See ``Packet.convert_to`` for more info.
@@ -648,13 +686,20 @@ def convert_to(self, other_cls, name=None, stats=None):
648686

649687

650688
class SndRcvList(PacketList):
651-
__slots__ = []
652-
653-
def __init__(self, res=None, name="Results", stats=None):
689+
__slots__ = [] # type: List[str]
690+
691+
def __init__(self,
692+
res=None, # type: Optional[Union[List[Packet], PacketList]]
693+
name="Results", # type: str
694+
stats=None # type: Optional[List[Packet]]
695+
):
696+
# type: (...) -> None
654697
PacketList.__init__(self, res, name, stats)
655698

656699
def _elt2pkt(self, elt):
700+
# type: (Tuple[Packet, Packet]) -> Packet
657701
return elt[1]
658702

659703
def _elt2sum(self, elt):
704+
# type: (Tuple[Packet, Packet]) -> str
660705
return "%s ==> %s" % (elt[0].summary(), elt[1].summary())

test/regression.uts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -680,18 +680,18 @@ from mock import MagicMock, patch
680680
bck_scapy_ext_lib = sys.modules.get("scapy.extlib", None)
681681
del(sys.modules["scapy.extlib"])
682682

683-
matplotlib = MagicMock()
684-
matplotlib.get_backend.return_value = "inline"
685-
matplotlib.pyplot = MagicMock()
686-
matplotlib.pyplot.plt = None
687-
with patch.dict("sys.modules", matplotlib=matplotlib):
688-
from scapy.extlib import MATPLOTLIB, MATPLOTLIB_INLINED, MATPLOTLIB_DEFAULT_PLOT_KARGS
683+
mock_matplotlib = MagicMock()
684+
mock_matplotlib.get_backend.return_value = "inline"
685+
mock_matplotlib.pyplot = MagicMock()
686+
mock_matplotlib.pyplot.plt = None
687+
with patch.dict("sys.modules", **{ "matplotlib": mock_matplotlib, "matplotlib.lines": mock_matplotlib}):
688+
from scapy.extlib import MATPLOTLIB, MATPLOTLIB_INLINED, MATPLOTLIB_DEFAULT_PLOT_KARGS, Line2D
689689
assert MATPLOTLIB == 1
690690
assert MATPLOTLIB_INLINED == 1
691691
assert "marker" in MATPLOTLIB_DEFAULT_PLOT_KARGS
692692

693-
matplotlib.get_backend.return_value = "ko"
694-
with patch.dict("sys.modules", matplotlib=matplotlib):
693+
mock_matplotlib.get_backend.return_value = "ko"
694+
with patch.dict("sys.modules", **{ "matplotlib": mock_matplotlib, "matplotlib.lines": mock_matplotlib}):
695695
from scapy.extlib import MATPLOTLIB, MATPLOTLIB_INLINED, MATPLOTLIB_DEFAULT_PLOT_KARGS
696696
assert MATPLOTLIB == 1
697697
assert MATPLOTLIB_INLINED == 0

0 commit comments

Comments
 (0)