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 .foundry/.gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
cache/
tmp/
user/
cache/
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@ dev.qwery.AddWater*.json~
firefox-gnome-theme
pylint-results.txt
subprojects/libportal
tests/__pycache__
__pycache__

24 changes: 19 additions & 5 deletions meson.build
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
project('addwater',
version: '1.3',
meson_version: '>= 1.4.0',
default_options: [ 'warning_level=2', 'werror=false', ],
default_options: ['warning_level=2', 'werror=true',
'buildtype=debugoptimized', 'python.install_env=auto'],
)

i18n = import('i18n')
gnome = import('gnome')
python = import('python').find_installation('python3',
modules: ['packaging', 'requests',])
modules: [
'packaging',
'requests',
]
)

pkgdatadir = get_option('prefix') / get_option('datadir') / meson.project_name()

Expand Down Expand Up @@ -36,16 +41,25 @@ conf = configuration_data({
conf.set('MOCK_API', mock_api)
conf.set('FORCE_BG', force_bg)

dependency('gtk4')
dependency('libadwaita-1', version: '>=1.9.0')
dependency('libportal', version: '>=0.9.1')
dependency('gtk4', version: '>=4.22')
dependency('libadwaita-1', version: '>=1.9.0')
dependency('libportal', version: '>=0.9.1',
default_options: ['backend-gtk4=enabled',
'backend-gtk3=disabled',
'backend-qt5=disabled',
'backend-qt6=disabled',
'vapi=false',
'introspection=true',
'werror=false'])
dependency('libportal-gtk4', version: '>=0.9.1')

subdir('data')
subdir('po')
subdir('src')

if get_option('tests')
subdir('build-aux')
subdir('tests')
endif

gnome.post_install(
Expand Down
7 changes: 7 additions & 0 deletions requirements.dev.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
iniconfig==2.3.1
packaging==26.3
pluggy==1.6.0
Pygments==2.21.0
pyproject-metadata==0.12.1
pytest==9.1.1
pytest-mock==3.16.0
8 changes: 8 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
certifi==2026.7.22
charset-normalizer==3.5.2
idna==3.20
packaging==26.3
pycairo==1.29.2
PyGObject==3.58.0
requests==2.34.2
urllib3==2.8.0
3 changes: 1 addition & 2 deletions src/apps/firefox/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
# FIXME circular import when organized
from .firefox_paths import FirefoxPack as FirefoxPack
from .firefox_details import FirefoxAppDetails as FirefoxAppDetails
from .firefox_paths import FirefoxPack as FirefoxPack
10 changes: 6 additions & 4 deletions src/apps/firefox/firefox_details.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,14 @@
from pathlib import Path

from addwater import info
from addwater.profile import AppProfile
from addwater.utils import paths
from addwater.model import AppProfile
from addwater.model.paths import aw_cache_dir
from gi.repository import Gio
from packaging.version import Version

from . import FirefoxPack
from .firefox_install import install_for_firefox
from .firefox_options import FIREFOX_OPTIONS
from .firefox_paths import FirefoxPack

log = logging.getLogger("firefox_details")

Expand All @@ -57,12 +57,14 @@ class FirefoxAppDetails:
)

# TODO just save the unzipped download in /tmp/ and then unzip into addwater/cache
save_to = paths.DOWNLOAD_DIR
# TODO make these into Paths, not PathLike strs
save_to = aw_cache_dir() / "themes"
app_folder = "firefox"
theme_folder = "firefox-gnome-theme"
full_path = join(save_to, app_folder, theme_folder)

def __init__(self) -> None:
self.save_to.mkdir(exist_ok=True, parents=False)
self.settings = self.get_new_gsettings()

version = Version(self.settings.get_string("installed-version"))
Expand Down
2 changes: 1 addition & 1 deletion src/apps/firefox/firefox_install.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
from os.path import exists, join

from addwater.components.install import InstallException
from addwater.profile import AppProfile
from addwater.model import AppProfile

log = logging.getLogger("firefox_install")

Expand Down
92 changes: 43 additions & 49 deletions src/apps/firefox/firefox_paths.py
Original file line number Diff line number Diff line change
@@ -1,59 +1,53 @@
from enum import Enum
from os import PathLike, environ
from os.path import exists, expanduser, join
from os import PathLike
from os.path import exists, join
from pathlib import Path

config_dir = environ.get("HOST_XDG_CONFIG_HOME", expanduser("~/.config"))
from addwater.model import AppPack
from addwater.model.paths import user_config, user_home

# TODO use new paths mod

# FIREFOX PATHS
# TODO replace fstring with join()
BASE_LEGACY = expanduser("~/.mozilla/firefox/")
BASE = expanduser(f"{config_dir}/mozilla/firefox/")
FLATPAK_LEGACY = expanduser("~/.var/app/org.mozilla.firefox/.mozilla/firefox/")
FLATPAK = expanduser("~/.var/app/org.mozilla.firefox/config/mozilla/firefox/")
SNAP_LEGACY = expanduser("~/snap/firefox/common/.mozilla/firefox/")
SNAP = expanduser("~/snap/firefox/common/.config/mozilla/firefox/")

LIBREWOLF_BASE_LEGACY = expanduser("~/.librewolf/")
LIBREWOLF_BASE = expanduser(f"{config_dir}/librewolf/librewolf")
LIBREWOLF_FLATPAK_LEGACY = expanduser(
"~/.var/app/io.gitlab.librewolf-community/.librewolf/"
)
LIBREWOLF_FLATPAK = expanduser(
"~/.var/app/io.gitlab.librewolf-community/config/librewolf/librewolf/"
)

FLOORP_BASE = expanduser("~/.floorp")
FLOORP_FLATPAK = expanduser("~/.var/app/one.ablaze.floorp/.floorp")

WATERFOX_BASE = expanduser("~/.waterfox")
WATERFOX_FLATPAK = expanduser("~/.var/app/net.waterfox.waterfox/.waterfox")

CACHY_BASE = expanduser("~/.cachy")
BASE_LEGACY = user_home() / ".mozilla/firefox/"
BASE = user_config() / "mozilla/firefox/"
FLATPAK_LEGACY = user_home() / ".var/app/org.mozilla.firefox/.mozilla/firefox/"
FLATPAK = user_home() / ".var/app/org.mozilla.firefox/config/mozilla/firefox/"

SNAP_LEGACY = user_home() / "snap/firefox/common/.mozilla/firefox/"
SNAP = user_home() / "snap/firefox/common/.config/mozilla/firefox/"

LIBREWOLF_BASE_LEGACY = user_home() / ".librewolf/"
LIBREWOLF_BASE = user_config() / "librewolf/librewolf"
LIBREWOLF_FLATPAK_LEGACY = user_home() / ".var/app/io.gitlab.librewolf-community/.librewolf/"
LIBREWOLF_FLATPAK = user_home() / ".var/app/io.gitlab.librewolf-community/config/librewolf/librewolf/"

FLOORP_BASE = user_home() / ".floorp"
FLOORP_FLATPAK = user_home() / ".var/app/one.ablaze.floorp/.floorp"

WATERFOX_BASE = user_home() / ".waterfox"
WATERFOX_FLATPAK = user_home() / ".var/app/net.waterfox.waterfox/.waterfox"

CACHY_BASE = user_home() / ".cachy"

# TODO can this be a GObject so I can use it in ListModels?
# or must I make a wrapper?
class FirefoxPack(Enum):
class FirefoxPack(AppPack):
# TODO rename these to just use the name instead of base later (Firefox / Firefox Flatpak / Librewolf / etc)
BASE = ("Base", BASE)
BASE_ALT = ("Base (Alt)", BASE_LEGACY)
FLATPAK = ("Flatpak", FLATPAK)
FLATPAK_ALT = ("Flatpak (Alt)", FLATPAK_LEGACY)
SNAP = ("Snap", SNAP)
SNAP_ALT = ("Snap (Alt)", SNAP_LEGACY)
LIBREWOLF = ("Librewolf", LIBREWOLF_BASE)
LIBREWOLF_ALT = ("Librewolf (Alt)", LIBREWOLF_BASE_LEGACY)
LIBREWOLF_FLATPAK = ("Librewolf Flatpak", LIBREWOLF_FLATPAK)
BASE = ("Base", BASE)
BASE_ALT = ("Base (Alt)", BASE_LEGACY)
FLATPAK = ("Flatpak", FLATPAK)
FLATPAK_ALT = ("Flatpak (Alt)", FLATPAK_LEGACY)
SNAP = ("Snap", SNAP)
SNAP_ALT = ("Snap (Alt)", SNAP_LEGACY)
LIBREWOLF = ("Librewolf", LIBREWOLF_BASE)
LIBREWOLF_ALT = ("Librewolf (Alt)", LIBREWOLF_BASE_LEGACY)
LIBREWOLF_FLATPAK = ("Librewolf Flatpak", LIBREWOLF_FLATPAK)
LIBREWOLF_FLATPAK_ALT = ("Librewolf Flatpak (Alt)", LIBREWOLF_FLATPAK_LEGACY)
FLOORP = ("Floorp", FLOORP_BASE)
FLOORP_FLATPAK = ("Floorp Flatpak", FLOORP_FLATPAK)
WATERFOX = ("Waterfox", WATERFOX_BASE)
WATERFOX_FLATPAK = ("Waterfox Flatpak", WATERFOX_FLATPAK)
CACHY = ("CachyOS Browser", CACHY_BASE)

def __init__(self, name: str, path: PathLike) -> None:
self.pack_name = name
self.path = Path(path)
FLOORP = ("Floorp", FLOORP_BASE)
FLOORP_FLATPAK = ("Floorp Flatpak", FLOORP_FLATPAK)
WATERFOX = ("Waterfox", WATERFOX_BASE)
WATERFOX_FLATPAK = ("Waterfox Flatpak", WATERFOX_FLATPAK)
CACHY = ("CachyOS Browser", CACHY_BASE)

def get_profile_ini(self) -> Path:
prof_ini = join(self.path, "profiles.ini")
Expand All @@ -64,7 +58,7 @@ def get_profile_ini(self) -> Path:


@staticmethod
def new_from_path(app_path: Path | PathLike) -> Enum | None:
def new_from_path(app_path: Path | PathLike) -> AppPack | None:
app_path = Path(app_path)
for pack in FirefoxPack:
if app_path == pack.path:
Expand All @@ -73,7 +67,7 @@ def new_from_path(app_path: Path | PathLike) -> Enum | None:
return None

@staticmethod
def new_from_name(name: str) -> Enum | None:
def new_from_name(name: str) -> AppPack | None:
for pack in FirefoxPack:
if name == pack.pack_name:
return pack
Expand Down
2 changes: 1 addition & 1 deletion src/backend.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
from addwater import info
from addwater.apps.firefox import FirefoxAppDetails, FirefoxPack
from addwater.components import InstallManager, InstallStatus, OnlineManager
from addwater.profile import AppProfile
from addwater.model import AppProfile
from addwater.utils.mocks import mock_online
from gi.repository import Gio
from packaging.version import Version
Expand Down
14 changes: 7 additions & 7 deletions src/components/install.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
from os import PathLike
from os.path import join

from addwater.profile import AppProfile
from addwater.model import AppProfile

log = logging.getLogger("install_manager")

Expand Down Expand Up @@ -89,8 +89,8 @@ def combined_install(
def uninstall(self, profile: AppProfile, folder_name: str) -> None:
try:
self._uninstaller(profile, folder_name)
except InstallException:
log.exception()
except InstallException as err:
log.exception(err)
return InstallStatus.FAILURE

return InstallStatus.SUCCESS
Expand Down Expand Up @@ -177,8 +177,8 @@ def _do_uninstall_theme(profile: AppProfile, theme_folder: str) -> None:
lines[i] = line.replace("true", "false")

file.writelines(lines)
except OSError:
log.exception()
except OSError as err:
log.exception(err)
raise InstallException("uninstall failed")

log.info("Done.")
Expand All @@ -202,8 +202,8 @@ def _remove_css_imports(chrome_path: PathLike) -> None:
lines.remove(line)

file.writelines(lines)
except FileNotFoundError:
log.exception()
except FileNotFoundError as err:
log.exception(err)

class InstallStatus(Enum):
SUCCESS = 0
Expand Down
14 changes: 7 additions & 7 deletions src/components/online.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,8 +104,8 @@ def _begin_download(self, path_info: str, tarball_url: str) -> Enum:
)
except NetworkException:
return OnlineStatus.DISCONNECTED
except ExtractionException:
log.exception()
except ExtractionException as err:
log.exception(err)
return OnlineStatus.OTHER_ERROR # TODO handle this error better
else:
return OnlineStatus.UPDATED
Expand All @@ -129,7 +129,7 @@ def _get_release(self, base_path: str, final_name: str, tarball_url: str) -> Non
try:
self._download_tarball(tarball_url, zipfile)
except (requests.RequestException, requests.ConnectionError) as err:
log.exception()
log.exception(err)
raise NetworkException(err)

try:
Expand Down Expand Up @@ -227,20 +227,20 @@ def _get_release_info(gh_url: str) -> dict:
}
try:
response = requests.get(gh_url, headers=headers, timeout=10)
except requests.RequestException:
except requests.RequestException as err:
# TODO use specific exceptions to handle being disconnected. It'll
# be more helpful if the issue isn't just being offline but an API or
# programmer error
log.exception()
log.exception(err)
raise NetworkException("failed to connect to Github")

api_calls_left = int(response.headers["x-ratelimit-remaining"])
try:
latest_release = response.json()[0]
version = Version(latest_release["tag_name"])
tarball_url = latest_release["tarball_url"]
except requests.JSONDecodeError:
log.exception()
except requests.JSONDecodeError as err:
log.exception(err)
version = None
tarball_url = None

Expand Down
4 changes: 2 additions & 2 deletions src/gui/pack_selector.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,8 @@ def set_package(self) -> None:
if new_pack:
try:
self.backend.set_package(new_pack)
except InterfaceMisuseError:
log.exception()
except InterfaceMisuseError as err:
log.exception(err)
self.valid_path = False
else:
self.valid_path = True
Expand Down
2 changes: 1 addition & 1 deletion src/gui/profile_selector.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@

from addwater import info
from addwater.apps.firefox import FirefoxPack
from addwater.profile import AppProfile
from addwater.model import AppProfile
from gi.repository import Adw, Gio, GObject, Gtk

log = logging.getLogger("profile_selector")
Expand Down
12 changes: 4 additions & 8 deletions src/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@
from addwater.backend import Backend
from gi.repository import Adw, Gio, GLib

from .utils import paths
from .utils.background import BackgroundUpdater
from .utils.logs import init_logs
from .window import Window
Expand All @@ -50,7 +49,6 @@ def __init__(self) -> None:
resource_base_path=info.PREFIX,
)

paths.init_paths()
init_logs()

self.init_actions()
Expand Down Expand Up @@ -127,15 +125,13 @@ def on_reset_app_action(self, *_args) -> None:
settings = Gio.Settings(info.APP_ID)
settings.reset("background-update")

# TODO delete theme files. Maybe add a method to tell
# AppTheme to clean up its data? Or make its dir
# public

for each in self.backends:
each.reset_app()

try:
shutil.rmtree(paths.DOWNLOAD_DIR)
except FileNotFoundError:
pass
log.info("deleted download folder")

log.info("app has been reset and will now exit")
self.quit()

Expand Down
Loading
Loading