[gnome-music/wip/mschraal/type-checking: 1/6] CI: Add static type checking pass




commit 9f79e0c315604120c8a83c975994a09a6b1c1981
Author: Marinus Schraal <mschraal gnome org>
Date:   Sat May 30 14:09:44 2020 +0200

    CI: Add static type checking pass
    
    Also:
    * Ignore initial property errors
    * Add relevant .gitignore
    * Add some required types
    * Add some info to the README

 .gitignore                                      |  1 +
 .gitlab-ci.yml                                  |  6 +++++
 README.md                                       | 36 +++++++++++++++++++++++++
 gnomemusic/artcache.py                          |  6 ++++-
 gnomemusic/corealbum.py                         |  4 +--
 gnomemusic/coreartist.py                        |  4 +--
 gnomemusic/coredisc.py                          |  2 +-
 gnomemusic/coremodel.py                         |  2 +-
 gnomemusic/coresong.py                          |  6 ++---
 gnomemusic/grilowrappers/grltrackerplaylists.py |  4 +--
 gnomemusic/grilowrappers/grltrackerwrapper.py   |  2 +-
 gnomemusic/gstplayer.py                         |  6 ++---
 gnomemusic/player.py                            |  2 +-
 gnomemusic/scrobbler.py                         |  6 ++---
 gnomemusic/views/artistsview.py                 |  2 +-
 gnomemusic/views/emptyview.py                   |  2 +-
 gnomemusic/views/searchview.py                  |  2 +-
 gnomemusic/views/songsview.py                   |  2 +-
 gnomemusic/widgets/artstack.py                  |  4 +--
 gnomemusic/widgets/headerbar.py                 |  6 ++---
 gnomemusic/widgets/playertoolbar.py             |  2 +-
 gnomemusic/widgets/playlistcontrols.py          |  4 +--
 gnomemusic/widgets/searchheaderbar.py           |  4 +--
 gnomemusic/widgets/smoothscale.py               |  2 +-
 gnomemusic/widgets/songwidget.py                |  6 ++---
 gnomemusic/widgets/starhandlerwidget.py         |  2 +-
 gnomemusic/widgets/starimage.py                 |  4 +--
 27 files changed, 88 insertions(+), 41 deletions(-)
---
diff --git a/.gitignore b/.gitignore
index cbbcb9ca..ff4b7f4c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -12,6 +12,7 @@ builddir/
 /.dirstamp
 /.gitignore
 /.libs
+/.mypy_cache
 /AUTHORS
 /ABOUT-NLS
 /GPATH
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index a484574a..fdbf4bad 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -28,3 +28,9 @@ flake8:
   script:
     - dnf install -y python3-flake8
     - flake8 --ignore E402,W503 --show-source gnomemusic/
+
+mypy:
+  stage: check
+  script:
+    - dnf install -y python3-mypy
+    - mypy --ignore-missing-imports --disallow-incomplete-defs gnomemusic
diff --git a/README.md b/README.md
index 7af1e256..d06c9400 100644
--- a/README.md
+++ b/README.md
@@ -101,6 +101,42 @@ All non-public classwide variables or methods should be prepended with an unders
 _single_leading_underscore: weak "internal use" indicator. E.g. from M import * does not import objects 
