Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/codespell.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ on: # yamllint disable-line rule:truthy
pull_request:

jobs:
pylint:
codespell:
name: Run Codespell
runs-on: ubuntu-latest
steps:
Expand Down
75 changes: 75 additions & 0 deletions .github/workflows/python_unit_tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
---
name: python_unit_tests

# Always run on Pull Requests
on: # yamllint disable-line rule:truthy
pull_request:

jobs:
get_files:
runs-on: ubuntu-latest
outputs:
changed_files_list: ${{ steps.get-changed-files.outputs.files }}
steps:
- name: Check out repository
uses: actions/checkout@v4
with:
fetch-depth: 0 # fetch-depth 0 is required for diffing

- name: Get changed Python files
id: get-changed-files
run: |
# Use git diff to find changed files and format them as a
# newline-separated string
changed="$(git diff --name-only --diff-filter=ACMRT HEAD~1 HEAD |\
grep '.*\.py$' | tr '\n' ' ')"
echo "changed files = $changed"
# Set the string as a step output
echo "files=$changed" >> $GITHUB_OUTPUT

- name: Display changed files (in the same job)
run: |
echo "Changed files in this job:"
echo "${{ steps.get-changed-files.outputs.files }}"
shell: bash

python_unit_tests:
needs: [get_files]
strategy:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
# Define additional variables for different target platforms or
# configurations
target: [x86_64, arm64]
# Optional: set fail-fast to false to allow all jobs to complete
# even if one fails
fail-fast: false

runs-on: ${{ matrix.os }}

steps:
- name: Check out repository
uses: actions/checkout@v4

- name: Set up Python 3
uses: actions/setup-python@v5 # Action to set up Python
with:
cache: 'pip' # Caches dependencies for faster subsequent runs
- name: Install dependencies
# The conditional check differs slightly between shells
# (Linux/macOS vs. Windows)
run: |
REQUIREMENTS_FILE="workflow/${{ runner.os }}/requirements.txt"
if [ -f "$REQUIREMENTS_FILE" ]; then
python -m pip install --upgrade pip
pip install -r "$REQUIREMENTS_FILE"
fi
shell: bash # Explicitly use bash for consistency on
# Linux/macOS/Windows runners
- name: Run unit test script
# GitHub VS-CODE plugin false positive
run: |
files="${{ needs.get_files.outputs.changed_files_list }}"
export CHANGED_FILES="$files"
./tests/pre-commit_d/python_unit_tests.sh
shell: bash
2 changes: 1 addition & 1 deletion .github/workflows/shellcheck.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ on: # yamllint disable-line rule:truthy
pull_request:

jobs:
pylint:
shellcheck:
name: Run ShellCheck
runs-on: ubuntu-latest
steps:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/xmllint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ on: # yamllint disable-line rule:truthy
pull_request:

jobs:
pylint:
xmllint:
name: Run Xmllint
# Oddly ubuntu-latest is older than 22.04 right now.
runs-on: ubuntu-22.04
Expand Down
6 changes: 4 additions & 2 deletions d-rats.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import sys
import traceback

# pylint: disable=import-error
import gi
gi.require_version("Gtk", "3.0")
from gi.repository import Gtk
Expand Down Expand Up @@ -59,8 +60,8 @@
sys.path.insert(0, os.path.join("/usr/share", "d-rats"))

# import module to have spelling correction in chat and email applications
from d_rats import utils, spell

from d_rats import utils, spell
spell.get_spell().test()

IGNORE_ALL = False
Expand Down Expand Up @@ -88,7 +89,8 @@ def handle_exception(except_type, value, trace_back):
global IGNORE_ALL

if except_type is KeyboardInterrupt or IGNORE_ALL:
return sys.__excepthook__(except_type, value, trace_back)
sys.__excepthook__(except_type, value, trace_back)
return

# Gdk.pointer_ungrab(Gdk.CURRENT_TIME)
# Gdk.keyboard_ungrab(Gdk.CURRENT_TIME)
Expand Down
1 change: 0 additions & 1 deletion d_rats/dplatform.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.

import logging
import os
import sys
Expand Down
82 changes: 53 additions & 29 deletions d_rats/dplatform_generic.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
#
# Copyright 2009 Dan Smith <dsmith@danplanet.com>
# review 2015 Maurizio Andreotti <iz2lxi@yahoo.it>
# Copyright 2021-2023 John. E. Malmberg - Python3 Conversion
# Copyright 2021-2023,2026 John. E. Malmberg - Python3 Conversion
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
Expand Down Expand Up @@ -37,16 +37,39 @@
HAVE_AUDIO = True
except ModuleNotFoundError:
pass
else:
# This code is mainly to silence the linters when run on a
# platform with out sound support, it is actually unreachable.
class AudioSegment():
'''Mocked class when sound is not available.'''

import urllib.request
import urllib.parse
import urllib.error
# pylint: disable=no-self-use
def from_wav(self, soundfile):
'''Mocked method when sound is not available'''
print(f'No support for playing {soundfile}')

@staticmethod
def dummy():
'''Needs two public methods'''

def play(sound):
'''Mocked routine when sound is not available.'''
sound_type = type(sound)
print(f'Unable to play sound {sound_type} is unsupported')

import gi # type: ignore # Needed for pylance on Microsoft Windows
gi.require_version("Gtk", "3.0")
from gi.repository import Gtk # type: ignore
from gi.repository import Gio # type: ignore

import urllib.request

