Fix lint messages in src/utils.py
This commit is contained in:
parent
f5a59b9b64
commit
812ca1779f
|
@ -23,7 +23,7 @@ jobs:
|
||||||
- name: Pylint
|
- name: Pylint
|
||||||
uses: cclauss/GitHub-Action-for-pylint@master
|
uses: cclauss/GitHub-Action-for-pylint@master
|
||||||
with:
|
with:
|
||||||
args: "pylint src/vcs/"
|
args: "pylint src/utils.py src/vcs/"
|
||||||
|
|
||||||
meson-build-test:
|
meson-build-test:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
|
@ -94,6 +94,7 @@ disable=raw-checker-failed,
|
||||||
missing-function-docstring,
|
missing-function-docstring,
|
||||||
import-error,
|
import-error,
|
||||||
no-self-use,
|
no-self-use,
|
||||||
|
too-many-arguments,
|
||||||
too-many-branches,
|
too-many-branches,
|
||||||
too-many-locals,
|
too-many-locals,
|
||||||
too-many-statements,
|
too-many-statements,
|
||||||
|
|
17
src/main.py
17
src/main.py
|
@ -29,25 +29,16 @@ import stat
|
||||||
import unicodedata
|
import unicodedata
|
||||||
import webbrowser
|
import webbrowser
|
||||||
|
|
||||||
|
# pylint: disable=wrong-import-position
|
||||||
import gi
|
import gi
|
||||||
|
|
||||||
gi.require_version('GObject', '2.0')
|
gi.require_version('GObject', '2.0')
|
||||||
from gi.repository import GObject
|
|
||||||
|
|
||||||
gi.require_version('Gtk', '3.0')
|
gi.require_version('Gtk', '3.0')
|
||||||
from gi.repository import Gtk
|
|
||||||
|
|
||||||
gi.require_version('Gdk', '3.0')
|
gi.require_version('Gdk', '3.0')
|
||||||
from gi.repository import Gdk
|
|
||||||
|
|
||||||
gi.require_version('GdkPixbuf', '2.0')
|
gi.require_version('GdkPixbuf', '2.0')
|
||||||
from gi.repository import GdkPixbuf
|
|
||||||
|
|
||||||
gi.require_version('Pango', '1.0')
|
gi.require_version('Pango', '1.0')
|
||||||
from gi.repository import Pango
|
|
||||||
|
|
||||||
gi.require_version('PangoCairo', '1.0')
|
gi.require_version('PangoCairo', '1.0')
|
||||||
from gi.repository import PangoCairo
|
from gi.repository import GObject, Gtk, Gdk, GdkPixbuf, Pango, PangoCairo
|
||||||
|
# pylint: enable=wrong-import-position
|
||||||
|
|
||||||
from urllib.parse import urlparse
|
from urllib.parse import urlparse
|
||||||
|
|
||||||
|
@ -6088,7 +6079,7 @@ class Diffuse(Gtk.Window):
|
||||||
if os.path.isfile(statepath):
|
if os.path.isfile(statepath):
|
||||||
try:
|
try:
|
||||||
f = open(statepath, 'r')
|
f = open(statepath, 'r')
|
||||||
ss = readlines(f)
|
ss = utils.readlines(f)
|
||||||
f.close()
|
f.close()
|
||||||
for j, s in enumerate(ss):
|
for j, s in enumerate(ss):
|
||||||
try:
|
try:
|
||||||
|
|
148
src/utils.py
148
src/utils.py
|
@ -23,21 +23,28 @@ import locale
|
||||||
import subprocess
|
import subprocess
|
||||||
import traceback
|
import traceback
|
||||||
|
|
||||||
|
# pylint: disable=wrong-import-position
|
||||||
import gi
|
import gi
|
||||||
|
|
||||||
gi.require_version('Gtk', '3.0')
|
gi.require_version('Gtk', '3.0')
|
||||||
from gi.repository import Gtk
|
from gi.repository import Gtk
|
||||||
|
# pylint: enable=wrong-import-position
|
||||||
|
|
||||||
from diffuse import constants
|
from diffuse import constants
|
||||||
|
|
||||||
# convenience class for displaying a message dialogue
|
# convenience class for displaying a message dialogue
|
||||||
class MessageDialog(Gtk.MessageDialog):
|
class MessageDialog(Gtk.MessageDialog):
|
||||||
def __init__(self, parent, type, s):
|
def __init__(self, parent, message_type, s):
|
||||||
if type == Gtk.MessageType.ERROR:
|
if message_type == Gtk.MessageType.ERROR:
|
||||||
buttons = Gtk.ButtonsType.OK
|
buttons = Gtk.ButtonsType.OK
|
||||||
else:
|
else:
|
||||||
buttons = Gtk.ButtonsType.OK_CANCEL
|
buttons = Gtk.ButtonsType.OK_CANCEL
|
||||||
Gtk.MessageDialog.__init__(self, parent = parent, destroy_with_parent = True, message_type = type, buttons = buttons, text = s)
|
Gtk.MessageDialog.__init__(
|
||||||
|
self,
|
||||||
|
parent=parent,
|
||||||
|
destroy_with_parent=True,
|
||||||
|
message_type=message_type,
|
||||||
|
buttons=buttons,
|
||||||
|
text=s)
|
||||||
self.set_title(constants.APP_NAME)
|
self.set_title(constants.APP_NAME)
|
||||||
|
|
||||||
# platform test
|
# platform test
|
||||||
|
@ -76,13 +83,17 @@ def make_subdirs(p, ss):
|
||||||
pass
|
pass
|
||||||
return p
|
return p
|
||||||
|
|
||||||
def useFlatpak():
|
# returns the Windows drive or share from a from an absolute path
|
||||||
return constants.use_flatpak
|
def _drive_from_path(path):
|
||||||
|
d = path.split(os.sep)
|
||||||
|
if len(d) > 3 and d[0] == '' and d[1] == '':
|
||||||
|
return os.path.join(d[:4])
|
||||||
|
return d[0]
|
||||||
|
|
||||||
# constructs a relative path from 'a' to 'b', both should be absolute paths
|
# constructs a relative path from 'a' to 'b', both should be absolute paths
|
||||||
def relpath(a, b):
|
def relpath(a, b):
|
||||||
if isWindows():
|
if isWindows():
|
||||||
if drive_from_path(a) != drive_from_path(b):
|
if _drive_from_path(a) != _drive_from_path(b):
|
||||||
return b
|
return b
|
||||||
c1 = [ c for c in a.split(os.sep) if c != '' ]
|
c1 = [ c for c in a.split(os.sep) if c != '' ]
|
||||||
c2 = [ c for c in b.split(os.sep) if c != '' ]
|
c2 = [ c for c in b.split(os.sep) if c != '' ]
|
||||||
|
@ -104,24 +115,25 @@ def safeRelativePath(abspath1, name, prefs, cygwin_pref):
|
||||||
s = s.replace('/', '\\')
|
s = s.replace('/', '\\')
|
||||||
return s
|
return s
|
||||||
|
|
||||||
# returns the Windows drive or share from a from an absolute path
|
|
||||||
def drive_from_path(s):
|
|
||||||
c = s.split(os.sep)
|
|
||||||
if len(c) > 3 and c[0] == '' and c[1] == '':
|
|
||||||
return os.path.join(c[:4])
|
|
||||||
return c[0]
|
|
||||||
|
|
||||||
# escape arguments for use with bash
|
# escape arguments for use with bash
|
||||||
def bashEscape(s):
|
def _bash_escape(s):
|
||||||
return "'" + s.replace("'", "'\\''") + "'"
|
return "'" + s.replace("'", "'\\''") + "'"
|
||||||
|
|
||||||
|
def _use_flatpak():
|
||||||
|
return constants.use_flatpak
|
||||||
|
|
||||||
# use popen to read the output of a command
|
# use popen to read the output of a command
|
||||||
def popenRead(dn, cmd, prefs, bash_pref, success_results=None):
|
def popenRead(dn, cmd, prefs, bash_pref, success_results=None):
|
||||||
if success_results is None:
|
if success_results is None:
|
||||||
success_results = [ 0 ]
|
success_results = [ 0 ]
|
||||||
if isWindows() and prefs.getBool(bash_pref):
|
if isWindows() and prefs.getBool(bash_pref):
|
||||||
# launch the command from a bash shell is requested
|
# launch the command from a bash shell is requested
|
||||||
cmd = [ prefs.convertToNativePath('/bin/bash.exe'), '-l', '-c', 'cd {}; {}'.format(bashEscape(dn), ' '.join([ bashEscape(arg) for arg in cmd ])) ]
|
cmd = [
|
||||||
|
prefs.convertToNativePath('/bin/bash.exe'),
|
||||||
|
'-l',
|
||||||
|
'-c',
|
||||||
|
f"cd {_bash_escape(dn)}; {' '.join([ _bash_escape(arg) for arg in cmd ])}"
|
||||||
|
]
|
||||||
dn = None
|
dn = None
|
||||||
# use subprocess.Popen to retrieve the file contents
|
# use subprocess.Popen to retrieve the file contents
|
||||||
if isWindows():
|
if isWindows():
|
||||||
|
@ -130,57 +142,26 @@ def popenRead(dn, cmd, prefs, bash_pref, success_results=None):
|
||||||
info.wShowWindow = subprocess.SW_HIDE
|
info.wShowWindow = subprocess.SW_HIDE
|
||||||
else:
|
else:
|
||||||
info = None
|
info = None
|
||||||
if useFlatpak():
|
if _use_flatpak():
|
||||||
cmd = [ 'flatpak-spawn', '--host' ] + cmd
|
cmd = [ 'flatpak-spawn', '--host' ] + cmd
|
||||||
proc = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=dn, startupinfo=info)
|
with (
|
||||||
proc.stdin.close()
|
subprocess.Popen(
|
||||||
proc.stderr.close()
|
cmd,
|
||||||
fd = proc.stdout
|
stdin=subprocess.PIPE,
|
||||||
# read the command's output
|
stdout=subprocess.PIPE,
|
||||||
s = fd.read()
|
stderr=subprocess.PIPE,
|
||||||
fd.close()
|
cwd=dn,
|
||||||
if proc.wait() not in success_results:
|
startupinfo=info) as proc
|
||||||
raise IOError('Command failed.')
|
):
|
||||||
return s
|
proc.stdin.close()
|
||||||
|
proc.stderr.close()
|
||||||
# use popen to read the output of a command
|
fd = proc.stdout
|
||||||
def popenReadLines(dn, cmd, prefs, bash_pref, success_results=None):
|
# read the command's output
|
||||||
return strip_eols(splitlines(popenRead(dn, cmd, prefs, bash_pref, success_results).decode('utf-8', errors='ignore')))
|
s = fd.read()
|
||||||
|
fd.close()
|
||||||
# simulate use of popen with xargs to read the output of a command
|
if proc.wait() not in success_results:
|
||||||
def popenXArgsReadLines(dn, cmd, args, prefs, bash_pref):
|
raise IOError('Command failed.')
|
||||||
# os.sysconf() is only available on Unix
|
return s
|
||||||
if hasattr(os, 'sysconf'):
|
|
||||||
maxsize = os.sysconf('SC_ARG_MAX')
|
|
||||||
maxsize -= sum([ len(k) + len(v) + 2 for k, v in os.environ.items() ])
|
|
||||||
else:
|
|
||||||
# assume the Window's limit to CreateProcess()
|
|
||||||
maxsize = 32767
|
|
||||||
maxsize -= sum([ len(k) + 1 for k in cmd ])
|
|
||||||
|
|
||||||
ss = []
|
|
||||||
i, s, a = 0, 0, []
|
|
||||||
while i < len(args):
|
|
||||||
f = (len(a) == 0)
|
|
||||||
if f:
|
|
||||||
# start a new command line
|
|
||||||
a = cmd[:]
|
|
||||||
elif s + len(args[i]) + 1 <= maxsize:
|
|
||||||
f = True
|
|
||||||
if f:
|
|
||||||
# append another argument to the current command line
|
|
||||||
a.append(args[i])
|
|
||||||
s += len(args[i]) + 1
|
|
||||||
i += 1
|
|
||||||
if i == len(args) or not f:
|
|
||||||
ss.extend(popenReadLines(dn, a, prefs, bash_pref))
|
|
||||||
s, a = 0, []
|
|
||||||
return ss
|
|
||||||
|
|
||||||
# escape special glob characters
|
|
||||||
def globEscape(s):
|
|
||||||
m = dict([ (c, f'[{c}]') for c in '[]?*' ])
|
|
||||||
return ''.join([ m.get(c, c) for c in s ])
|
|
||||||
|
|
||||||
# returns the number of characters in the string excluding any line ending
|
# returns the number of characters in the string excluding any line ending
|
||||||
# characters
|
# characters
|
||||||
|
@ -196,20 +177,35 @@ def len_minus_line_ending(s):
|
||||||
|
|
||||||
# returns the string without the line ending characters
|
# returns the string without the line ending characters
|
||||||
def strip_eol(s):
|
def strip_eol(s):
|
||||||
if s is not None:
|
if s:
|
||||||
return s[:len_minus_line_ending(s)]
|
s = s[:len_minus_line_ending(s)]
|
||||||
|
return s
|
||||||
|
|
||||||
|
# returns the list of strings without line ending characters
|
||||||
|
def _strip_eols(ss):
|
||||||
|
return [ strip_eol(s) for s in ss ]
|
||||||
|
|
||||||
|
# use popen to read the output of a command
|
||||||
|
def popenReadLines(dn, cmd, prefs, bash_pref, success_results=None):
|
||||||
|
return _strip_eols(splitlines(popenRead(
|
||||||
|
dn, cmd, prefs, bash_pref, success_results).decode('utf-8', errors='ignore')))
|
||||||
|
|
||||||
|
# escape special glob characters
|
||||||
|
def globEscape(s):
|
||||||
|
m = { c: f'[{c}]' for c in '[]?*' }
|
||||||
|
return ''.join([ m.get(c, c) for c in s ])
|
||||||
|
|
||||||
# split string into lines based upon DOS, Mac, and Unix line endings
|
# split string into lines based upon DOS, Mac, and Unix line endings
|
||||||
def splitlines(s):
|
def splitlines(text: str) -> list[str]:
|
||||||
# split on new line characters
|
# split on new line characters
|
||||||
temp, i, n = [], 0, len(s)
|
temp, i, n = [], 0, len(text)
|
||||||
while i < n:
|
while i < n:
|
||||||
j = s.find('\n', i)
|
j = text.find('\n', i)
|
||||||
if j < 0:
|
if j < 0:
|
||||||
temp.append(s[i:])
|
temp.append(text[i:])
|
||||||
break
|
break
|
||||||
j += 1
|
j += 1
|
||||||
temp.append(s[i:j])
|
temp.append(text[i:j])
|
||||||
i = j
|
i = j
|
||||||
# split on carriage return characters
|
# split on carriage return characters
|
||||||
ss = []
|
ss = []
|
||||||
|
@ -229,7 +225,7 @@ def splitlines(s):
|
||||||
|
|
||||||
# also recognize old Mac OS line endings
|
# also recognize old Mac OS line endings
|
||||||
def readlines(fd):
|
def readlines(fd):
|
||||||
return [ strip_eol(s) for s in splitlines(fd.read()) ]
|
return _strip_eols(splitlines(fd.read()))
|
||||||
|
|
||||||
# use the program's location as a starting place to search for supporting files
|
# use the program's location as a starting place to search for supporting files
|
||||||
# such as icon and help documentation
|
# such as icon and help documentation
|
||||||
|
@ -249,8 +245,8 @@ if isWindows():
|
||||||
if v in os.environ:
|
if v in os.environ:
|
||||||
lang = os.environ[v]
|
lang = os.environ[v]
|
||||||
# remove any additional languages, encodings, or modifications
|
# remove any additional languages, encodings, or modifications
|
||||||
for v in ':.@':
|
for c in ':.@':
|
||||||
lang = lang.split(v)[0]
|
lang = lang.split(c)[0]
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
if lang is not None:
|
if lang is not None:
|
||||||
|
|
|
@ -59,6 +59,36 @@ class Rcs(VcsInterface):
|
||||||
utils.logError(_('Error parsing revision %s.') % (rev, ))
|
utils.logError(_('Error parsing revision %s.') % (rev, ))
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
# simulate use of popen with xargs to read the output of a command
|
||||||
|
def _popen_xargs_readlines(self, dn, cmd, args, prefs, bash_pref):
|
||||||
|
# os.sysconf() is only available on Unix
|
||||||
|
if hasattr(os, 'sysconf'):
|
||||||
|
maxsize = os.sysconf('SC_ARG_MAX')
|
||||||
|
maxsize -= sum([ len(k) + len(v) + 2 for k, v in os.environ.items() ])
|
||||||
|
else:
|
||||||
|
# assume the Window's limit to CreateProcess()
|
||||||
|
maxsize = 32767
|
||||||
|
maxsize -= sum([ len(k) + 1 for k in cmd ])
|
||||||
|
|
||||||
|
ss = []
|
||||||
|
i, s, a = 0, 0, []
|
||||||
|
while i < len(args):
|
||||||
|
f = (len(a) == 0)
|
||||||
|
if f:
|
||||||
|
# start a new command line
|
||||||
|
a = cmd[:]
|
||||||
|
elif s + len(args[i]) + 1 <= maxsize:
|
||||||
|
f = True
|
||||||
|
if f:
|
||||||
|
# append another argument to the current command line
|
||||||
|
a.append(args[i])
|
||||||
|
s += len(args[i]) + 1
|
||||||
|
i += 1
|
||||||
|
if i == len(args) or not f:
|
||||||
|
ss.extend(utils.popenReadLines(dn, a, prefs, bash_pref))
|
||||||
|
s, a = 0, []
|
||||||
|
return ss
|
||||||
|
|
||||||
def getFolderTemplate(self, prefs, names):
|
def getFolderTemplate(self, prefs, names):
|
||||||
# build command
|
# build command
|
||||||
cmd = [ prefs.getString('rcs_bin_rlog'), '-L', '-h' ]
|
cmd = [ prefs.getString('rcs_bin_rlog'), '-L', '-h' ]
|
||||||
|
@ -108,7 +138,7 @@ class Rcs(VcsInterface):
|
||||||
args = [ utils.safeRelativePath(self.root, k, prefs, 'rcs_cygwin') for k in r ]
|
args = [ utils.safeRelativePath(self.root, k, prefs, 'rcs_cygwin') for k in r ]
|
||||||
# run command
|
# run command
|
||||||
r, k = {}, ''
|
r, k = {}, ''
|
||||||
for line in utils.popenXArgsReadLines(self.root, cmd, args, prefs, 'rcs_bash'):
|
for line in self._popen_xargs_readlines(self.root, cmd, args, prefs, 'rcs_bash'):
|
||||||
# parse response
|
# parse response
|
||||||
if line.startswith('Working file: '):
|
if line.startswith('Working file: '):
|
||||||
k = prefs.convertToNativePath(line[14:])
|
k = prefs.convertToNativePath(line[14:])
|
||||||
|
|
Loading…
Reference in New Issue