Skip to content

Commit

Permalink
Type annotations corrections
Browse files Browse the repository at this point in the history
Now type annotations are more commonly added than not fix mypy issues.
Some of this is scrappy and would be better dealt with by upgrading to
sqlalchemy 2 etc..

OsmGpsMap [attr-defined] import error only when run on the file itself
not the whole repo?

prefs.testing = True not needed in most situtations and hence removed.

Removed a couple of monkey patches in tests, use mock instead

Removed unused monkey patching of models to db.

Some context:
python/typing#1102
sqlalchemy/sqlalchemy#9321
python/mypy#16426
  • Loading branch information
RoDuth committed Nov 3, 2024
1 parent f6158c1 commit d682881
Show file tree
Hide file tree
Showing 46 changed files with 363 additions and 339 deletions.
4 changes: 2 additions & 2 deletions .pylintrc
Original file line number Diff line number Diff line change
Expand Up @@ -610,5 +610,5 @@ min-public-methods=2

# Exceptions that will emit a warning when being caught. Defaults to
# "BaseException, Exception".
overgeneral-exceptions=BaseException,
Exception
overgeneral-exceptions=builtins.BaseException,
builtins.Exception
2 changes: 1 addition & 1 deletion bauble/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
from bauble import paths
from bauble.version import version

version_tuple = tuple(version.split("."))
version_tuple: tuple[str, ...] = tuple(version.split("."))
release_date = datetime.datetime.fromtimestamp(0, datetime.UTC)
release_version = None
installation_date = datetime.datetime.now()
Expand Down
2 changes: 1 addition & 1 deletion bauble/btypes.py
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ class CustomEnum(Enum):

cache_ok = False

def __init__(self, size: str, **kwargs: Any) -> None:
def __init__(self, size: int, **kwargs: Any) -> None:
"""Pass the size parameter to impl column (Unicode).
To complete initialisation call `self.init` when values become
Expand Down
6 changes: 3 additions & 3 deletions bauble/db.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,13 +94,13 @@ def get_active_children(children: Callable | str, obj: Any) -> Iterable:
"""Return only active children of obj if the 'exclude_inactive' pref is
set True else return all children.
"""
children = children(obj) if callable(children) else getattr(obj, children)
kids = children(obj) if callable(children) else getattr(obj, children)
# avoid circular refs
from bauble import prefs

if prefs.prefs.get(prefs.exclude_inactive_pref):
return [i for i in children if getattr(i, "active", True)]
return children
return [i for i in kids if getattr(i, "active", True)]
return kids


class MapperBase(DeclarativeMeta):
Expand Down
21 changes: 12 additions & 9 deletions bauble/editor.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,12 @@
Description: a collection of functions and abstract classes for creating
editors
"""

import datetime
import json
import logging
import os
import re
import threading
import weakref
from collections.abc import Callable
from pathlib import Path
Expand Down Expand Up @@ -194,7 +194,8 @@ class GenericEditorView:
parent=None then bauble.gui.window is used
"""

_tooltips = {}
_tooltips: dict[str, str] = {}
accept_buttons: list[str] = []

def __init__(
self, filename, parent=None, root_widget_name=None, tooltips=None
Expand Down Expand Up @@ -380,7 +381,9 @@ def connect_signals(self, target):

def set_accept_buttons_sensitive(self, sensitive):
"""set the sensitivity of all the accept/ok buttons"""
for wname in self.accept_buttons: # pylint: disable=no-member
if not self.accept_buttons:
raise AttributeError("accept_buttons not set.")
for wname in self.accept_buttons:
getattr(self.widgets, wname).set_sensitive(sensitive)

def connect(self, obj, signal, callback, *args):
Expand Down Expand Up @@ -1136,8 +1139,8 @@ class GenericEditorPresenter:
view should trigger a session.commit.
"""

widget_to_field_map = {}
view_accept_buttons = []
widget_to_field_map: dict[str, str] = {}
view_accept_buttons: list[str] = []

