diff --git a/.gitignore b/.gitignore index 2397aa4..e0c7a94 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,5 @@ *.coverage *.ui~ *.txt +*.patch PKGBUILD diff --git a/Makefile b/Makefile index 57ca21e..efa2a93 100644 --- a/Makefile +++ b/Makefile @@ -6,16 +6,17 @@ export EMMENTAL_LIB = ${PREFIX}/lib/emmental export EMMENTAL_BIN = ${PREFIX}/bin export EMMENTAL_SHARE = ${PREFIX}/share -export EMMENTAL_MAJOR = $(shell grep \^MAJOR lib/version.py | awk -F= '{ gsub(/ /,""); print $$2}') -export EMMENTAL_MINOR = $(shell grep \^MINOR lib/version.py | awk -F= '{ gsub(/ /,""); print $$2}') -export EMMENTAL_TARGZ = https://git.nowheycreamery.com/anna/emmental/archive/emmental-${EMMENTAL_MAJOR}.${EMMENTAL_MINOR}.tar.gz -export EMMENTAL_CSUM = $(shell curl -s ${EMMENTAL_TARGZ} | sha256sum | awk '{print $$1}') +all: flake8 clean: find . -type d -name __pycache__ -exec rm -r {} \+ find data/ -type d -name "Test Album" -exec rm -r {} \+ find data/ -type d -name "Test Library" -exec rm -r {} \+ +.PHONY:flake8 +flake8: + flake8 emmental/ tests/ + .PHONY: install install: exec tools/install.sh @@ -29,12 +30,18 @@ uninstall: .PHONY: pkgbuild pkgbuild: + $(eval MAJOR := $(shell grep \^MAJOR lib/version.py | awk -F= '{ gsub(/ /,""); print $$2}')) + $(eval MINOR := $(shell grep \^MINOR lib/version.py | awk -F= '{ gsub(/ /,""); print $$2}')) + $(eval TAG := $(shell git describe --tags --abbrev=0)) + $(eval CSUM := $(shell git archive --format tar.gz $(TAG) | sha256sum | awk '{print $$1}')) cp data/PKGBUILD aur/ - sed -i 's|{MAJOR}.{MINOR}|${EMMENTAL_MAJOR}.${EMMENTAL_MINOR}|' aur/PKGBUILD - sed -i 's|{SHA256SUM}|${EMMENTAL_CSUM}|' aur/PKGBUILD + sed -i 's|{MAJOR}.{MINOR}|${MAJOR}.${MINOR}|' aur/PKGBUILD + sed -i 's|{SHA256SUM}|$(CSUM)|' aur/PKGBUILD cd aur && makepkg --printsrcinfo > .SRCINFO +.PHONY: pytest +pytest: + pytest + .PHONY: tests -tests: - python tools/generate_tracks.py - python -m unittest discover -v +tests: pytest flake8 diff --git a/emmental/__init__.py b/emmental/__init__.py new file mode 100644 index 0000000..d69ed56 --- /dev/null +++ b/emmental/__init__.py @@ -0,0 +1,35 @@ +# Copyright 2022 (c) Anna Schumaker. +"""Set up our Application.""" +from . import gsetup +from . import options +from gi.repository import GLib +from gi.repository import Adw + +MAJOR_VERSION = 3 +MINOR_VERSION = 0 +VERSION_STRING = f"Emmental {MAJOR_VERSION}.{MINOR_VERSION}{gsetup.DEBUG_STR}" + + +class Application(Adw.Application): + """Our custom Adw.Application.""" + + def __init__(self): + """Initialize an Application.""" + super().__init__(application_id=gsetup.APPLICATION_ID) + self.add_main_option_entries([options.Version]) + + def do_handle_local_options(self, opts: GLib.VariantDict) -> int: + """Handle any command line options.""" + if opts.contains("version"): + print(VERSION_STRING) + gsetup.print_versions() + return 0 + return -1 + + def do_startup(self) -> None: + """Handle the Adw.Application::startup signal.""" + Adw.Application.do_startup(self) + + def do_activate(self) -> None: + """Handle the Adw.Application::activate signal.""" + Adw.Application.do_activate(self) diff --git a/emmental/gsetup.py b/emmental/gsetup.py new file mode 100644 index 0000000..b102342 --- /dev/null +++ b/emmental/gsetup.py @@ -0,0 +1,26 @@ +# Copyright 2022 (c) Anna Schumaker. +"""Set up GObject Introspection.""" +import sys +import gi + +gi.require_version("Gtk", "4.0") +gi.require_version("Adw", "1") + +DEBUG_STR = "-debug" if __debug__ else "" +APPLICATION_ID = f"com.nowheycreamery.emmental{DEBUG_STR}" + + +def __print_version(subsystem, major, minor, micro): + print(f" ⋅ {subsystem} {major}.{minor}.{micro}") + + +def print_versions(): + """Print version information for libraries we use.""" + __print_version("Python", sys.version_info.major, sys.version_info.minor, + sys.version_info.micro) + __print_version("Gtk", gi.repository.Gtk.MAJOR_VERSION, + gi.repository.Gtk.MINOR_VERSION, + gi.repository.Gtk.MICRO_VERSION) + __print_version("Libadwaita", gi.repository.Adw.MAJOR_VERSION, + gi.repository.Adw.MINOR_VERSION, + gi.repository.Adw.MICRO_VERSION) diff --git a/emmental/options.py b/emmental/options.py new file mode 100644 index 0000000..3a8f659 --- /dev/null +++ b/emmental/options.py @@ -0,0 +1,12 @@ +# Copyright 2022 (c) Anna Schumaker. +"""Configure command line options passed to Emmental.""" +from gi.repository import GLib + +Version = GLib.OptionEntry() +Version.long_name = "version" +Version.short_name = ord("v") +Version.flags = GLib.OptionFlags.NONE +Version.arg = GLib.OptionArg.NONE +Version.arg_data = None +Version.description = "Print version information and exit" +Version.arg_description = None diff --git a/emmental3.py b/emmental3.py new file mode 100755 index 0000000..12dd5ea --- /dev/null +++ b/emmental3.py @@ -0,0 +1,8 @@ +#!/usr/bin/python +# Copyright 2022 (c) Anna Schumaker. +"""The main Emmental application, version 3.0""" +import sys +import emmental + +if __name__ == "__main__": + emmental.Application().run(sys.argv) diff --git a/pytest.ini b/pytest.ini new file mode 100644 index 0000000..7a0473e --- /dev/null +++ b/pytest.ini @@ -0,0 +1,7 @@ +[pytest] +required_plugins = pytest-timeout pytest-subtests +testpaths = emmental/ tests/ +addopts = -rP +timeout = 5 +timeout_method = thread +timeout_func_only = true diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000..8d37d26 --- /dev/null +++ b/tests/__init__.py @@ -0,0 +1,2 @@ +# Copyright 2022 (c) Anna Schumaker +"""Needed to initialize tests correctly.""" diff --git a/tests/test_emmental.py b/tests/test_emmental.py new file mode 100644 index 0000000..46012d4 --- /dev/null +++ b/tests/test_emmental.py @@ -0,0 +1,25 @@ +# Copyright 2022 (c) Anna Schumaker. +"""Test as much as we can of the Emmental Application.""" +import unittest +import gi +import emmental + + +class TestEmmental(unittest.TestCase): + """Emmental Application test case.""" + + def setUp(self): + """Set up common variables.""" + self.application = emmental.Application() + + def test_version(self): + """Check that version constants have been set properly.""" + self.assertEqual(emmental.MAJOR_VERSION, 3) + self.assertEqual(emmental.MINOR_VERSION, 0) + self.assertEqual(emmental.VERSION_STRING, "Emmental 3.0-debug") + + def test_application(self): + """Check that the application instance is initialized properly.""" + self.assertIsInstance(self.application, gi.repository.Adw.Application) + self.assertEqual(self.application.get_application_id(), + "com.nowheycreamery.emmental-debug") diff --git a/tests/test_gsetup.py b/tests/test_gsetup.py new file mode 100644 index 0000000..1501ac2 --- /dev/null +++ b/tests/test_gsetup.py @@ -0,0 +1,30 @@ +# Copyright 2022 (c) Anna Schumaker. +"""Test that the gi.repository has been configured correctly.""" +import unittest +import emmental +import gi + + +class TestGSetup(unittest.TestCase): + """GObject Introspection configuration test case.""" + + def test_require_version(self): + """Check that gi.require_version() has been called.""" + self.assertEqual(gi.get_required_version("Gtk"), "4.0") + self.assertEqual(gi.get_required_version("Adw"), "1") + + def test_adw(self): + """Check that libadwaita style has been set.""" + style = gi.repository.Adw.StyleManager.get_default() + self.assertEqual(style.get_color_scheme(), + gi.repository.Adw.ColorScheme.DEFAULT) + + def test_import(self): + """Check that modules have been imported.""" + self.assertIsNotNone(emmental.gsetup.gi) + + def test_application_id(self): + """Check that the application id is generated properly.""" + self.assertEqual(emmental.gsetup.DEBUG_STR, "-debug") + self.assertEqual(emmental.gsetup.APPLICATION_ID, + "com.nowheycreamery.emmental-debug") diff --git a/tests/test_options.py b/tests/test_options.py new file mode 100644 index 0000000..5d936a3 --- /dev/null +++ b/tests/test_options.py @@ -0,0 +1,19 @@ +# Copyright 2022 (c) Anna Schumaker. +"""Test setup of the Emmental command line options.""" +import unittest +import gi +import emmental.options + + +class TestOptions(unittest.TestCase): + """Test case for our various command line options.""" + + def test_version(self): + """Check that the version option is set up properly.""" + opt = emmental.options.Version + self.assertIsInstance(opt, gi.repository.GLib.OptionEntry) + self.assertEqual(opt.long_name, "version") + self.assertEqual(opt.short_name, ord("v")) + self.assertEqual(opt.flags, gi.repository.GLib.OptionFlags.NONE) + self.assertEqual(opt.arg, gi.repository.GLib.OptionArg.NONE) + self.assertEqual(opt.arg_data, 0)