Ivars il y a 6 ans
Parent
révision
3e8c0375ec
9 fichiers modifiés avec 1022 ajouts et 944 suppressions
  1. 11
    11
      addon.py
  2. 2
    2
      addon.xml
  3. 9
    0
      changelog.md
  4. 26
    14
      context_download.py
  5. 6
    4
      kmake.bat
  6. 853
    812
      project.wpr
  7. 2
    1
      resources/language/English/strings.xml
  8. 6
    0
      resources/settings.xml
  9. 107
    100
      wingdbstub.py

+ 11
- 11
addon.py Voir le fichier

1
 # -*- coding: utf-8 -*-
1
 # -*- coding: utf-8 -*-
2
+
2
 try:
3
 try:
3
     import wingdbstub
4
     import wingdbstub
5
+    #import ptvsd
6
+    #ptvsd.enable_attach("debug", address = ('127.0.0.1', 5678))
7
+    #ptvsd.wait_for_attach()
8
+    print "[playstream] Remote debug started"
4
 except:
9
 except:
10
+    print "[playstream] Remote debug skipped"
5
     pass
11
     pass
6
-#try:
7
-#    import ptvsd
8
-#    ptvsd.enable_attach("debug")
9
-#    ptvsd.wait_for_attach()
10
-#except:
11
-#    pass
12
-import os,os.path,sys, glob, shutil, re
12
+import os, os.path,sys, glob, shutil, re
13
 import urllib, traceback
13
 import urllib, traceback
14
 try:
14
 try:
15
     import cPickle as pickle
15
     import cPickle as pickle
100
     sources.plugins[source].options_write(options)
100
     sources.plugins[source].options_write(options)
101
 
101
 
102
 
102
 
103
-
104
 @plugin.route(".+" )
103
 @plugin.route(".+" )
105
 def main():
104
 def main():
106
     global prefix
105
     global prefix
229
     if len(streams)>1:
228
     if len(streams)>1:
230
         slist = []
229
         slist = []
231
         for s in streams:
230
         for s in streams:
232
-            slist.append("%s [%s,%s]"%(s["name"],s["quality"],s["lang"]))
233
-        res = xbmcgui.Dialog().select("Select stream",slist, useDetails=True) if not CLI_MODE else 0
231
+            name2 = "%s,%s" % (s["quality"],s["lang"]) if s["lang"] else s["quality"]
232
+            slist.append("[%s] %s"%(name2, s["name"]))
233
+        res = xbmcgui.Dialog().select("Select stream",slist) if not CLI_MODE else 0
234
         #res = xbmcgui.Dialog().contextmenu(slist) if not CLI_MODE else 0
234
         #res = xbmcgui.Dialog().contextmenu(slist) if not CLI_MODE else 0
235
         stream = streams[res]
235
         stream = streams[res]
236
     else:
236
     else:
303
             "Banner": 501,
303
             "Banner": 501,
304
             "FanArt": 502
304
             "FanArt": 502
305
         },
305
         },