PROBLEM_DUPLICATE = f"duplicate:{random()}"
PROBLEM_EMPTY = f"empty:{random()}"
Expand All @@ -1154,11 +1157,11 @@ def __init__(
):
self.model = model
self.view = view
self.problems = set()
self.problems: set[tuple[int, Gtk.Widget]] = set()
self._dirty = False
self.is_committing_presenter = do_commit
self.committing_results = committing_results
self.running_threads = []
self.running_threads: list[threading.Thread] = []
self.owns_session = False
self.session = session
if session is False:
Expand Down Expand Up @@ -1997,7 +2000,7 @@ def on_map_delete(self, *_args):
def on_map_kml_show(self, *_args):
import tempfile

from mako.template import Template
from mako.template import Template # type: ignore [import-untyped]

template = Template(
filename=self.kml_template,
Expand Down Expand Up @@ -2103,7 +2106,7 @@ class GenericModelViewPresenterEditor:
:param parent: the parent windows for the view or None
"""

ok_responses = ()
ok_responses: tuple[int, ...] = ()

def __init__(self, model, parent=None):
self.session = db.Session()
Expand Down
27 changes: 10 additions & 17 deletions bauble/i18n.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# Copyright (c) 2007 Kopfgeldjaeger
# Copyright (c) 2012-2017 Mario Frasca <mario@anche.no>
# Copyright 2017 Jardín Botánico de Quito
# Copyright (c) 2022 Ross Demuth <rossdemuth123@gmail.com>
# Copyright (c) 2022-2024 Ross Demuth <rossdemuth123@gmail.com>
#
# This file is part of ghini.desktop.
#
Expand Down Expand Up @@ -50,19 +50,15 @@

__all__ = ["_"]

TEXT_DOMAIN = "ghini-%s" % ".".join(version_tuple[0:2])
TEXT_DOMAIN = f"ghini-{'.'.join(version_tuple[0:2])}"

# most of the following code was adapted from:
# http://www.learningpython.com/2006/12/03/\
# translating-your-pythonpygtk-application/

langs = []
# Check the default locale
try:
# Python >= 3.11
lang_code, encoding = locale.getlocale()
except AttributeError:
lang_code, encoding = locale.getdefaultlocale()
lang_code, encoding = locale.getlocale()

if lang_code:
# If we have a default, it's the first in the list
Expand All @@ -81,17 +77,14 @@
# use. First we check the default, then what the system told us, and
# finally the 'known' list

if sys.platform in ["win32", "darwin"]:
locale = gettext
# NOTE not sure about this, commenting for now
# if sys.platform in ["win32", "darwin"]:
# locale = gettext
# locale.bindtextdomain(TEXT_DOMAIN, paths.locale_dir())
# locale.textdomain(TEXT_DOMAIN)

try:
import Gtk.glade as gtkglade
except ImportError:
gtkglade = locale

for module in locale, gtkglade:
module.bindtextdomain(TEXT_DOMAIN, paths.locale_dir())
module.textdomain(TEXT_DOMAIN)
gettext.bindtextdomain(TEXT_DOMAIN, paths.locale_dir())
gettext.textdomain(TEXT_DOMAIN)

# Get the language to use
lang = gettext.translation(
Expand Down
4 changes: 3 additions & 1 deletion bauble/paths.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,9 @@ def appdata_dir():
)
elif sys.platform == "darwin":
# pylint: disable=no-name-in-module
from AppKit import NSApplicationSupportDirectory
from AppKit import ( # type: ignore [import-untyped] # noqa
NSApplicationSupportDirectory,
)
from AppKit import NSSearchPathForDirectoriesInDomains
from AppKit import NSUserDomainMask

Expand Down
28 changes: 10 additions & 18 deletions bauble/pluginmgr.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,9 @@
from bauble.error import BaubleError
from bauble.i18n import _

plugins = {}
commands = {}
provided = {}
plugins: dict[str, "Plugin"] = {}
commands: dict[str, type["CommandHandler"]] = {}
provided: dict[str, type[db.Base]] = {}


def register_command(handler):
Expand Down Expand Up @@ -456,21 +456,21 @@ class Plugin:
a map of commands this plugin handled with callbacks,
e.g dict('cmd', lambda x: handler)
tools:
a list of BaubleTool classes that this plugin provides, the
a list of Tool classes that this plugin provides, the
tools' category and label will be used in Ghini's "Tool" menu
depends:
a list of names classes that inherit from BaublePlugin that this
a list of class names that inherit from Plugin that this
plugin depends on
provides:
a dictionary name->class exported by this plugin
description:
a short description of the plugin
"""

commands = []
tools = []
depends = []
provides = {}
commands: list[type["CommandHandler"]] = []
tools: list[type["Tool"]] = []
depends: list[str] = []
provides: dict[str, type] = {}
description = ""
version = "0.0"

Expand All @@ -491,14 +491,6 @@ def install(cls, import_defaults=True):
pass


class EditorPlugin(Plugin):
"""a plugin that provides one or more editors, the editors should
implement the Editor interface
"""

editors = []


class Tool: # pylint: disable=too-few-public-methods
category: str | None = None
label: str
Expand Down Expand Up @@ -564,7 +556,7 @@ def show_all(self) -> None:


class CommandHandler(ABC):
command: str | Iterable[str]
command: str | Iterable[str | None]

def get_view(self) -> View | None:
"""return the view for this command handler"""
Expand Down
34 changes: 22 additions & 12 deletions bauble/plugins/abcd/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,10 @@
from gi.repository import Gtk
from lxml import etree
from lxml.etree import Element
from lxml.etree import ElementBase
from lxml.etree import ElementTree
from lxml.etree import SubElement
from lxml.etree import _ElementTree
from sqlalchemy.orm import object_session

from bauble import db
Expand Down Expand Up @@ -190,6 +192,14 @@ def extra_elements(self, unit):
def species_markup(self, unit):
"""The species markup"""

@abstractmethod
def get_datelastedited(self):
"""Get the date last edited"""

@abstractmethod
def get_notes(self, unit):
"""Get the associated notes"""


class SpeciesABCDAdapter(ABCDAdapter):
"""An adapter to convert a Species to an ABCD Unit.
Expand Down Expand Up @@ -321,14 +331,14 @@ def extra_elements(self, unit):
# invalid XML file
if self.for_reports:
if self.species.label_distribution:
etree.SubElement(
unit, "LabelDistribution"
).text = self.species.label_distribution
etree.SubElement(unit, "LabelDistribution").text = (
self.species.label_distribution
)

if self.species.distribution:
etree.SubElement(
unit, "Distribution"
).text = self.species.distribution_str()
etree.SubElement(unit, "Distribution").text = (
self.species.distribution_str()
)

def species_markup(self, unit):
if self.for_reports:
Expand Down Expand Up @@ -495,9 +505,9 @@ def extra_elements(self, unit):
def species_markup(self, unit):
if self.for_reports:
# first the non marked up version
etree.SubElement(
unit, "FullSpeciesName"
).text = self.accession.species_str()
etree.SubElement(unit, "FullSpeciesName").text = (
self.accession.species_str()
)

unit.append(
etree.fromstring(
Expand Down Expand Up @@ -563,10 +573,10 @@ def __init__(
self.decorated_objects = decorated_objects
self.authors = authors
self.datasets = data_sets()
self.units = None
self.units: ElementBase | None = None
self.inst = institution.Institution()

def _create_units_element(self) -> SubElement:
def _create_units_element(self) -> ElementBase:
"""Create the base of the 'Units' subelement"""
if not verify_institution(self.inst):
msg = _(
Expand Down Expand Up @@ -734,7 +744,7 @@ def generate_elements(self) -> Generator[None, None, None]:
)
yield

def get_element_tree(self) -> ElementTree:
def get_element_tree(self) -> _ElementTree:
"""Call after `generate_elements` has been called."""
return ElementTree(self.datasets)

Expand Down
9 changes: 0 additions & 9 deletions bauble/plugins/garden/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -581,12 +581,3 @@ def on_combo_changed(combo, *_args):


plugin = GardenPlugin

# make names visible to db module
db.Accession = Accession
db.AccessionNote = AccessionNote
db.Plant = Plant
db.PlantNote = PlantNote
db.PlantPicture = PlantPicture
db.Location = Location
db.LocationNote = LocationNote
Loading

0 comments on commit d682881

Please sign in to comment.