whose name starts with an underscore.

 
+### Type checking
+
+Post 3.38 Music is starting to use type checking for all new code. This means that all arguments, returns 
values and variables have defined types and these types are checked for errors during the CI phase. Music 
uses [mypy](http://www.mypy-lang.org/) for the type checking pass.
+
+The specific syntax is best learned from the code already adapted ([coresong.py](gnomemusic/coresong.py), 
[grltrackerwrapper.py](gnomemusic/grilowrappers/grltrackerwrapper.py)) or online sources, note that Music 
uses the annotation style. A simple example follows.
+
+###### Old
+```python
+x = []
+
+x.append(1)
+```
+
+###### New
+```python
+from typing import List
+
+x: List[int] = []
+
+x.append(1)
+```
+
+#### Properties
+
+Mypy does not currently support PyGObject properties. This means property setters need to be forceibly 
ignored.
+
+```python
+@GObject.Property(type=bool, default=False)
+def selected(self) -> bool:
+    return self._selected
+
+@selected.setter  # type: ignore
+def selected(self, value: bool) -> None:
+    self._selected = value
+```
+
 ### PyGObject specifics
 
 #### Treemodel
diff --git a/gnomemusic/artcache.py b/gnomemusic/artcache.py
index 785d9d9d..d22ae44c 100644
--- a/gnomemusic/artcache.py
+++ b/gnomemusic/artcache.py
@@ -24,6 +24,7 @@
 
 from enum import Enum
 from math import pi
+from typing import Dict, Tuple
 
 import cairo
 from gi.repository import Gdk, GdkPixbuf, Gio, Gtk, GLib, GObject
@@ -32,6 +33,7 @@ from gnomemusic.corealbum import CoreAlbum
 from gnomemusic.coreartist import CoreArtist
 from gnomemusic.coresong import CoreSong
 from gnomemusic.musiclogger import MusicLogger
+from gnomemusic.utils import ArtSize
 
 
 def _make_icon_frame(
@@ -128,7 +130,9 @@ class DefaultIcon(GObject.GObject):
         LOADING = "content-loading-symbolic"
         MUSIC = "folder-music-symbolic"
 
-    _cache = {}
+    _cache: Dict[
+        Tuple["DefaultIcon.Type", ArtSize, int, bool], cairo.Surface] = {}
+
     _default_theme = Gtk.IconTheme.get_default()
 
     def __init__(self):
diff --git a/gnomemusic/corealbum.py b/gnomemusic/corealbum.py
index 3be2f5bf..4ab1569c 100644
--- a/gnomemusic/corealbum.py
+++ b/gnomemusic/corealbum.py
@@ -118,7 +118,7 @@ class CoreAlbum(GObject.GObject):
     def selected(self):
         return self._selected
 
-    @selected.setter
+    @selected.setter  # type: ignore
     def selected(self, value):
         if value == self._selected:
             return
@@ -145,7 +145,7 @@ class CoreAlbum(GObject.GObject):
 
         return self._thumbnail
 
-    @thumbnail.setter
+    @thumbnail.setter  # type: ignore
     def thumbnail(self, value):
         """Album art thumbnail setter
 
diff --git a/gnomemusic/coreartist.py b/gnomemusic/coreartist.py
index 036f4c17..1630d3fb 100644
--- a/gnomemusic/coreartist.py
+++ b/gnomemusic/coreartist.py
@@ -93,7 +93,7 @@ class CoreArtist(GObject.GObject):
     def selected(self):
         return self._selected
 
-    @selected.setter
+    @selected.setter  # type: ignore
     def selected(self, value):
         if value == self._selected:
             return
@@ -120,7 +120,7 @@ class CoreArtist(GObject.GObject):
 
         return self._thumbnail
 
-    @thumbnail.setter
+    @thumbnail.setter  # type: ignore
     def thumbnail(self, value):
         """Artist art thumbnail setter
 
diff --git a/gnomemusic/coredisc.py b/gnomemusic/coredisc.py
index 4307f0ed..697089a6 100644
--- a/gnomemusic/coredisc.py
+++ b/gnomemusic/coredisc.py
@@ -113,7 +113,7 @@ class CoreDisc(GObject.GObject):
     def selected(self):
         return self._selected
 
-    @selected.setter
+    @selected.setter  # type: ignore
     def selected(self, value):
         self._selected = value
 
diff --git a/gnomemusic/coremodel.py b/gnomemusic/coremodel.py
index 7d8f8173..2a3f7967 100644
--- a/gnomemusic/coremodel.py
+++ b/gnomemusic/coremodel.py
@@ -311,7 +311,7 @@ class CoreModel(GObject.GObject):
         """
         return self._active_core_object
 
-    @active_core_object.setter
+    @active_core_object.setter  # type: ignore
     def active_core_object(self, value):
         """Set the current playing core object
         (album, artist, playlist, search result or song).
diff --git a/gnomemusic/coresong.py b/gnomemusic/coresong.py
index 6099b3d5..8365d6be 100644
--- a/gnomemusic/coresong.py
+++ b/gnomemusic/coresong.py
@@ -89,7 +89,7 @@ class CoreSong(GObject.GObject):
     def favorite(self):
         return self._favorite
 
-    @favorite.setter
+    @favorite.setter  # type: ignore
     def favorite(self, favorite):
         if not self._is_tracker:
             return
@@ -109,7 +109,7 @@ class CoreSong(GObject.GObject):
     def selected(self):
         return self._selected
 
-    @selected.setter
+    @selected.setter  # type: ignore
     def selected(self, value):
         if not self._is_tracker:
             return
@@ -133,7 +133,7 @@ class CoreSong(GObject.GObject):
 
         return self._thumbnail
 
-    @thumbnail.setter
+    @thumbnail.setter  # type: ignore
     def thumbnail(self, value):
         """Song art thumbnail setter
 
diff --git a/gnomemusic/grilowrappers/grltrackerplaylists.py b/gnomemusic/grilowrappers/grltrackerplaylists.py
index 566a6762..720c541c 100644
--- a/gnomemusic/grilowrappers/grltrackerplaylists.py
+++ b/gnomemusic/grilowrappers/grltrackerplaylists.py
@@ -325,7 +325,7 @@ class Playlist(GObject.GObject):
 
         return self._model
 
-    @model.setter
+    @model.setter  # type: ignore
     def model(self, value):
         self._model = value
 
@@ -432,7 +432,7 @@ class Playlist(GObject.GObject):
         """
         return self._title
 
-    @title.setter
+    @title.setter  # type: ignore
     def title(self, new_name):
         """Rename a playlist
 
diff --git a/gnomemusic/grilowrappers/grltrackerwrapper.py b/gnomemusic/grilowrappers/grltrackerwrapper.py
index 96b19897..681e5998 100644
--- a/gnomemusic/grilowrappers/grltrackerwrapper.py
+++ b/gnomemusic/grilowrappers/grltrackerwrapper.py
@@ -134,7 +134,7 @@ class GrlTrackerWrapper(GObject.GObject):
     def source(self):
         return self._source
 
-    @source.setter
+    @source.setter  # type: ignore
     def source(self, new_source):
         """Set a new grilo tracker source
 
diff --git a/gnomemusic/gstplayer.py b/gnomemusic/gstplayer.py
index 978a0e8d..cb248fd8 100644
--- a/gnomemusic/gstplayer.py
+++ b/gnomemusic/gstplayer.py
@@ -215,7 +215,7 @@ class GstPlayer(GObject.GObject):
         """
         return self._state
 
-    @state.setter
+    @state.setter  # type: ignore
     def state(self, state):
         """Set state of the player
 
@@ -239,7 +239,7 @@ class GstPlayer(GObject.GObject):
         """
         return self._player.props.current_uri
 
-    @url.setter
+    @url.setter  # type: ignore
     def url(self, url_):
         """url to load next
 
@@ -274,7 +274,7 @@ class GstPlayer(GObject.GObject):
 
     # Setter provided to trigger a property signal.
     # For internal use only.
-    @duration.setter
+    @duration.setter  # type: ignore
     def duration(self, duration):
         """Set duration of current media (internal)
 
diff --git a/gnomemusic/player.py b/gnomemusic/player.py
index 64d29e48..bdf85daf 100644
--- a/gnomemusic/player.py
+++ b/gnomemusic/player.py
@@ -585,7 +585,7 @@ class Player(GObject.GObject):
     def repeat_mode(self):
         return self._repeat
 
-    @repeat_mode.setter
+    @repeat_mode.setter  # type: ignore
     def repeat_mode(self, mode):
         if mode == self._repeat:
             return
diff --git a/gnomemusic/scrobbler.py b/gnomemusic/scrobbler.py
index 857a7580..aed95156 100644
--- a/gnomemusic/scrobbler.py
+++ b/gnomemusic/scrobbler.py
@@ -274,7 +274,7 @@ class LastFmScrobbler(GObject.GObject):
         """
         return self._account_state
 
-    @account_state.setter
+    @account_state.setter  # type: ignore
     def account_state(self, value):
         """Set the Last.fm account state
 
@@ -298,7 +298,7 @@ class LastFmScrobbler(GObject.GObject):
         return (self.props.account_state == GoaLastFM.State.ENABLED
                 and self._report is True)
 
-    @can_scrobble.setter
+    @can_scrobble.setter  # type: ignore
     def can_scrobble(self, value):
         """Set the can_scrobble status
 
@@ -324,7 +324,7 @@ class LastFmScrobbler(GObject.GObject):
         """Bool indicating current scrobble status"""
         return self._scrobbled
 
-    @scrobbled.setter
+    @scrobbled.setter  # type: ignore
     def scrobbled(self, scrobbled):
         self._scrobbled = scrobbled
 
diff --git a/gnomemusic/views/artistsview.py b/gnomemusic/views/artistsview.py
index e7a7c1c2..7666b6ce 100644
--- a/gnomemusic/views/artistsview.py
+++ b/gnomemusic/views/artistsview.py
@@ -175,7 +175,7 @@ class ArtistsView(Gtk.Box):
         """
         return self._selection_mode
 
-    @selection_mode.setter
+    @selection_mode.setter  # type: ignore
     def selection_mode(self, value):
         """selection-mode setter
 
diff --git a/gnomemusic/views/emptyview.py b/gnomemusic/views/emptyview.py
index e82a1d21..52418f74 100644
--- a/gnomemusic/views/emptyview.py
+++ b/gnomemusic/views/emptyview.py
@@ -89,7 +89,7 @@ class EmptyView(Gtk.Stack):
         """
         return self._state
 
-    @state.setter
+    @state.setter  # type: ignore
     def state(self, value):
         """Set the state of the empty view
 
diff --git a/gnomemusic/views/searchview.py b/gnomemusic/views/searchview.py
index 5760e06e..59c98353 100644
--- a/gnomemusic/views/searchview.py
+++ b/gnomemusic/views/searchview.py
@@ -474,7 +474,7 @@ class SearchView(Gtk.Stack):
         """
         return self._search_mode_active
 
-    @search_mode_active.setter
+    @search_mode_active.setter  # type: ignore
     def search_mode_active(self, value):
         """Set search mode status.
 
diff --git a/gnomemusic/views/songsview.py b/gnomemusic/views/songsview.py
index 9eea53c0..e487a54b 100644
--- a/gnomemusic/views/songsview.py
+++ b/gnomemusic/views/songsview.py
@@ -113,7 +113,7 @@ class SongsView(Gtk.ScrolledWindow):
         """
         return self._selection_mode
 
-    @selection_mode.setter
+    @selection_mode.setter  # type: ignore
     def selection_mode(self, value):
         """selection-mode setter
 
diff --git a/gnomemusic/widgets/artstack.py b/gnomemusic/widgets/artstack.py
index 7be71f8e..129b67a8 100644
--- a/gnomemusic/widgets/artstack.py
+++ b/gnomemusic/widgets/artstack.py
@@ -73,7 +73,7 @@ class ArtStack(Gtk.Stack):
         """
         return self._size
 
-    @size.setter
+    @size.setter  # type: ignore
     def size(self, value):
         """Set the cover size
 
@@ -86,7 +86,7 @@ class ArtStack(Gtk.Stack):
     def coreobject(self):
         return self._coreobject
 
-    @coreobject.setter
+    @coreobject.setter  # type: ignore
     def coreobject(self, coreobject):
         if self._thumbnail_id != 0:
             self._coreobject.disconnect(self._thumbnail_id)
diff --git a/gnomemusic/widgets/headerbar.py b/gnomemusic/widgets/headerbar.py
index d6b70d59..ee163963 100644
--- a/gnomemusic/widgets/headerbar.py
+++ b/gnomemusic/widgets/headerbar.py
@@ -55,7 +55,7 @@ class SelectionBarMenuButton(Gtk.MenuButton):
         """
         return self._selected_songs_count
 
-    @selected_songs_count.setter
+    @selected_songs_count.setter  # type: ignore
     def selected_songs_count(self, value):
         """Set the number of songs selected
 
@@ -157,7 +157,7 @@ class HeaderBar(Gtk.HeaderBar):
         """
         return self._selection_mode
 
-    @selection_mode.setter
+    @selection_mode.setter  # type: ignore
     def selection_mode(self, mode):
         """Set the selection mode
 
@@ -182,7 +182,7 @@ class HeaderBar(Gtk.HeaderBar):
         """
         return self._state
 
-    @state.setter
+    @state.setter  # type: ignore
     def state(self, value):
         """Set state of the of widget
 
diff --git a/gnomemusic/widgets/playertoolbar.py b/gnomemusic/widgets/playertoolbar.py
index 78eb0f46..16f7ac31 100644
--- a/gnomemusic/widgets/playertoolbar.py
+++ b/gnomemusic/widgets/playertoolbar.py
@@ -83,7 +83,7 @@ class PlayerToolbar(Gtk.ActionBar):
         """
         return self._player
 
-    @player.setter
+    @player.setter  # type: ignore
     def player(self, player):
         """Set the GstPlayer object used
 
diff --git a/gnomemusic/widgets/playlistcontrols.py b/gnomemusic/widgets/playlistcontrols.py
index c406c18f..def8b944 100644
--- a/gnomemusic/widgets/playlistcontrols.py
+++ b/gnomemusic/widgets/playlistcontrols.py
@@ -70,7 +70,7 @@ class PlaylistControls(Gtk.Grid):
         """
         return self._application
 
-    @application.setter
+    @application.setter  # type: ignore
     def application(self, application):
         """Set the Application object used
 
@@ -157,7 +157,7 @@ class PlaylistControls(Gtk.Grid):
         """
         return self._playlist
 
-    @playlist.setter
+    @playlist.setter  # type: ignore
     def playlist(self, new_playlist):
         """Playlist property setter.
 
diff --git a/gnomemusic/widgets/searchheaderbar.py b/gnomemusic/widgets/searchheaderbar.py
index 3335726b..3e05a866 100644
--- a/gnomemusic/widgets/searchheaderbar.py
+++ b/gnomemusic/widgets/searchheaderbar.py
@@ -112,7 +112,7 @@ class SearchHeaderBar(Gtk.HeaderBar):
         """
         return self._selection_mode
 
-    @selection_mode.setter
+    @selection_mode.setter  # type: ignore
     def selection_mode(self, mode):
         """Set the selection mode
 
@@ -137,7 +137,7 @@ class SearchHeaderBar(Gtk.HeaderBar):
         """
         return self._state
 
-    @state.setter
+    @state.setter  # type: ignore
     def state(self, value):
         """Set state of the of widget
 
diff --git a/gnomemusic/widgets/smoothscale.py b/gnomemusic/widgets/smoothscale.py
index 31bd85cd..d1f6d3f9 100644
--- a/gnomemusic/widgets/smoothscale.py
+++ b/gnomemusic/widgets/smoothscale.py
@@ -64,7 +64,7 @@ class SmoothScale(Gtk.Scale):
         """
         return self._player
 
-    @player.setter
+    @player.setter  # type: ignore
     def player(self, player):
         """Set the Player object used
 
diff --git a/gnomemusic/widgets/songwidget.py b/gnomemusic/widgets/songwidget.py
index 8846e876..1c494e07 100644
--- a/gnomemusic/widgets/songwidget.py
+++ b/gnomemusic/widgets/songwidget.py
@@ -234,7 +234,7 @@ class SongWidget(Gtk.EventBox):
         """
         return self._selection_mode
 
-    @selection_mode.setter
+    @selection_mode.setter  # type: ignore
     def selection_mode(self, value):
         """Set the selection mode
 
@@ -262,7 +262,7 @@ class SongWidget(Gtk.EventBox):
         """
         return self._state
 
-    @state.setter
+    @state.setter  # type: ignore
     def state(self, value):
         """Set state of the of widget
 
@@ -308,7 +308,7 @@ class SongWidget(Gtk.EventBox):
         """
         return self._number_label.props.label
 
-    @song_number.setter
+    @song_number.setter  # type: ignore
     def song_number(self, new_nr):
         """Set song number label from an integer
 
diff --git a/gnomemusic/widgets/starhandlerwidget.py b/gnomemusic/widgets/starhandlerwidget.py
index 2657237f..08df4e88 100644
--- a/gnomemusic/widgets/starhandlerwidget.py
+++ b/gnomemusic/widgets/starhandlerwidget.py
@@ -81,7 +81,7 @@ class CellRendererStar(Gtk.CellRendererPixbuf):
     def show_star(self):
         return self._show_star
 
-    @show_star.setter
+    @show_star.setter  # type: ignore
     def show_star(self, value):
         """Set the show-star value
 
diff --git a/gnomemusic/widgets/starimage.py b/gnomemusic/widgets/starimage.py
index 032bf6e3..1d84ecd3 100644
--- a/gnomemusic/widgets/starimage.py
+++ b/gnomemusic/widgets/starimage.py
@@ -47,7 +47,7 @@ class StarImage(Gtk.Image):
         """
         return self._favorite
 
-    @favorite.setter
+    @favorite.setter  # type: ignore
     def favorite(self, value):
         """Set favorite
 
@@ -66,7 +66,7 @@ class StarImage(Gtk.Image):
     def hover(self):
         return self._hover
 
-    @hover.setter
+    @hover.setter  # type: ignore
     def hover(self, value):
         if value:
             self.set_state_flags(Gtk.StateFlags.PRELIGHT, False)


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]