2323import subprocess
2424import traceback
2525
26+ # pylint: disable=wrong-import-position
2627import gi
27-
2828gi .require_version ('Gtk' , '3.0' )
2929from gi .repository import Gtk
30+ # pylint: enable=wrong-import-position
3031
3132from diffuse import constants
3233
3334# convenience class for displaying a message dialogue
3435class MessageDialog (Gtk .MessageDialog ):
35- def __init__ (self , parent , type , s ):
36- if type == Gtk .MessageType .ERROR :
36+ def __init__ (self , parent , message_type , s ):
37+ if message_type == Gtk .MessageType .ERROR :
3738 buttons = Gtk .ButtonsType .OK
3839 else :
3940 buttons = Gtk .ButtonsType .OK_CANCEL
40- Gtk .MessageDialog .__init__ (self , parent = parent , destroy_with_parent = True , message_type = type , buttons = buttons , text = s )
41+ Gtk .MessageDialog .__init__ (
42+ self ,
43+ parent = parent ,
44+ destroy_with_parent = True ,
45+ message_type = message_type ,
46+ buttons = buttons ,
47+ text = s )
4148 self .set_title (constants .APP_NAME )
4249
4350# platform test
@@ -76,13 +83,17 @@ def make_subdirs(p, ss):
7683 pass
7784 return p
7885
79- def useFlatpak ():
80- return constants .use_flatpak
86+ # returns the Windows drive or share from a from an absolute path
87+ def _drive_from_path (path ):
88+ d = path .split (os .sep )
89+ if len (d ) > 3 and d [0 ] == '' and d [1 ] == '' :
90+ return os .path .join (d [:4 ])
91+ return d [0 ]
8192
8293# constructs a relative path from 'a' to 'b', both should be absolute paths
8394def relpath (a , b ):
8495 if isWindows ():
85- if drive_from_path (a ) != drive_from_path (b ):
96+ if _drive_from_path (a ) != _drive_from_path (b ):
8697 return b
8798 c1 = [ c for c in a .split (os .sep ) if c != '' ]
8899 c2 = [ c for c in b .split (os .sep ) if c != '' ]
@@ -104,24 +115,25 @@ def safeRelativePath(abspath1, name, prefs, cygwin_pref):
104115 s = s .replace ('/' , '\\ ' )
105116 return s
106117
107- # returns the Windows drive or share from a from an absolute path
108- def drive_from_path (s ):
109- c = s .split (os .sep )
110- if len (c ) > 3 and c [0 ] == '' and c [1 ] == '' :
111- return os .path .join (c [:4 ])
112- return c [0 ]
113-
114118# escape arguments for use with bash
115- def bashEscape (s ):
119+ def _bash_escape (s ):
116120 return "'" + s .replace ("'" , "'\\ ''" ) + "'"
117121
122+ def _use_flatpak ():
123+ return constants .use_flatpak
124+
118125# use popen to read the output of a command
119126def popenRead (dn , cmd , prefs , bash_pref , success_results = None ):
120127 if success_results is None :
121128 success_results = [ 0 ]
122129 if isWindows () and prefs .getBool (bash_pref ):
123130 # launch the command from a bash shell is requested
124- cmd = [ prefs .convertToNativePath ('/bin/bash.exe' ), '-l' , '-c' , 'cd {}; {}' .format (bashEscape (dn ), ' ' .join ([ bashEscape (arg ) for arg in cmd ])) ]
131+ cmd = [
132+ prefs .convertToNativePath ('/bin/bash.exe' ),
133+ '-l' ,
134+ '-c' ,
135+ f"cd { _bash_escape (dn )} ; { ' ' .join ([ _bash_escape (arg ) for arg in cmd ])} "
136+ ]
125137 dn = None
126138 # use subprocess.Popen to retrieve the file contents
127139 if isWindows ():
@@ -130,57 +142,26 @@ def popenRead(dn, cmd, prefs, bash_pref, success_results=None):
130142 info .wShowWindow = subprocess .SW_HIDE
131143 else :
132144 info = None
133- if useFlatpak ():
145+ if _use_flatpak ():
134146 cmd = [ 'flatpak-spawn' , '--host' ] + cmd
135- proc = subprocess .Popen (cmd , stdin = subprocess .PIPE , stdout = subprocess .PIPE , stderr = subprocess .PIPE , cwd = dn , startupinfo = info )
136- proc .stdin .close ()
137- proc .stderr .close ()
138- fd = proc .stdout
139- # read the command's output
140- s = fd .read ()
141- fd .close ()
142- if proc .wait () not in success_results :
143- raise IOError ('Command failed.' )
144- return s
145-
146- # use popen to read the output of a command
147- def popenReadLines (dn , cmd , prefs , bash_pref , success_results = None ):
148- return strip_eols (splitlines (popenRead (dn , cmd , prefs , bash_pref , success_results ).decode ('utf-8' , errors = 'ignore' )))
149-
150- # simulate use of popen with xargs to read the output of a command
151- def popenXArgsReadLines (dn , cmd , args , prefs , bash_pref ):
152- # os.sysconf() is only available on Unix
153- if hasattr (os , 'sysconf' ):
154- maxsize = os .sysconf ('SC_ARG_MAX' )
155- maxsize -= sum ([ len (k ) + len (v ) + 2 for k , v in os .environ .items () ])
156- else :
157- # assume the Window's limit to CreateProcess()
158- maxsize = 32767
159- maxsize -= sum ([ len (k ) + 1 for k in cmd ])
160-
161- ss = []
162- i , s , a = 0 , 0 , []
163- while i < len (args ):
164- f = (len (a ) == 0 )
165- if f :
166- # start a new command line
167- a = cmd [:]
168- elif s + len (args [i ]) + 1 <= maxsize :
169- f = True
170- if f :
171- # append another argument to the current command line
172- a .append (args [i ])
173- s += len (args [i ]) + 1
174- i += 1
175- if i == len (args ) or not f :
176- ss .extend (popenReadLines (dn , a , prefs , bash_pref ))
177- s , a = 0 , []
178- return ss
179-
180- # escape special glob characters
181- def globEscape (s ):
182- m = dict ([ (c , f'[{ c } ]' ) for c in '[]?*' ])
183- return '' .join ([ m .get (c , c ) for c in s ])
147+ with (
148+ subprocess .Popen (
149+ cmd ,
150+ stdin = subprocess .PIPE ,
151+ stdout = subprocess .PIPE ,
152+ stderr = subprocess .PIPE ,
153+ cwd = dn ,
154+ startupinfo = info ) as proc
155+ ):
156+ proc .stdin .close ()
157+ proc .stderr .close ()
158+ fd = proc .stdout
159+ # read the command's output
160+ s = fd .read ()
161+ fd .close ()
162+ if proc .wait () not in success_results :
163+ raise IOError ('Command failed.' )
164+ return s
184165
185166# returns the number of characters in the string excluding any line ending
186167# characters
@@ -196,20 +177,35 @@ def len_minus_line_ending(s):
196177
197178# returns the string without the line ending characters
198179def strip_eol (s ):
199- if s is not None :
200- return s [:len_minus_line_ending (s )]
180+ if s :
181+ s = s [:len_minus_line_ending (s )]
182+ return s
183+
184+ # returns the list of strings without line ending characters
185+ def _strip_eols (ss ):
186+ return [ strip_eol (s ) for s in ss ]
187+
188+ # use popen to read the output of a command
189+ def popenReadLines (dn , cmd , prefs , bash_pref , success_results = None ):
190+ return _strip_eols (splitlines (popenRead (
191+ dn , cmd , prefs , bash_pref , success_results ).decode ('utf-8' , errors = 'ignore' )))
192+
193+ # escape special glob characters
194+ def globEscape (s ):
195+ m = { c : f'[{ c } ]' for c in '[]?*' }
196+ return '' .join ([ m .get (c , c ) for c in s ])
201197
202198# split string into lines based upon DOS, Mac, and Unix line endings
203- def splitlines (s ) :
199+ def splitlines (text : str ) -> list [ str ] :
204200 # split on new line characters
205- temp , i , n = [], 0 , len (s )
201+ temp , i , n = [], 0 , len (text )
206202 while i < n :
207- j = s .find ('\n ' , i )
203+ j = text .find ('\n ' , i )
208204 if j < 0 :
209- temp .append (s [i :])
205+ temp .append (text [i :])
210206 break
211207 j += 1
212- temp .append (s [i :j ])
208+ temp .append (text [i :j ])
213209 i = j
214210 # split on carriage return characters
215211 ss = []
@@ -229,7 +225,7 @@ def splitlines(s):
229225
230226# also recognize old Mac OS line endings
231227def readlines (fd ):
232- return [ strip_eol ( s ) for s in splitlines (fd .read ()) ]
228+ return _strip_eols ( splitlines (fd .read ()))
233229
234230# use the program's location as a starting place to search for supporting files
235231# such as icon and help documentation
@@ -249,8 +245,8 @@ def readlines(fd):
249245 if v in os .environ :
250246 lang = os .environ [v ]
251247 # remove any additional languages, encodings, or modifications
252- for v in ':.@' :
253- lang = lang .split (v )[0 ]
248+ for c in ':.@' :
249+ lang = lang .split (c )[0 ]
254250 break
255251 else :
256252 if lang is not None :
0 commit comments