306
-            "skin.estuary.isl": {
306
+        "skin.estuary.isl": {
307
             "None": None,
307
             "None": None,
308
             "List": 50,
308
             "List": 50,
309
             "Poster": 51,
309
             "Poster": 51,

+ 2
- 2
addon.xml Voir le fichier

1
 <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
1
 <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
2
-<addon version="0.1.83" id="plugin.video.playstream" name="PlayStream" provider-name="ivars777"  >
2
+<addon version="0.1.94" id="plugin.video.playstream" name="PlayStream" provider-name="ivars777"  >
3
   <requires>
3
   <requires>
4
     <import addon="xbmc.python" version="2.1.0"/>
4
     <import addon="xbmc.python" version="2.1.0"/>
5
     <import addon="script.module.requests" />
5
     <import addon="script.module.requests" />
6
     <import addon="script.module.simplejson" />
6
     <import addon="script.module.simplejson" />
7
-    <import addon="script.module.pycryptodome" optional="true"/>
7
+    <import addon="script.module.twisted" optional="true"/>
8
   </requires>
8
   </requires>
9
   <extension point="xbmc.python.pluginsource" library="addon.py">
9
   <extension point="xbmc.python.pluginsource" library="addon.py">
10
     <provides>video</provides>
10
     <provides>video</provides>

+ 9
- 0
changelog.md Voir le fichier

1
+**0.1.94** (04.09.2018):
2
+- [fix] salabots TVPlay (raidījumu kategorijas)
3
+
4
+**0.1.93** (04.09.2018):
5
+- [feature] pievienota iespēja spēlēt strīmus no enigma2 satelītuztvērēja
6
+
7
+**0.1.91** (21.08.2018):
8
+- [feature] pievienots jaunais tvplay (nepareiza mime-type dēļ nerādās bildes)
9
+
1
 **0.1.77** (28.06.2018):
10
 **0.1.77** (28.06.2018):
2
 - [change] salabots, lai strādā ar Kodi 18 (alpha2)
11
 - [change] salabots, lai strādā ar Kodi 18 (alpha2)
3
 
12
 

+ 26
- 14
context_download.py Voir le fichier

89
     if len(streams)>1 and not num:
89
     if len(streams)>1 and not num:
90
         slist = []
90
         slist = []
91
         for s in streams:
91
         for s in streams:
92
-            slist.append("%s [%s,%s]"%(s["name"],s["quality"],s["lang"]))
92
+            name2 = "%s,%s" % (s["quality"],s["lang"]) if s["lang"] else s["quality"]
93
+            slist.append("[%s] %s"%(name2, s["name"]))
93
         res = xbmcgui.Dialog().select("Select stream",slist) if not CLI_MODE else 0
94
         res = xbmcgui.Dialog().select("Select stream",slist) if not CLI_MODE else 0
94
         #res = xbmcgui.Dialog().contextmenu(slist) if not CLI_MODE else 0
95
         #res = xbmcgui.Dialog().contextmenu(slist) if not CLI_MODE else 0
95
         stream = streams[res]
96
         stream = streams[res]
215
 #    if not "User-Agent" in headers:
216
 #    if not "User-Agent" in headers:
216
 #        headers["User-Agent"] = UA
217
 #        headers["User-Agent"] = UA
217
     #outputfile = file.join(download_dir,output)
218
     #outputfile = file.join(download_dir,output)
219
+    if "/" in outputfile:
220
+        output = outputfile.split('/')[-1]
221
+    else:
222
+        output = outputfile.split('\\')[-1]
218
 
223
 
219
-    if cb_notify: cb_notify("Download started - %s" % outputfile)
220
-    print "Download started - %s" % outputfile, url
224
+    if cb_notify: cb_notify("Download started - %s" % output)
225
+    print "Download started - %s" % output
221
     #print url
226
     #print url
222
 
227
 
223
 
228
 
277
         r = requests.get(url2, headers=headers, verify=False)
282
         r = requests.get(url2, headers=headers, verify=False)
278
         content = r.content
283
         content = r.content
279
         if key:
284
         if key:
280
-            #from Crypto.Cipher import AES
281
-            import pyaes
285
+            try:
286
+                from Cryptodome.Cipher import AES
287
+            except:
288
+                raise Exception("No Crypto or Cryptodome library")
289
+            #import pyaes
282
             iv = content[:16]
290
             iv = content[:16]
283
             #key2 = binascii.a2b_hex(key)
291
             #key2 = binascii.a2b_hex(key)
284
-            #d = AES.new(key, AES.MODE_CBC, iv)
285
-            d = pyaes.AESModeOfOperationCBC(key, iv = iv)
286
-            content2 = ""
287
-            for i in range(16, len(content), 16):
288
-                content2 += d.decrypt(content[i:i+16])
289
-            content = content2
290
-            #content = d.decrypt(content[16:])
292
+            d = AES.new(key, AES.MODE_CBC, iv)
293
+            #d = pyaes.AESModeOfOperationCBC(key, iv = iv)
294
+            #content2 = ""
295
+            #for i in range(16, len(content), 16):
296
+            #    content2 += d.decrypt(content[i:i+16])
297
+            #content = content2
298
+            content = d.decrypt(content[16:])
291
             #d = pyaes.Decrypter(pyaes.AESModeOfOperationCBC(key, iv))
299
             #d = pyaes.Decrypter(pyaes.AESModeOfOperationCBC(key, iv))
292
             #content = d.feed(content[16:])
300
             #content = d.feed(content[16:])
293
         tsfile.write(content)
301
         tsfile.write(content)
343
 #    if not "User-Agent" in headers:
351
 #    if not "User-Agent" in headers:
344
 #        headers["User-Agent"] = UA
352
 #        headers["User-Agent"] = UA
345
     #fname = file.join(download_dir,output)
353
     #fname = file.join(download_dir,output)
354
+    if "/" in outputfile:
355
+        output = outputfile.split('/')[-1]
356
+    else:
357
+        output = outputfile.split('\\')[-1]
346
 
358
 
347
-    if cb_notify: cb_notify("Download started - %s" % outputfile)
348
-    print "Download started - %s" % outputfile
359
+    if cb_notify: cb_notify("Download started - %s" % output)
360
+    print "Download started - %s" % output
349
     #print url
361
     #print url
350
     try:
362
     try:
351
         r = requests.get(url,headers=headers, stream=True)
363
         r = requests.get(url,headers=headers, stream=True)

+ 6
- 4
kmake.bat Voir le fichier

2
 
2
 
3
 :--- Pull content submodule ---
3
 :--- Pull content submodule ---
4
 pushd resources\lib\content
4
 pushd resources\lib\content
5
-:git commit -a -m a
6
-:git checkout .
7
-:git pull
5
+rem git commit -a -m a
6
+git checkout .
7
+git pull
8
 popd
8
 popd
9
 
9
 
10
 :=== Parameters ===
10
 :=== Parameters ===
11
 python get_version.py addon.xml >version.txt
11
 python get_version.py addon.xml >version.txt
12
 set /p ver=<version.txt
12
 set /p ver=<version.txt
13
 echo %ver%
13
 echo %ver%
14
-rem pause
14
+pause
15
 
15
 
16
 set prog=PlayStream
16
 set prog=PlayStream
17
 set pack_name=plugin.video.playstream
17
 set pack_name=plugin.video.playstream
79
 resources\lib\content\sources\ustvnow.py
79
 resources\lib\content\sources\ustvnow.py
80
 resources\lib\content\sources\viaplay.py
80
 resources\lib\content\sources\viaplay.py
81
 resources\lib\content\sources\filmas.py
81
 resources\lib\content\sources\filmas.py
82
+resources\lib\content\sources\tvplay.py
83
+resources\lib\content\sources\enigma2.py
82
 resources\lib\content\sources\YouTubeVideoUrl.py
84
 resources\lib\content\sources\YouTubeVideoUrl.py
83
 resources\lib\content\sources\jsinterp.py
85
 resources\lib\content\sources\jsinterp.py
84
 resources\lib\content\sources\swfinterp.py
86
 resources\lib\content\sources\swfinterp.py

+ 853
- 812
project.wpr
Fichier diff supprimé car celui-ci est trop grand
Voir le fichier


+ 2
- 1
resources/language/English/strings.xml Voir le fichier

19
   <string id="40013">USTVNow</string>
19
   <string id="40013">USTVNow</string>
20
   <string id="40014">FilmOn</string>
20
   <string id="40014">FilmOn</string>
21
   <string id="40015">MTGPlay</string>
21
   <string id="40015">MTGPlay</string>
22
+  <string id="40016">Enigma2</string>
22
 
23
 
23
   <string id="50001">Username</string>
24
   <string id="50001">Username</string>
24
   <string id="50002">Password</string>
25
   <string id="50002">Password</string>
39
   <string id="50023">Remote content config file location/name (ftp or http)</string>
40
   <string id="50023">Remote content config file location/name (ftp or http)</string>
40
   <string id="50024">Use remote content config file</string>
41
   <string id="50024">Use remote content config file</string>
41
   <string id="50025">Overwrite existing files while downloading</string>
42
   <string id="50025">Overwrite existing files while downloading</string>
42
-
43
+  <string id="50026">Enigma2 hostname or ip address</string>
43
 </strings>
44
 </strings>

+ 6
- 0
resources/settings.xml Voir le fichier

55
         <setting type="sep" />
55
         <setting type="sep" />
56
     </category>
56
     </category>
57
 
57
 
58
+   <category label="40016">
59
+        <setting id="enigma2_host" label="50026" type="text" default="" />
60
+        <setting id="enigma2_user" label="50001" type="text" default="" />
61
+        <setting id="enigma2_password" label="50002" type="text" default="change password" />
62
+        <setting type="sep" />
63
+    </category>
58
 
64
 
59
 </settings>
65
 </settings>

+ 107
- 100
wingdbstub.py Voir le fichier

1
 #########################################################################
1
 #########################################################################
2
-""" wingdbstub.py    -- Debug stub for debuggifying Python programs
2
+""" wingdbstub.py -- Start debugging Python programs from outside of Wing
3
 
3
 
4
-Copyright (c) 1999-2001, Archaeopteryx Software, Inc.  All rights reserved.
4
+Copyright (c) 1999-2018, Archaeopteryx Software, Inc.  All rights reserved.
5
 
5
 
6
 Written by Stephan R.A. Deibel and John P. Ehresman
6
 Written by Stephan R.A. Deibel and John P. Ehresman
7
 
7
 
8
 Usage:
8
 Usage:
9
 -----
9
 -----
10
 
10
 
11
-This is the file that Wing DB users copy into their python project 
12
-directory if they want to be able to debug programs that are launched
13
-outside of the IDE (e.g., CGI scripts, in response to a browser page
14
-load).
15
-
16
-To use this, edit the configuration values below to match your 
17
-Wing installation and requirements of your project.
18
-
19
-Then, add the following line to your code:
11
+This file is used to initiate debug in Python code without launching
12
+that code from Wing.  To use it, edit the configuration values below,
13
+start Wing and configure it to listen for outside debug connections,
14
+and then add the following line to your code:
20
 
15
 
21
   import wingdbstub
16
   import wingdbstub
22
 
17
 
23
-Debugging will start immediately after this import statements.
24
-
25
-Next make sure that your IDE is running and that it's configured to accept
26
-connections from the host the debug program will be running on.
18
+Debugging will start immediately after this import statement is reached.
27
 
19
 
28
-Now, invoking your python file should run the code within the debugger.
29
-Note, however, that Wing will not stop in the code unless a breakpoint
30
-is set.
31
-
32
-If the debug process is started before the IDE, or is not listening
33
-at the time this module is imported then the program will run with
34
-debugging until an attach request is seen.  Attaching only works 
35
-if the .wingdebugpw file is present; see the manual for details.
36
-
37
-On win32, you either need to edit WINGHOME in this script or
38
-pass in an environment variable called WINGHOME that points to
39
-the Wing installation directory.
20
+For details, see Debugging Externally Launched Code in the manual.
40
 
21
 
41
 """
22
 """
42
 #########################################################################
23
 #########################################################################
43
 
24
 
44
 import sys
25
 import sys
45
 import os
26
 import os
46
-import imp
27
+if sys.version_info >= (3, 7):
28
+  import importlib
29
+else:
30
+  import imp
47
 
31
 
32
+#------------------------------------------------------------------------
33
+# Required configuration values (some installers set this automatically)
34
+
35
+# This should be the full path to your Wing installation.  On OS X, use
36
+# the full path of the Wing application bundle, for example
37
+# /Applications/WingIDE.app.  When set to None, the environment variable
38
+# WINGHOME is used instead.
39
+WINGHOME = r"C:\Program Files (x86)\Wing IDE 6.1"
48
 
40
 
49
 #------------------------------------------------------------------------
41
 #------------------------------------------------------------------------
50
-# Default configuration values:  Note that the named environment 
51
-# variables, if set, will override these settings.
42
+# Optional configuration values:  The named environment variables, if set,
43
+# will override these settings.
52
 
44
 
53
 # Set this to 1 to disable all debugging; 0 to enable debugging
45
 # Set this to 1 to disable all debugging; 0 to enable debugging
54
 # (WINGDB_DISABLED environment variable)
46
 # (WINGDB_DISABLED environment variable)
60
 kWingHostPort = 'localhost:50005'
52
 kWingHostPort = 'localhost:50005'
61
 
53
 
62
 # Port on which to listen for connection requests, so that the
54
 # Port on which to listen for connection requests, so that the
63
-# IDE can (re)attach to the debug process after it has started.
55
+# IDE can attach or reattach to the debug process after it has started.
64
 # Set this to '-1' to disable listening for connection requests.
56
 # Set this to '-1' to disable listening for connection requests.
65
 # This is only used when the debug process is not attached to
57
 # This is only used when the debug process is not attached to
66
 # an IDE or the IDE has dropped its connection. The configured
58
 # an IDE or the IDE has dropped its connection. The configured
67
 # port can optionally be added to the IDE's Common Attach Hosts
59
 # port can optionally be added to the IDE's Common Attach Hosts
68
-# preference. Note that a random port is used instead if this 
69
-# port is already in use!
60
+# preference. Note that a random port is used instead if the given
61
+# port is already in use.
70
 # (WINGDB_ATTACHPORT environment variable)
62
 # (WINGDB_ATTACHPORT environment variable)
71
 kAttachPort = '50015'
63
 kAttachPort = '50015'
72
 
64
 
73
 # Set this to a filename to log verbose information about the debugger
65
 # Set this to a filename to log verbose information about the debugger
74
 # internals to a file.  If the file does not exist, it will be created
66
 # internals to a file.  If the file does not exist, it will be created
75
-# as long as its enclosing directory exists and is writeable.  Use 
76
-# "<stderr>" or "<stdout>".  Note that "<stderr>" may cause problems 
77
-# on win32 if the debug process is not running in a console.
67
+# as long as its enclosing directory exists and is writeable.  Use
68
+# "<stderr>" or "<stdout>" to write to stderr or stdout.  Note that
69
+# "<stderr>" may cause problems on Windows if the debug process is not
70
+# running in a console.
78
 # (WINGDB_LOGFILE environment variable)
71
 # (WINGDB_LOGFILE environment variable)
79
 kLogFile = None
72
 kLogFile = None
80
 
73
 
81
-# Set to get a tremendous amount of logging from the debugger internals
82
-# (WINGDB_LOGVERYVERBOSE)
74
+# Produce a tremendous amount of logging from the debugger internals.
75
+# Do not set this unless instructed to do so by Wingware support.  It
76
+# will slow the debugger to a crawl.
77
+# (WINGDB_LOGVERYVERBOSE environment variable)
83
 kLogVeryVerbose = 0
78
 kLogVeryVerbose = 0
84
 
79
 
85
 # Set this to 1 when debugging embedded scripts in an environment that
80
 # Set this to 1 when debugging embedded scripts in an environment that
86
-# creates and reuses a Python instance across multiple script invocations:  
81
+# creates and reuses a Python instance across multiple script invocations.
87
 # It turns off automatic detection of program quit so that the debug session
82
 # It turns off automatic detection of program quit so that the debug session
88
 # can span multiple script invocations.  When this is turned on, you may
83
 # can span multiple script invocations.  When this is turned on, you may
89
 # need to call ProgramQuit() on the debugger object to shut down the
84
 # need to call ProgramQuit() on the debugger object to shut down the
92
 # only the first one will be able to debug unless it terminates debug
87
 # only the first one will be able to debug unless it terminates debug
93
 # and the environment variable WINGDB_ACTIVE is unset before importing
88
 # and the environment variable WINGDB_ACTIVE is unset before importing
94
 # this module in the second or later Python instance.  See the Wing
89
 # this module in the second or later Python instance.  See the Wing
95
-# IDE manual for details.
96
-kEmbedded = 0
90
+# manual for details.
91
+# (WINGDB_EMBEDDED environment variable)
92
+kEmbedded = 1
97
 
93
 
98
 # Path to search for the debug password file and the name of the file
94
 # Path to search for the debug password file and the name of the file
99
-# to use.  The password file contains the encryption type and connect 
100
-# password for all connections to the IDE and must match the wingdebugpw
101
-# file in the profile dir used by the IDE.  Any entry of '$<winguserprofile>' 
102
-# is replaced by the wing user profile directory for the user that the 
103
-# current process is running as
95
+# to use.  The password file contains a security token for all
96
+# connections to the IDE and must match the wingdebugpw file in the
97
+# User Settngs directory used by the IDE. '$<winguserprofile>'
98
+# is replaced by the User Settings directory for the user that
99
+# is running the process.
104
 # (WINGDB_PWFILEPATH environment variable)
100
 # (WINGDB_PWFILEPATH environment variable)
105
 kPWFilePath = [os.path.dirname(__file__), '$<winguserprofile>']
101
 kPWFilePath = [os.path.dirname(__file__), '$<winguserprofile>']
106
 kPWFileName = 'wingdebugpw'
102
 kPWFileName = 'wingdebugpw'
107
 
103
 
108
-# Whether to exit if the debugger fails to run or to connect with an IDE
109
-# for whatever reason
104
+# Whether to exit when the debugger fails to run or to connect with the IDE
105
+# By default, execution continues without debug or without connecting to
106
+# the IDE.
107
+# (WINGDB_EXITONFAILURE environment variable)
110
 kExitOnFailure = 0
108
 kExitOnFailure = 0
111
 
109
 
112
 #------------------------------------------------------------------------
110
 #------------------------------------------------------------------------
113
 # Find Wing debugger installation location
111
 # Find Wing debugger installation location
114
 
112
 
115
-# Edit this to point to your Wing installation or set to None to use env WINGHOME
116
-# On OS X this must be set to name of the Wing application bundle
117
-# (for example, /Applications/WingIDE.app)
118
-WINGHOME = None
119
-
120
 if sys.hexversion >= 0x03000000:
113
 if sys.hexversion >= 0x03000000:
121
   def has_key(o, key):
114
   def has_key(o, key):
122
     return key in o
115
     return key in o
123
 else:
116
 else:
124
   def has_key(o, key):
117
   def has_key(o, key):
125
     return o.has_key(key)
118
     return o.has_key(key)
126
-    
119
+
127
 # Check environment:  Must have WINGHOME defined if still == None
120
 # Check environment:  Must have WINGHOME defined if still == None
128
 if WINGHOME == None:
121
 if WINGHOME == None:
129
   if has_key(os.environ, 'WINGHOME'):
122
   if has_key(os.environ, 'WINGHOME'):
130
     WINGHOME=os.environ['WINGHOME']
123
     WINGHOME=os.environ['WINGHOME']
131
   else:
124
   else:
132
-    sys.stdout.write("*******************************************************************\n")
133
-    sys.stdout.write("Error: Could not find Wing installation!  You must set WINGHOME or edit\n")
134
-    sys.stdout.write("wingdbstub.py where indicated to point it to the location where\n")
135
-    sys.stdout.write("Wing is installed.\n")
136
-    sys.exit(1)
137
-
125
+    msg = '\n'.join(["*******************************************************************",
126
+                     "Error: Could not find Wing installation!  You must set WINGHOME or edit",
127
+                     "wingdbstub.py where indicated to point it to the location where",
128
+                     "Wing is installed.\n"])
129
+    sys.stderr.write(msg)
130
+    raise ImportError(msg)
131
+
132
+WINGHOME = os.path.expanduser(WINGHOME)
138
 kPWFilePath.append(WINGHOME)
133
 kPWFilePath.append(WINGHOME)
139
 
134
 
140
 # The user settings dir where per-user settings & patches are located.  Will be
135
 # The user settings dir where per-user settings & patches are located.  Will be
142
 kUserSettingsDir = None
137
 kUserSettingsDir = None
143
 if kUserSettingsDir is None:
138
 if kUserSettingsDir is None:
144
   kUserSettingsDir = os.environ.get('WINGDB_USERSETTINGS')
139
   kUserSettingsDir = os.environ.get('WINGDB_USERSETTINGS')
145
-  
140
+
146
 def _FindActualWingHome(winghome):
141
 def _FindActualWingHome(winghome):
147
   """ Find the actual directory to use for winghome.  Needed on OS X
142
   """ Find the actual directory to use for winghome.  Needed on OS X
148
   where the .app directory is the preferred dir to use for WINGHOME and
143
   where the .app directory is the preferred dir to use for WINGHOME and
149
   .app/Contents/MacOS is accepted for backward compatibility. """
144
   .app/Contents/MacOS is accepted for backward compatibility. """
150
-  
145
+
151
   if sys.platform != 'darwin':
146
   if sys.platform != 'darwin':
152
     return winghome
147
     return winghome
153
-  
148
+
154
   app_dir = None
149
   app_dir = None
155
   if os.path.isdir(winghome):
150
   if os.path.isdir(winghome):
156
     if winghome.endswith('/'):
151
     if winghome.endswith('/'):
157
       wo_slash = winghome[:-1]
152
       wo_slash = winghome[:-1]
158
     else:
153
     else:
159
       wo_slash = winghome
154
       wo_slash = winghome
160
-      
155
+
161
     if wo_slash.endswith('.app'):
156
     if wo_slash.endswith('.app'):
162
       app_dir = wo_slash
157
       app_dir = wo_slash
163
     elif wo_slash.endswith('.app/Contents/MacOS'):
158
     elif wo_slash.endswith('.app/Contents/MacOS'):
164
       app_dir = wo_slash[:-len('/Contents/MacOS')]
159
       app_dir = wo_slash[:-len('/Contents/MacOS')]
165
-    
160
+
166
   if app_dir and os.path.isdir(os.path.join(app_dir, 'Contents', 'Resources')):
161
   if app_dir and os.path.isdir(os.path.join(app_dir, 'Contents', 'Resources')):
167
     return os.path.join(app_dir, 'Contents', 'Resources')
162
     return os.path.join(app_dir, 'Contents', 'Resources')
168
-  
163
+
169
   return winghome
164
   return winghome
170
-  
165
+
171
 def _ImportWingdb(winghome, user_settings=None):
166
 def _ImportWingdb(winghome, user_settings=None):
172
   """ Find & import wingdb module. """
167
   """ Find & import wingdb module. """
173
-  
168
+
174
   try:
169
   try:
175
     exec_dict = {}
170
     exec_dict = {}
176
     execfile(os.path.join(winghome, 'bin', '_patchsupport.py'), exec_dict)
171
     execfile(os.path.join(winghome, 'bin', '_patchsupport.py'), exec_dict)
181
   dir_list.extend([os.path.join(winghome, 'bin'), os.path.join(winghome, 'src')])
176
   dir_list.extend([os.path.join(winghome, 'bin'), os.path.join(winghome, 'src')])
182
   for path in dir_list:
177
   for path in dir_list:
183
     try:
178
     try:
184
-      f, p, d = imp.find_module('wingdb', [path])
185
-      try:
186
-        return imp.load_module('wingdb', f, p, d)
187
-      finally:
188
-        if f is not None:
189
-          f.close()
190
-      break
179
+      if sys.version_info >= (3, 7):
180
+        import importlib.machinery
181
+        import importlib.util
182
+
183
+        spec = importlib.machinery.PathFinder.find_spec('wingdb', [path])
184
+        if spec is not None:
185
+          mod = importlib.util.module_from_spec(spec)
186
+          if mod is not None:
187
+            spec.loader.exec_module(mod)
188
+            return mod
189
+      else:
190
+        f, p, d = imp.find_module('wingdb', [path])
191
+        try:
192
+          return imp.load_module('wingdb', f, p, d)
193
+        finally:
194
+          if f is not None:
195
+            f.close()
196
+
191
     except ImportError:
197
     except ImportError:
192
       pass
198
       pass
193
 
199
 
200
+  return None
201
+
194
 #------------------------------------------------------------------------
202
 #------------------------------------------------------------------------
195
 # Set debugger if it hasn't been set -- this is to handle module reloading
203
 # Set debugger if it hasn't been set -- this is to handle module reloading
196
 # In the reload case, the debugger variable will be set to something
204
 # In the reload case, the debugger variable will be set to something
198
   debugger
206
   debugger
199
 except NameError:
207
 except NameError:
200
   debugger = None
208
   debugger = None
201
-  
209
+
202
 # Unset WINGDB_ACTIVE env if it was inherited from another process
210
 # Unset WINGDB_ACTIVE env if it was inherited from another process
203
 # XXX Would be better to be able to call getpid() on dbgtracer but can't access it yet
211
 # XXX Would be better to be able to call getpid() on dbgtracer but can't access it yet
204
 if 'WINGDB_ACTIVE' in os.environ and os.environ['WINGDB_ACTIVE'] != str(os.getpid()):
212
 if 'WINGDB_ACTIVE' in os.environ and os.environ['WINGDB_ACTIVE'] != str(os.getpid()):
207
 # Start debugging if not disabled and this module has never been imported
215
 # Start debugging if not disabled and this module has never been imported
208
 # before
216
 # before
209
 if (not kWingDebugDisabled and debugger is None
217
 if (not kWingDebugDisabled and debugger is None
210
-    and not has_key(os.environ, 'WINGDB_DISABLED') and 
218
+    and not has_key(os.environ, 'WINGDB_DISABLED') and
211
     not has_key(os.environ, 'WINGDB_ACTIVE')):
219
     not has_key(os.environ, 'WINGDB_ACTIVE')):
212
 
220
 
213
   exit_on_fail = 0
221
   exit_on_fail = 0
214
-  
222
+
215
   try:
223
   try:
216
     # Obtain exit if fails value
224
     # Obtain exit if fails value
217
     exit_on_fail = os.environ.get('WINGDB_EXITONFAILURE', kExitOnFailure)
225
     exit_on_fail = os.environ.get('WINGDB_EXITONFAILURE', kExitOnFailure)
218
-    
226
+
219
     # Obtain configuration for log file to use, if any
227
     # Obtain configuration for log file to use, if any
220
     logfile = os.environ.get('WINGDB_LOGFILE', kLogFile)
228
     logfile = os.environ.get('WINGDB_LOGFILE', kLogFile)
221
     if logfile == '-' or logfile == None or len(logfile.strip()) == 0:
229
     if logfile == '-' or logfile == None or len(logfile.strip()) == 0:
224
     very_verbose_log = os.environ.get('WINGDB_LOGVERYVERBOSE', kLogVeryVerbose)
232
     very_verbose_log = os.environ.get('WINGDB_LOGVERYVERBOSE', kLogVeryVerbose)
225
     if type(very_verbose_log) == type('') and very_verbose_log.strip() == '':
233
     if type(very_verbose_log) == type('') and very_verbose_log.strip() == '':
226
       very_verbose_log = 0
234
       very_verbose_log = 0
227
-      
235
+
228
     # Determine remote host/port where the IDE is running
236
     # Determine remote host/port where the IDE is running
229
     hostport = os.environ.get('WINGDB_HOSTPORT', kWingHostPort)
237
     hostport = os.environ.get('WINGDB_HOSTPORT', kWingHostPort)
230
     colonpos = hostport.find(':')
238
     colonpos = hostport.find(':')
231
     host = hostport[:colonpos]
239
     host = hostport[:colonpos]
232
     port = int(hostport[colonpos+1:])
240
     port = int(hostport[colonpos+1:])
233
-  
241
+
234
     # Determine port to listen on locally for attach requests
242
     # Determine port to listen on locally for attach requests
235
     attachport = int(os.environ.get('WINGDB_ATTACHPORT', kAttachPort))
243
     attachport = int(os.environ.get('WINGDB_ATTACHPORT', kAttachPort))
236
-  
244
+
237
     # Check if running embedded script
245
     # Check if running embedded script
238
     embedded = int(os.environ.get('WINGDB_EMBEDDED', kEmbedded))
246
     embedded = int(os.environ.get('WINGDB_EMBEDDED', kEmbedded))
239
-  
247
+
240
     # Obtain debug password file search path
248
     # Obtain debug password file search path
241
     if has_key(os.environ, 'WINGDB_PWFILEPATH'):
249
     if has_key(os.environ, 'WINGDB_PWFILEPATH'):
242
       pwfile_path = os.environ['WINGDB_PWFILEPATH'].split(os.pathsep)
250
       pwfile_path = os.environ['WINGDB_PWFILEPATH'].split(os.pathsep)
243
     else:
251
     else:
244
       pwfile_path = kPWFilePath
252
       pwfile_path = kPWFilePath
245
-    
253
+
246
     # Obtain debug password file name
254
     # Obtain debug password file name
247
     if has_key(os.environ, 'WINGDB_PWFILENAME'):
255
     if has_key(os.environ, 'WINGDB_PWFILENAME'):
248
       pwfile_name = os.environ['WINGDB_PWFILENAME']
256
       pwfile_name = os.environ['WINGDB_PWFILENAME']
249
     else:
257
     else:
250
       pwfile_name = kPWFileName
258
       pwfile_name = kPWFileName
251
-    
259
+
252
     # Load wingdb.py
260
     # Load wingdb.py
253
     actual_winghome = _FindActualWingHome(WINGHOME)
261
     actual_winghome = _FindActualWingHome(WINGHOME)
254
     wingdb = _ImportWingdb(actual_winghome, kUserSettingsDir)
262
     wingdb = _ImportWingdb(actual_winghome, kUserSettingsDir)
257
       sys.stdout.write("Error: Cannot find wingdb.py in $(WINGHOME)/bin or $(WINGHOME)/src\n")
265
       sys.stdout.write("Error: Cannot find wingdb.py in $(WINGHOME)/bin or $(WINGHOME)/src\n")
258
       sys.stdout.write("Error: Please check the WINGHOME definition in wingdbstub.py\n")
266
       sys.stdout.write("Error: Please check the WINGHOME definition in wingdbstub.py\n")
259
       sys.exit(2)
267
       sys.exit(2)
260
-    
268
+
261
     # Find the netserver module and create an error stream
269
     # Find the netserver module and create an error stream
262
     netserver = wingdb.FindNetServerModule(actual_winghome, kUserSettingsDir)
270
     netserver = wingdb.FindNetServerModule(actual_winghome, kUserSettingsDir)
263
     err = wingdb.CreateErrStream(netserver, logfile, very_verbose_log)
271
     err = wingdb.CreateErrStream(netserver, logfile, very_verbose_log)
264
-    
272
+
265
     # Start debugging
273
     # Start debugging
266
-    debugger = netserver.CNetworkServer(host, port, attachport, err, 
274
+    debugger = netserver.CNetworkServer(host, port, attachport, err,
267
                                         pwfile_path=pwfile_path,
275
                                         pwfile_path=pwfile_path,
268
                                         pwfile_name=pwfile_name,
276
                                         pwfile_name=pwfile_name,
269
                                         autoquit=not embedded)
277
                                         autoquit=not embedded)
271
     os.environ['WINGDB_ACTIVE'] = str(os.getpid())
279
     os.environ['WINGDB_ACTIVE'] = str(os.getpid())
272
     if debugger.ChannelClosed():
280
     if debugger.ChannelClosed():
273
       raise ValueError('Not connected')
281
       raise ValueError('Not connected')
274
-    
282
+
275
   except:
283
   except:
276
     if exit_on_fail:
284
     if exit_on_fail:
277
       raise
285
       raise
281
 def Ensure(require_connection=1, require_debugger=1):
289
 def Ensure(require_connection=1, require_debugger=1):
282
   """ Ensure the debugger is started and attempt to connect to the IDE if
290
   """ Ensure the debugger is started and attempt to connect to the IDE if
283
   not already connected.  Will raise a ValueError if:
291
   not already connected.  Will raise a ValueError if:
284
-  
292
+
285
   * the require_connection arg is true and the debugger is unable to connect
293
   * the require_connection arg is true and the debugger is unable to connect
286
   * the require_debugger arg is true and the debugger cannot be loaded
294
   * the require_debugger arg is true and the debugger cannot be loaded
287
-  
295
+
288
   If SuspendDebug() has been called through the low-level API, calling
296
   If SuspendDebug() has been called through the low-level API, calling
289
   Ensure() resets the suspend count to zero and additional calls to
297
   Ensure() resets the suspend count to zero and additional calls to
290
   ResumeDebug() will be ignored until SuspendDebug() is called again.
298
   ResumeDebug() will be ignored until SuspendDebug() is called again.
291
-  
299
+
292
   Note that a change to the host & port to connect to will only
300
   Note that a change to the host & port to connect to will only
293
   be use if a new connection is made.
301
   be use if a new connection is made.
294
-  
302
+
295
   """
303
   """
296
-  
304
+
297
   if debugger is None:
305
   if debugger is None:
298
     if require_debugger:
306
     if require_debugger:
299
       raise ValueError("No debugger")
307
       raise ValueError("No debugger")
303
   colonpos = hostport.find(':')
311
   colonpos = hostport.find(':')
304
   host = hostport[:colonpos]
312
   host = hostport[:colonpos]
305
   port = int(hostport[colonpos+1:])
313
   port = int(hostport[colonpos+1:])
306
-  
314
+
307
   resumed = debugger.ResumeDebug()
315
   resumed = debugger.ResumeDebug()
308
   while resumed > 0:
316
   while resumed > 0:
309
     resumed = debugger.ResumeDebug()
317
     resumed = debugger.ResumeDebug()
310
-  
311
-  debugger.SetClientAddress((host, port))  
312
-  
318
+
319
+  debugger.SetClientAddress((host, port))
320
+
313
   if not debugger.DebugActive():
321
   if not debugger.DebugActive():
314
     debugger.StartDebug()
322
     debugger.StartDebug()
315
   elif debugger.ChannelClosed():
323
   elif debugger.ChannelClosed():
316
     debugger.ConnectToClient()
324
     debugger.ConnectToClient()
317
-    
325
+
318
   if require_connection and debugger.ChannelClosed():
326
   if require_connection and debugger.ChannelClosed():
319
     raise ValueError('Not connected')
327
     raise ValueError('Not connected')
320
-