From 431b04a95da67282a59bdf0a1898e106b18814d0 Mon Sep 17 00:00:00 2001
From: gpotter2 <gpotter2@users.noreply.github.com>
Date: Tue, 3 Jan 2017 15:25:17 +0100
Subject: [PATCH] [Windows] Fix import loops (#435)

---
 scapy/arch/__init__.py              | 42 ++++++++---------------------
 scapy/arch/bpf/core.py              |  2 +-
 scapy/arch/bpf/supersocket.py       |  2 +-
 scapy/arch/linux.py                 |  2 +-
 scapy/arch/unix.py                  |  2 +-
 scapy/arch/windows/__init__.py      |  3 +--
 scapy/arch/windows/compatibility.py |  8 +++---
 scapy/{arch => }/consts.py          | 30 ++++++++++++++++++++-
 scapy/layers/l2.py                  |  2 +-
 scapy/plist.py                      |  3 +--
 scapy/route.py                      |  2 +-
 scapy/sendrecv.py                   |  2 +-
 scapy/tools/UTscapy.py              |  2 +-
 13 files changed, 54 insertions(+), 48 deletions(-)
 rename scapy/{arch => }/consts.py (55%)

diff --git a/scapy/arch/__init__.py b/scapy/arch/__init__.py
index 496d255a..949303dd 100644
--- a/scapy/arch/__init__.py
+++ b/scapy/arch/__init__.py
@@ -9,41 +9,16 @@ Operating system specific functionality.
 
 import socket
 
-from scapy.arch.consts import LINUX, OPENBSD, FREEBSD, NETBSD, DARWIN, \
-    SOLARIS, WINDOWS, BSD, X86_64, ARM_64, LOOPBACK_NAME
+from scapy.consts import LINUX, OPENBSD, FREEBSD, NETBSD, DARWIN, \
+    SOLARIS, WINDOWS, BSD, X86_64, ARM_64, LOOPBACK_NAME, plt, MATPLOTLIB_INLINED, \
+    MATPLOTLIB_DEFAULT_PLOT_KARGS, PYX, parent_function
 from scapy.error import *
 import scapy.config
 from scapy.pton_ntop import inet_pton
 
-try:
-    from matplotlib import get_backend as matplotlib_get_backend
-    import matplotlib.pyplot as plt
-    MATPLOTLIB = 1
-    if "inline" in matplotlib_get_backend():
-        MATPLOTLIB_INLINED = 1
-    else:
-        MATPLOTLIB_INLINED = 0
-    MATPLOTLIB_DEFAULT_PLOT_KARGS = {"marker": "+"}
-# RuntimeError to catch gtk "Cannot open display" error
-except (ImportError, RuntimeError):
-    plt = None
-    MATPLOTLIB = 0
-    MATPLOTLIB_INLINED = 0
-    MATPLOTLIB_DEFAULT_PLOT_KARGS = dict()
-    log_loading.info("Can't import matplotlib. Won't be able to plot.")
-
-try:
-    import pyx
-    PYX=1
-except ImportError:
-    log_loading.info("Can't import PyX. Won't be able to use psdump() or pdfdump().")
-    PYX=0
-
-
 def str2mac(s):
     return ("%02x:"*6)[:-1] % tuple(map(ord, s)) 
 
-
 if not WINDOWS:
     if not scapy.config.conf.use_pcap and not scapy.config.conf.use_dnet:
         from scapy.arch.bpf.core import get_if_raw_addr
@@ -71,8 +46,6 @@ def get_if_hwaddr(iff):
 # def get_if(iff,cmd):
 # def get_if_index(iff):
 
-
-
 if LINUX:
     from scapy.arch.linux import *
     if scapy.config.conf.use_pcap or scapy.config.conf.use_dnet:
@@ -93,7 +66,14 @@ elif SOLARIS:
     from scapy.arch.solaris import *
 elif WINDOWS:
     from scapy.arch.windows import *
-    from scapy.arch.windows.compatibility import *
+    # import only if parent is not route.py
+    # because compatibility.py will require route.py to work (through sendrecv.py)
+    parents = parent_function()
+    if len(parents) >= 3:
+        if not parents[2][1].endswith("route.py"):
+            from scapy.arch.windows.compatibility import *
+    else:
+        from scapy.arch.windows.compatibility import *
 
 if scapy.config.conf.iface is None:
     scapy.config.conf.iface = LOOPBACK_NAME
diff --git a/scapy/arch/bpf/core.py b/scapy/arch/bpf/core.py
index 99180699..a8339b2a 100644
--- a/scapy/arch/bpf/core.py
+++ b/scapy/arch/bpf/core.py
@@ -8,7 +8,7 @@ from scapy.config import conf
 from scapy.error import Scapy_Exception
 from scapy.data import ARPHDR_LOOPBACK, ARPHDR_ETHER
 from scapy.arch.common import get_if
-from scapy.arch.consts import LOOPBACK_NAME
+from scapy.consts import LOOPBACK_NAME
 from scapy.utils import warning
 
 from scapy.arch.bpf.consts import *
diff --git a/scapy/arch/bpf/supersocket.py b/scapy/arch/bpf/supersocket.py
index a74d8f82..244e909c 100644
--- a/scapy/arch/bpf/supersocket.py
+++ b/scapy/arch/bpf/supersocket.py
@@ -12,7 +12,7 @@ from scapy.layers.inet import IP
 from scapy.layers.inet6 import IPv6
 from scapy.packet import Raw
 from scapy.data import ETH_P_ALL
-from scapy.arch.consts import FREEBSD, OPENBSD, NETBSD
+from scapy.consts import FREEBSD, OPENBSD, NETBSD
 from scapy.utils import warning
 
 from scapy.arch.bpf.core import get_dev_bpf, attach_filter
diff --git a/scapy/arch/linux.py b/scapy/arch/linux.py
index ed5ab9af..898356e2 100644
--- a/scapy/arch/linux.py
+++ b/scapy/arch/linux.py
@@ -11,7 +11,7 @@ import sys,os,struct,socket,time
 from select import select
 from fcntl import ioctl
 
-from scapy.arch.consts import LOOPBACK_NAME
+from scapy.consts import LOOPBACK_NAME
 import scapy.utils
 import scapy.utils6
 from scapy.packet import Packet, Padding
diff --git a/scapy/arch/unix.py b/scapy/arch/unix.py
index 0e3428cb..c55e4413 100644
--- a/scapy/arch/unix.py
+++ b/scapy/arch/unix.py
@@ -16,7 +16,7 @@ import scapy.config
 import scapy.utils
 from scapy.utils6 import in6_getscope, construct_source_candidate_set
 from scapy.utils6 import in6_isvalid, in6_ismlladdr, in6_ismnladdr
-from scapy.arch.consts import FREEBSD, NETBSD, OPENBSD, SOLARIS, LOOPBACK_NAME
+from scapy.consts import FREEBSD, NETBSD, OPENBSD, SOLARIS, LOOPBACK_NAME
 from scapy.arch import get_if_addr
 from scapy.config import conf
 
diff --git a/scapy/arch/windows/__init__.py b/scapy/arch/windows/__init__.py
index 5ff08a02..e1f4e16d 100755
--- a/scapy/arch/windows/__init__.py
+++ b/scapy/arch/windows/__init__.py
@@ -16,9 +16,8 @@ from scapy.config import conf,ConfClass
 from scapy.error import Scapy_Exception,log_loading,log_runtime
 from scapy.utils import atol, itom, inet_aton, inet_ntoa, PcapReader
 from scapy.base_classes import Gen, Net, SetGen
-import scapy.plist as plist
 from scapy.data import MTU, ETHER_BROADCAST, ETH_P_ARP
-from scapy.arch.consts import LOOPBACK_NAME
+from scapy.consts import LOOPBACK_NAME
 
 conf.use_pcap = False
 conf.use_dnet = False
diff --git a/scapy/arch/windows/compatibility.py b/scapy/arch/windows/compatibility.py
index 573d64c4..7d321e1d 100644
--- a/scapy/arch/windows/compatibility.py
+++ b/scapy/arch/windows/compatibility.py
@@ -15,7 +15,7 @@ import subprocess
 import sys
 import time
 
-from scapy.arch.consts import LOOPBACK_NAME
+from scapy.consts import LOOPBACK_NAME
 from scapy.config import conf,ConfClass
 from scapy.base_classes import Gen, SetGen
 import scapy.plist as plist
@@ -168,8 +168,8 @@ def sndrcv(pks, pkt, timeout = 2, inter = 0, verbose=None, chainCC=0, retry=0, m
     return plist.SndRcvList(ans),plist.PacketList(remain,"Unanswered")
 
 
-import scapy.sendrecv
-scapy.sendrecv.sndrcv = sndrcv
+import scapy.sendrecv as sendrecv
+sendrecv.sndrcv = sndrcv
 
 def sniff(count=0, store=1, offline=None, prn = None, lfilter=None, L2socket=None, timeout=None, *arg, **karg):
     """Sniff packets
@@ -249,7 +249,7 @@ L2socket: use the provided L2socket
     return plist.PacketList(lst,"Sniffed")
 
 import scapy.sendrecv
-scapy.sendrecv.sniff = sniff
+sendrecv.sniff = sniff
 
 # If wpcap.dll is not available
 if not (conf.use_winpcapy or conf.use_pcap or conf.use_dnet):
diff --git a/scapy/arch/consts.py b/scapy/consts.py
similarity index 55%
rename from scapy/arch/consts.py
rename to scapy/consts.py
index 57a33dae..aa09ff78 100644
--- a/scapy/arch/consts.py
+++ b/scapy/consts.py
@@ -3,9 +3,34 @@
 ## Copyright (C) Philippe Biondi <phil@secdev.org>
 ## This program is published under a GPLv2 license
 
-import os
+import os, inspect
 from sys import platform
 import platform as platform_lib
+from scapy.error import *
+
+try:
+    from matplotlib import get_backend as matplotlib_get_backend
+    import matplotlib.pyplot as plt
+    MATPLOTLIB = 1
+    if "inline" in matplotlib_get_backend():
+        MATPLOTLIB_INLINED = 1
+    else:
+        MATPLOTLIB_INLINED = 0
+    MATPLOTLIB_DEFAULT_PLOT_KARGS = {"marker": "+"}
+# RuntimeError to catch gtk "Cannot open display" error
+except (ImportError, RuntimeError):
+    plt = None
+    MATPLOTLIB = 0
+    MATPLOTLIB_INLINED = 0
+    MATPLOTLIB_DEFAULT_PLOT_KARGS = dict()
+    log_loading.info("Can't import matplotlib. Won't be able to plot.")
+
+try:
+    import pyx
+    PYX=1
+except ImportError:
+    log_loading.info("Can't import PyX. Won't be able to use psdump() or pdfdump().")
+    PYX=0
 
 LINUX = platform.startswith("linux")
 OPENBSD = platform.startswith("openbsd")
@@ -31,3 +56,6 @@ else:
     X86_64 = uname[4] == 'x86_64'
     ARM_64 = uname[4] == 'aarch64'
     LOOPBACK_NAME = "lo" if LINUX else "lo0"
+
+def parent_function():
+    return inspect.getouterframes(inspect.currentframe())
diff --git a/scapy/layers/l2.py b/scapy/layers/l2.py
index 83ec881d..26bf33d4 100644
--- a/scapy/layers/l2.py
+++ b/scapy/layers/l2.py
@@ -18,7 +18,7 @@ from scapy.plist import SndRcvList
 from scapy.fields import *
 from scapy.sendrecv import srp, srp1, srpflood
 from scapy.arch import get_if_hwaddr
-from scapy.arch.consts import LOOPBACK_NAME
+from scapy.consts import LOOPBACK_NAME
 from scapy.utils import inet_ntoa, inet_aton
 if conf.route is None:
     # unused import, only to initialize conf.route
diff --git a/scapy/plist.py b/scapy/plist.py
index d4d82629..eb9a7faa 100644
--- a/scapy/plist.py
+++ b/scapy/plist.py
@@ -15,8 +15,7 @@ from scapy.config import conf
 from scapy.base_classes import BasePacket,BasePacketList
 from scapy.utils import do_graph,hexdump,make_table,make_lined_table,make_tex_table,get_temp_file
 
-from scapy.arch import plt, MATPLOTLIB_INLINED, MATPLOTLIB_DEFAULT_PLOT_KARGS
-
+from scapy.consts import plt, MATPLOTLIB_INLINED, MATPLOTLIB_DEFAULT_PLOT_KARGS
 
 
 #############
diff --git a/scapy/route.py b/scapy/route.py
index d0f81213..a6595d08 100644
--- a/scapy/route.py
+++ b/scapy/route.py
@@ -8,7 +8,7 @@ Routing and handling of network interfaces.
 """
 
 import socket
-from scapy.arch.consts import LOOPBACK_NAME
+from scapy.consts import LOOPBACK_NAME
 from scapy.utils import atol,ltoa,itom
 from scapy.config import conf
 from scapy.error import Scapy_Exception,warning
diff --git a/scapy/sendrecv.py b/scapy/sendrecv.py
index 9ca7d480..86b28e4e 100644
--- a/scapy/sendrecv.py
+++ b/scapy/sendrecv.py
@@ -12,7 +12,7 @@ import cPickle,os,sys,time,subprocess
 import itertools
 from select import select, error as select_error
 
-from scapy.arch.consts import DARWIN, FREEBSD, OPENBSD
+from scapy.consts import DARWIN, FREEBSD, OPENBSD
 from scapy.data import *
 from scapy.config import conf
 from scapy.packet import Gen
diff --git a/scapy/tools/UTscapy.py b/scapy/tools/UTscapy.py
index ac5dcdd1..97ca2a84 100755
--- a/scapy/tools/UTscapy.py
+++ b/scapy/tools/UTscapy.py
@@ -9,7 +9,7 @@ Unit testing infrastructure for Scapy
 
 import sys,getopt,imp
 import bz2, base64, os.path, time, traceback, zlib, sha
-from scapy.arch.consts import WINDOWS
+from scapy.consts import WINDOWS
 
 
 #### Import tool ####
-- 
GitLab