From a29c4509a316c0c77450b6fa74b96f036b0f0821 Mon Sep 17 00:00:00 2001 From: Simeon Simeonov Date: Tue, 23 Dec 2025 09:59:50 +0100 Subject: Add structure --- .gitignore | 65 +++++++++++++++ CHANGELOG | 5 ++ LICENSE | 15 ++++ README.rst | 12 +++ __init__.py | 0 __main__.py | 6 -- app.py | 75 ----------------- pyproject.toml | 194 +++++++++++++++++++++++++++++++++++++++++++ src/scorecounter/__init__.py | 0 src/scorecounter/__main__.py | 6 ++ src/scorecounter/app.py | 75 +++++++++++++++++ tests/__init__.py | 0 tests/scorecounter.py | 35 ++++++++ tests/test_app.py | 3 + 14 files changed, 410 insertions(+), 81 deletions(-) create mode 100644 .gitignore create mode 100644 CHANGELOG create mode 100644 LICENSE create mode 100644 README.rst delete mode 100644 __init__.py delete mode 100644 __main__.py delete mode 100644 app.py create mode 100644 pyproject.toml create mode 100644 src/scorecounter/__init__.py create mode 100644 src/scorecounter/__main__.py create mode 100644 src/scorecounter/app.py create mode 100644 tests/__init__.py create mode 100644 tests/scorecounter.py create mode 100644 tests/test_app.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..691f282 --- /dev/null +++ b/.gitignore @@ -0,0 +1,65 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# OSX useful to ignore +*.DS_Store +.AppleDouble +.LSOverride + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +# C extensions +*.so + +# Distribution / packaging +.Python +env/ +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +*.dist-info/ +*.egg-info/ +.installed.cfg +*.egg + +# IntelliJ Idea family of suites +.idea +*.iml +## File-based project format: +*.ipr +*.iws +## mpeltonen/sbt-idea plugin +.idea_modules/ + +# Briefcase log files +logs/ + +# Briefcase local configuratoin +.briefcase/ diff --git a/CHANGELOG b/CHANGELOG new file mode 100644 index 0000000..3a9a25a --- /dev/null +++ b/CHANGELOG @@ -0,0 +1,5 @@ +# scorecounter Release Notes + +## 0.0.1 (22 Dec 2025) + +* Initial release diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..de39d30 --- /dev/null +++ b/LICENSE @@ -0,0 +1,15 @@ +scorecounter: Simple application for counting scores for two teams +Copyright (C) 2025 Simeon Simeonov + +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 +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . diff --git a/README.rst b/README.rst new file mode 100644 index 0000000..9316f3e --- /dev/null +++ b/README.rst @@ -0,0 +1,12 @@ +scorecounter +============ + +**This cross-platform app was generated by** `Briefcase`_ **- part of** +`The BeeWare Project`_. **If you want to see more tools like Briefcase, please +consider** `becoming a financial member of BeeWare`_. + +Simple application for counting scores for two teams + +.. _`Briefcase`: https://briefcase.readthedocs.io/ +.. _`The BeeWare Project`: https://beeware.org/ +.. _`becoming a financial member of BeeWare`: https://beeware.org/contributing/membership diff --git a/__init__.py b/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/__main__.py b/__main__.py deleted file mode 100644 index 8fac33c..0000000 --- a/__main__.py +++ /dev/null @@ -1,6 +0,0 @@ -"""main entry point""" - -from scorecounter.app import main - -if __name__ == '__main__': - main().main_loop() diff --git a/app.py b/app.py deleted file mode 100644 index cf4bc1d..0000000 --- a/app.py +++ /dev/null @@ -1,75 +0,0 @@ -"""Simple score counter for two teams""" - -import toga -from toga.style.pack import COLUMN, ROW - - -class ScoreCounter(toga.App): - """The main ScoreCounter application""" - - def startup(self): - """startup entry point""" - self.score_team1 = 0 - self.score_team2 = 0 - - main_box = toga.Box(direction=COLUMN) - - self.score_label1 = toga.Label( - f'Team1: {self.score_team1}', margin=(0, 5), color='red' - ) - self.score_label2 = toga.Label( - f'Team2: {self.score_team2}', margin=(0, 5), color='blue' - ) - self.separator_label = toga.Label(' - ', margin=(0, 10)) - - score_box = toga.Box(direction=ROW, margin=5) - score_box.add(self.score_label1) - score_box.add(self.separator_label) - score_box.add(self.score_label2) - - button_clear = toga.Button( - 'Clear', on_press=self.cb_clear, margin=(20, 5, 5) - ) - button_team1 = toga.Button( - 'Team 1 (+1)', on_press=self.cb_score_team1, margin=(20, 5, 5) - ) - button_team1.style.background_color = 'red' - button_team2 = toga.Button( - 'Team 2 (+1)', on_press=self.cb_score_team2, margin=5 - ) - button_team2.style.background_color = 'blue' - - main_box.add(score_box) - main_box.add(button_team1) - main_box.add(button_team2) - main_box.add(button_clear) - - self.main_window = toga.MainWindow(title=self.formal_name) - self.main_window.content = main_box - self.main_window.show() - - def cb_clear(self, _widget): - """Clear on press callback""" - self.score_team1 = 0 - self.score_team2 = 0 - self.refresh() - - def cb_score_team1(self, _widget): - """Team1 on press callback""" - self.score_team1 += 1 - self.refresh() - - def cb_score_team2(self, _widget): - """Team 2 on press callback""" - self.score_team2 += 1 - self.refresh() - - def refresh(self): - """Refreshes the score labels""" - self.score_label1.text = f'Team1: {self.score_team1}' - self.score_label2.text = f'Team2: {self.score_team2}' - - -def main(): - """main entry point""" - return ScoreCounter() diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..b76b249 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,194 @@ +# This project was generated with 0.3.26 using template: https://github.com/beeware/briefcase-template @ v0.3.26 +[tool.briefcase] +project_name = "scorecounter" +bundle = "org.pichove" +version = "1.0.0" +url = "https://simeon.simeonov.no" +license.file = "LICENSE" +author = "Simeon Simeonov" +author_email = "sgs@pichove.org" + +[tool.briefcase.app.scorecounter] +formal_name = "scorecounter" +description = "Simple application for counting scores for two teams" +long_description = """Simple application for counting scores for two teams +""" +sources = [ + "src/scorecounter", +] +test_sources = [ + "tests", +] + +requires = [ +] +test_requires = [ + "pytest", +] + +[tool.briefcase.app.scorecounter.macOS] +universal_build = true +requires = [ + "toga-cocoa~=0.5.0", + "std-nslog~=1.0.3", +] + +[tool.briefcase.app.scorecounter.linux] +requires = [ + "toga-gtk~=0.5.0", + # PyGObject 3.52.1 enforces a requirement on libgirepository-2.0-dev. This library + # isn't available on Debian 12/Ubuntu 22.04. If you don't need to support those (or + # older) releases, you can remove this version pin. See beeware/toga#3143. + "pygobject < 3.52.1", +] + +[tool.briefcase.app.scorecounter.linux.system.debian] +system_requires = [ + # Needed to compile pycairo wheel + "libcairo2-dev", + # One of the following two packages are needed to compile PyGObject wheel. If you + # remove the pygobject pin in the requires list, you should also change to the + # version 2.0 of the girepository library. See beeware/toga#3143. + "libgirepository1.0-dev", + # "libgirepository-2.0-dev", +] + +system_runtime_requires = [ + # Needed to provide GTK and its GI bindings + "gir1.2-gtk-3.0", + # One of the following two packages are needed to use PyGObject at runtime. If you + # remove the pygobject pin in the requires list, you should also change to the + # version 2.0 of the girepository library. See beeware/toga#3143. + "libgirepository-1.0-1", + # "libgirepository-2.0-0", + # Dependencies that GTK looks for at runtime + "libcanberra-gtk3-module", + # Needed to provide WebKit2 at runtime + # Note: Debian 11 requires gir1.2-webkit2-4.0 instead + # "gir1.2-webkit2-4.1", +] + +[tool.briefcase.app.scorecounter.linux.system.rhel] +system_requires = [ + # Needed to compile pycairo wheel + "cairo-gobject-devel", + # Needed to compile PyGObject wheel + "gobject-introspection-devel", +] + +system_runtime_requires = [ + # Needed to support Python bindings to GTK + "gobject-introspection", + # Needed to provide GTK + "gtk3", + # Dependencies that GTK looks for at runtime + "libcanberra-gtk3", + # Needed to provide WebKit2 at runtime + # "webkit2gtk3", +] + +[tool.briefcase.app.scorecounter.linux.system.suse] +system_requires = [ + # Needed to compile pycairo wheel + "cairo-devel", + # Needed to compile PyGObject wheel + "gobject-introspection-devel", +] + +system_runtime_requires = [ + # Needed to provide GTK + "gtk3", + # Needed to support Python bindings to GTK + "gobject-introspection", "typelib(Gtk) = 3.0", + # Dependencies that GTK looks for at runtime + "libcanberra-gtk3-module", + # Needed to provide WebKit2 at runtime + # "libwebkit2gtk3", "typelib(WebKit2)", +] + +[tool.briefcase.app.scorecounter.linux.system.arch] +system_requires = [ + # Needed to compile pycairo wheel + "cairo", + # Needed to compile PyGObject wheel + "gobject-introspection", + # Runtime dependencies that need to exist so that the + # Arch package passes final validation. + # Needed to provide GTK + "gtk3", + # Dependencies that GTK looks for at runtime + "libcanberra", + # Needed to provide WebKit2 + # "webkit2gtk", +] + +system_runtime_requires = [ + # Needed to provide GTK + "gtk3", + # Needed to provide PyGObject bindings + "gobject-introspection-runtime", + # Dependencies that GTK looks for at runtime + "libcanberra", + # Needed to provide WebKit2 at runtime + # "webkit2gtk", +] + +[tool.briefcase.app.scorecounter.linux.appimage] +manylinux = "manylinux_2_28" + +system_requires = [ + # Needed to compile pycairo wheel + "cairo-gobject-devel", + # Needed to compile PyGObject wheel + "gobject-introspection-devel", + # Needed to provide GTK + "gtk3-devel", + # Dependencies that GTK looks for at runtime, that need to be + # in the build environment to be picked up by linuxdeploy + "libcanberra-gtk3", + "PackageKit-gtk3-module", + "gvfs-client", +] + +linuxdeploy_plugins = [ + "DEPLOY_GTK_VERSION=3 gtk", +] + +[tool.briefcase.app.scorecounter.linux.flatpak] +flatpak_runtime = "org.gnome.Platform" +flatpak_runtime_version = "48" +flatpak_sdk = "org.gnome.Sdk" + +[tool.briefcase.app.scorecounter.windows] +requires = [ + "toga-winforms~=0.5.0", +] + +# Mobile deployments +[tool.briefcase.app.scorecounter.iOS] +requires = [ + "toga-iOS~=0.5.0", + "std-nslog~=1.0.3", +] + +[tool.briefcase.app.scorecounter.android] +requires = [ + "toga-android~=0.5.0", +] + +base_theme = "Theme.MaterialComponents.Light.DarkActionBar" + +build_gradle_dependencies = [ + "com.google.android.material:material:1.13.0", + # Needed for DetailedList + # "androidx.swiperefreshlayout:swiperefreshlayout:1.1.0", + # Needed for MapView + # "org.osmdroid:osmdroid-android:6.1.20", +] + +# Web deployments +[tool.briefcase.app.scorecounter.web] +requires = [ + "toga-web~=0.5.0", +] + diff --git a/src/scorecounter/__init__.py b/src/scorecounter/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/scorecounter/__main__.py b/src/scorecounter/__main__.py new file mode 100644 index 0000000..8fac33c --- /dev/null +++ b/src/scorecounter/__main__.py @@ -0,0 +1,6 @@ +"""main entry point""" + +from scorecounter.app import main + +if __name__ == '__main__': + main().main_loop() diff --git a/src/scorecounter/app.py b/src/scorecounter/app.py new file mode 100644 index 0000000..cf4bc1d --- /dev/null +++ b/src/scorecounter/app.py @@ -0,0 +1,75 @@ +"""Simple score counter for two teams""" + +import toga +from toga.style.pack import COLUMN, ROW + + +class ScoreCounter(toga.App): + """The main ScoreCounter application""" + + def startup(self): + """startup entry point""" + self.score_team1 = 0 + self.score_team2 = 0 + + main_box = toga.Box(direction=COLUMN) + + self.score_label1 = toga.Label( + f'Team1: {self.score_team1}', margin=(0, 5), color='red' + ) + self.score_label2 = toga.Label( + f'Team2: {self.score_team2}', margin=(0, 5), color='blue' + ) + self.separator_label = toga.Label(' - ', margin=(0, 10)) + + score_box = toga.Box(direction=ROW, margin=5) + score_box.add(self.score_label1) + score_box.add(self.separator_label) + score_box.add(self.score_label2) + + button_clear = toga.Button( + 'Clear', on_press=self.cb_clear, margin=(20, 5, 5) + ) + button_team1 = toga.Button( + 'Team 1 (+1)', on_press=self.cb_score_team1, margin=(20, 5, 5) + ) + button_team1.style.background_color = 'red' + button_team2 = toga.Button( + 'Team 2 (+1)', on_press=self.cb_score_team2, margin=5 + ) + button_team2.style.background_color = 'blue' + + main_box.add(score_box) + main_box.add(button_team1) + main_box.add(button_team2) + main_box.add(button_clear) + + self.main_window = toga.MainWindow(title=self.formal_name) + self.main_window.content = main_box + self.main_window.show() + + def cb_clear(self, _widget): + """Clear on press callback""" + self.score_team1 = 0 + self.score_team2 = 0 + self.refresh() + + def cb_score_team1(self, _widget): + """Team1 on press callback""" + self.score_team1 += 1 + self.refresh() + + def cb_score_team2(self, _widget): + """Team 2 on press callback""" + self.score_team2 += 1 + self.refresh() + + def refresh(self): + """Refreshes the score labels""" + self.score_label1.text = f'Team1: {self.score_team1}' + self.score_label2.text = f'Team2: {self.score_team2}' + + +def main(): + """main entry point""" + return ScoreCounter() diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/scorecounter.py b/tests/scorecounter.py new file mode 100644 index 0000000..d59e9f3 --- /dev/null +++ b/tests/scorecounter.py @@ -0,0 +1,35 @@ +import os +import sys +import tempfile +from pathlib import Path + +import pytest + + +def run_tests(): + project_path = Path(__file__).parent.parent + os.chdir(project_path) + + # Determine any args to pass to pytest. If there aren't any, + # default to running the whole test suite. + args = sys.argv[1:] + if len(args) == 0: + args = ["tests"] + + returncode = pytest.main( + [ + # Turn up verbosity + "-vv", + # Disable color + "--color=no", + # Overwrite the cache directory to somewhere writable + "-o", + f"cache_dir={tempfile.gettempdir()}/.pytest_cache", + ] + args + ) + + print(f">>>>>>>>>> EXIT {returncode} <<<<<<<<<<") + + +if __name__ == "__main__": + run_tests() diff --git a/tests/test_app.py b/tests/test_app.py new file mode 100644 index 0000000..e1a335f --- /dev/null +++ b/tests/test_app.py @@ -0,0 +1,3 @@ +def test_first(): + """An initial test for the app.""" + assert 1 + 1 == 2 -- cgit v1.3