# This version of D-Rats requires GTK 3.0, but not for doing unit
# tests. This allows the default unit tests to pass on a system with
# out GTK+ installed.
try:
import gi
gi.require_version("Gtk", "3.0")
from gi.repository import Gtk # type: ignore
from gi.repository import Gio # type: ignore
except (ImportError, ValueError):
pass

if '_' not in locals():
import gettext
Expand Down Expand Up @@ -176,14 +199,15 @@ def get_exe_path(name):
:rtype: str
'''
# Make trivial check from the normal paths
exe_path = shutil.which(name)
# known false positive in pylance
exe_path = shutil.which(name) # type: ignore
if exe_path:
return exe_path
programfiles = os.getenv("PROGRAMFILES")
if programfiles:
for program in [programfiles, programfiles + " (x86)"]:
test_path=os.path.join(program, name)
exe_path = shutil.which(name, path=test_path)
exe_path = shutil.which(name, path=test_path) # type: ignore
if exe_path:
return exe_path
return None
Expand Down Expand Up @@ -261,14 +285,14 @@ def open_html_file(path):
gio_path = Gio.File.parse_name(path)
appinfo.launch([gio_path], None)

@staticmethod
def list_serial_ports():
def list_serial_ports(self):
'''
List Serial Ports.

:returns: empty list
:rtype: list
'''
self.logger.info("list_serial_ports not available on this platform")
return []

@staticmethod
Expand All @@ -281,9 +305,8 @@ def default_dir():
'''
return "."

@staticmethod
# pylint: disable=unused-argument
def gui_open_file(mime_types=None, start_dir=None):
# pylint: disable=unused-argument, no-self-use
def gui_open_file(self, mime_types=None, start_dir=None):
'''
GUI Open File.

Expand All @@ -309,14 +332,14 @@ def gui_open_file(mime_types=None, start_dir=None):
# for mime_type in mime_types:
# exts = mimetypes.guess_all_extensions(mime_type, strict=True)
# filter_mime.set_name=(exts)
# In this case it does not seem to matter what string was
# passed to the filter, the filter shows up as unnamed.
# This issue does not reproduce in a quick test program.
# In this case it does not seem to matter what string was
# passed to the filter, the filter shows up as unnamed.
# This issue does not reproduce in a quick test program.
# filter_mime.add_mime_type=(mime_type)
# dlg.add_filter(filter_mime)
# filter_any = Gtk.FileFilter()
# filter_any.set_name(_("All files"))
# In this case the filter name gets set prpoerly unlike above.
# In this case the filter name gets set properly unlike above.
# filter_any.add_pattern=('*')
# dlg.add_filter(filter_any)

Expand All @@ -331,9 +354,9 @@ def gui_open_file(mime_types=None, start_dir=None):
return fname
return None

@staticmethod
# pylint: disable=unused-argument
def gui_save_file(mime_types=None, start_dir=None, default_name=None):
# pylint: disable=unused-argument, no-self-use
def gui_save_file(self, mime_types=None, start_dir=None,
default_name=None):
'''
GUI Save File.

Expand Down Expand Up @@ -376,8 +399,8 @@ def gui_save_file(mime_types=None, start_dir=None, default_name=None):
return fname
return None

@staticmethod
def gui_select_dir(start_dir=None):
# pylint: disable=no-self-use
def gui_select_dir(self, start_dir=None):
'''
Gui Select Directory.

Expand Down Expand Up @@ -405,14 +428,14 @@ def gui_select_dir(start_dir=None):
return fname
return None

@staticmethod
def os_version_string():
def os_version_string(self):
'''
OS Version String.

:returns: "Unknown Operating System"
:rtype: str
'''
self.logger.info("Unknown Operating System")
return "Unknown Operating System"

@staticmethod
Expand Down Expand Up @@ -487,7 +510,7 @@ def have_sound():
Do we have sound support?

:returns: Status of sound support
:rytpe: bool
:rtype: bool
'''
return HAVE_AUDIO

Expand All @@ -502,7 +525,8 @@ def play_sound(self, soundfile):
if not HAVE_AUDIO:
self.logger.info("play_sound: "
"pydub and pyaudio not installed!")
return

sound = AudioSegment.from_wav(soundfile)
sound = AudioSegment.from_wav(soundfile) # type: ignore
with suppress_stderr():
play(sound)
play(sound) # type: ignore
2 changes: 2 additions & 0 deletions d_rats/dplatform_macos.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,8 @@ def sys_data(self):

@staticmethod
def _unix_doublefork_run(*args):
# False positive when editing on some platforms.
# pylint: disable=no-member
pid1 = os.fork()
if pid1 == 0:
pid2 = os.fork()
Expand Down
7 changes: 6 additions & 1 deletion d_rats/dplatform_unix.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,8 @@ def set_config_dir(self, basepath):
os.makedirs(basepath, exist_ok=True)
self._base = basepath

def default_dir(self):
@staticmethod
def default_dir():
'''
Default Directory.

Expand Down Expand Up @@ -99,11 +100,15 @@ def os_version_string(self):
issue = open("/etc/issue.net", "r")
ver = issue.read().strip()
issue.close()
# False positive when editing on some platforms
# pylint: disable=no-member
ver = "%s - %s" % (os.uname()[0], ver)
except IOError as err:
if err.errno == 2: # No such file or directory
# Linux use of this file seems to be deprecated.
pass
# False positive when editing on some platforms
# pylint: disable=no-member
ver = " ".join(os.uname())
return ver

Expand Down
Loading
Loading