sysetup 1.1.0__tar.gz → 1.2.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. {sysetup-1.1.0/src/sysetup.egg-info → sysetup-1.2.0}/PKG-INFO +3 -3
  2. {sysetup-1.1.0 → sysetup-1.2.0}/README.md +1 -1
  3. {sysetup-1.1.0 → sysetup-1.2.0}/pyproject.toml +10 -9
  4. {sysetup-1.1.0 → sysetup-1.2.0}/src/sysetup/cli/entry_point.py +1 -2
  5. sysetup-1.2.0/src/sysetup/context/context.py +31 -0
  6. sysetup-1.2.0/src/sysetup/main/environment.py +14 -0
  7. sysetup-1.2.0/src/sysetup/main/files/__init__.py +1 -0
  8. sysetup-1.2.0/src/sysetup/main/files/assets.py +40 -0
  9. sysetup-1.2.0/src/sysetup/main/files/permissions.py +33 -0
  10. sysetup-1.2.0/src/sysetup/main/files/settings.py +45 -0
  11. sysetup-1.2.0/src/sysetup/main/files/setup.py +8 -0
  12. sysetup-1.2.0/src/sysetup/main/installations.py +67 -0
  13. {sysetup-1.1.0 → sysetup-1.2.0}/src/sysetup/main/main.py +11 -7
  14. sysetup-1.2.0/src/sysetup/main/packages.py +60 -0
  15. {sysetup-1.1.0 → sysetup-1.2.0}/src/sysetup/models/__init__.py +0 -2
  16. {sysetup-1.1.0 → sysetup-1.2.0}/src/sysetup/models/action.py +1 -0
  17. {sysetup-1.1.0 → sysetup-1.2.0}/src/sysetup/models/path.py +1 -1
  18. sysetup-1.2.0/src/sysetup/utils/__init__.py +1 -0
  19. sysetup-1.2.0/src/sysetup/utils/download.py +12 -0
  20. {sysetup-1.1.0 → sysetup-1.2.0/src/sysetup.egg-info}/PKG-INFO +3 -3
  21. {sysetup-1.1.0 → sysetup-1.2.0}/src/sysetup.egg-info/SOURCES.txt +9 -4
  22. sysetup-1.2.0/src/sysetup.egg-info/entry_points.txt +3 -0
  23. {sysetup-1.1.0 → sysetup-1.2.0}/src/sysetup.egg-info/requires.txt +1 -1
  24. {sysetup-1.1.0 → sysetup-1.2.0}/tests/test_background.py +12 -7
  25. {sysetup-1.1.0 → sysetup-1.2.0}/tests/test_installer.py +1 -1
  26. sysetup-1.1.0/src/sysetup/context/context.py +0 -5
  27. sysetup-1.1.0/src/sysetup/main/environment.py +0 -12
  28. sysetup-1.1.0/src/sysetup/main/files.py +0 -96
  29. sysetup-1.1.0/src/sysetup/main/installer.py +0 -124
  30. sysetup-1.1.0/src/sysetup/models/config.py +0 -9
  31. sysetup-1.1.0/src/sysetup/models/secrets_.py +0 -11
  32. sysetup-1.1.0/src/sysetup.egg-info/entry_points.txt +0 -3
  33. {sysetup-1.1.0 → sysetup-1.2.0}/LICENSE +0 -0
  34. {sysetup-1.1.0 → sysetup-1.2.0}/bin/pw +0 -0
  35. {sysetup-1.1.0 → sysetup-1.2.0}/bin/pw-askpass +0 -0
  36. {sysetup-1.1.0 → sysetup-1.2.0}/setup.cfg +0 -0
  37. {sysetup-1.1.0 → sysetup-1.2.0}/src/sysetup/__init__.py +0 -0
  38. {sysetup-1.1.0 → sysetup-1.2.0}/src/sysetup/cli/__init__.py +0 -0
  39. {sysetup-1.1.0 → sysetup-1.2.0}/src/sysetup/context/__init__.py +0 -0
  40. {sysetup-1.1.0 → sysetup-1.2.0}/src/sysetup/main/__init__.py +0 -0
  41. {sysetup-1.1.0 → sysetup-1.2.0}/src/sysetup/models/options.py +0 -0
  42. {sysetup-1.1.0 → sysetup-1.2.0}/src/sysetup/py.typed +0 -0
  43. {sysetup-1.1.0 → sysetup-1.2.0}/src/sysetup.egg-info/dependency_links.txt +0 -0
  44. {sysetup-1.1.0 → sysetup-1.2.0}/src/sysetup.egg-info/top_level.txt +0 -0
  45. {sysetup-1.1.0 → sysetup-1.2.0}/tests/test_cli_entry_point.py +0 -0
  46. {sysetup-1.1.0 → sysetup-1.2.0}/tests/test_main.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: sysetup
3
- Version: 1.1.0
3
+ Version: 1.2.0
4
4
  Summary: Personal system setup
5
5
  Author-email: Quinten Roets <qdr2104@columbia.edu>
6
6
  License: MIT
@@ -8,7 +8,7 @@ Project-URL: Source Code, https://github.com/quintenroets/sysetup
8
8
  Requires-Python: >=3.10
9
9
  Description-Content-Type: text/markdown
10
10
  License-File: LICENSE
11
- Requires-Dist: backupmaster<2,>=1.2.2
11
+ Requires-Dist: backupmaster<2,>=1.2.6
12
12
  Requires-Dist: dbus-next<1,>=0.2.3
13
13
  Requires-Dist: package-utils[context]<1,>=0.6.1
14
14
  Requires-Dist: powercli<1,>=0.3.1
@@ -42,11 +42,11 @@ Requires-Dist: package-dev-utils<1,>=0.1.6; extra == "dev"
42
42
  * Enable GPU acceleration in chrome://flags
43
43
  * PDF viewer: set page zoom to page fit
44
44
  * Import certificate from Scripts/assets/sysetup/certificates/certificate.crt
45
+ * Click experimental: enable tab groups save and sync
45
46
  5) Login to
46
47
  * Pycharm professional
47
48
  * VNC Server
48
49
  6) For new device: set touchpad scroll direction and click on touch
49
- ## Usage
50
50
 
51
51
  ## Installation
52
52
  ```shell
@@ -21,11 +21,11 @@
21
21
  * Enable GPU acceleration in chrome://flags
22
22
  * PDF viewer: set page zoom to page fit
23
23
  * Import certificate from Scripts/assets/sysetup/certificates/certificate.crt
24
+ * Click experimental: enable tab groups save and sync
24
25
  5) Login to
25
26
  * Pycharm professional
26
27
  * VNC Server
27
28
  6) For new device: set touchpad scroll direction and click on touch
28
- ## Usage
29
29
 
30
30
  ## Installation
31
31
  ```shell
@@ -1,13 +1,13 @@
1
1
  [project]
2
2
  name = "sysetup"
3
- version = "1.1.0"
3
+ version = "1.2.0"
4
4
  description = "Personal system setup"
5
5
  authors = [{name = "Quinten Roets", email = "qdr2104@columbia.edu"}]
6
6
  license = {text = "MIT"}
7
7
  readme = "README.md"
8
8
  requires-python = ">=3.10"
9
9
  dependencies = [
10
- "backupmaster >=1.2.2, <2",
10
+ "backupmaster >=1.2.6, <2",
11
11
  "dbus-next >=0.2.3, <1",
12
12
  "package-utils[context] >=0.6.1, <1",
13
13
  "powercli >=0.3.1, <1",
@@ -27,7 +27,7 @@ dev = [
27
27
 
28
28
  [project.scripts]
29
29
  sysetup = "sysetup.cli:entry_point"
30
- exportcrontab = "sysetup.main.files:move_crontab"
30
+ exportcrontab = "sysetup.main.files.assets:move_crontab"
31
31
 
32
32
  [build-system]
33
33
  requires = ["setuptools"]
@@ -53,12 +53,13 @@ pythonpath = [
53
53
  fix = true
54
54
 
55
55
  [tool.ruff.lint]
56
- select = [
57
- "E", # pycodestyle errors
58
- "W", # pycodestyle warnings
59
- "F", # pyflakes
60
- "I", # isort
61
- "UP", # pyupgrade
56
+ select = ["ALL"]
57
+ ignore = [
58
+ "ANN101", # annotate self
59
+ "ANN102", # annotate cls
60
+ "ANN401", # annotated with Any
61
+ "D", # docstrings
62
+ "S101", # assert used
62
63
  ]
63
64
 
64
65
  [tool.ruff.lint.isort]
@@ -1,7 +1,6 @@
1
1
  from package_utils.context.entry_point import create_entry_point
2
2
 
3
+ from sysetup.context import context
3
4
  from sysetup.main.main import main
4
5
 
5
- from ..context import context
6
-
7
6
  entry_point = create_entry_point(main, context)
@@ -0,0 +1,31 @@
1
+ import os
2
+ from collections.abc import Iterator
3
+ from functools import cached_property
4
+
5
+ import cli
6
+ from package_utils.context import Context as Context_
7
+
8
+ from sysetup.models import Options
9
+
10
+
11
+ class Context(Context_[Options, None, None]):
12
+ @cached_property
13
+ def package_manager(self) -> str:
14
+ def generate_package_manager() -> Iterator[str]:
15
+ package_managers = "apt-get", "pacman"
16
+ for package_manager in package_managers:
17
+ if cli.completes_successfully("which", package_manager):
18
+ yield package_manager
19
+
20
+ return next(generate_package_manager())
21
+
22
+ @cached_property
23
+ def apt_is_installed(self) -> bool:
24
+ return self.package_manager == "apt-get"
25
+
26
+ @cached_property
27
+ def is_running_in_test(self) -> bool:
28
+ return "DISPLAY" not in os.environ
29
+
30
+
31
+ context = Context(Options)
@@ -0,0 +1,14 @@
1
+ import os
2
+
3
+ from dotenv import load_dotenv
4
+
5
+ from sysetup.models import Path
6
+ from sysetup.utils import download_file
7
+
8
+
9
+ def setup() -> None:
10
+ download_file(Path("etc") / "environment")
11
+ if "SUDO_ASKPASS" not in os.environ:
12
+ path = Path.HOME / ".bask_profile"
13
+ download_file(Path.HOME / ".bask_profile")
14
+ load_dotenv(dotenv_path=Path.HOME / path)
@@ -0,0 +1 @@
1
+ from .setup import setup
@@ -0,0 +1,40 @@
1
+ import cli
2
+ from backup.backups.cache import cache
3
+
4
+ from sysetup.models import Path
5
+ from sysetup.utils import download_directory
6
+
7
+
8
+ def setup() -> None:
9
+ download_directory(Path.assets)
10
+ move_crontab()
11
+ move_setup_files()
12
+
13
+
14
+ def move_crontab() -> None:
15
+ src = Path.assets / "crontab" / "crontab"
16
+ cli.run("crontab -", input=src.text)
17
+
18
+
19
+ def move_setup_files() -> None:
20
+ setup_files_root = Path.assets / "files"
21
+ setup_files = []
22
+ archived_setup_files = []
23
+ for path in setup_files_root.rglob("*"):
24
+ if path.is_file():
25
+ if path.archive_format is None:
26
+ setup_files.append(path)
27
+ else:
28
+ archived_setup_files.append(path)
29
+
30
+ backup = cache.Backup(paths=setup_files)
31
+ backup.pull()
32
+
33
+ for path in archived_setup_files:
34
+ dest = (backup.source / path.relative_to(setup_files_root)).parent
35
+ if dest.is_root and not dest.exists():
36
+ cli.run("mkdir -p", dest, root=True)
37
+ else:
38
+ dest.create_parent()
39
+ with cli.status(f"Unpacking {path.relative_to(setup_files_root)}"):
40
+ cli.capture_output("unzip -o", path, "-d", dest, root=dest.is_root)
@@ -0,0 +1,33 @@
1
+ import stat
2
+
3
+ import cli
4
+
5
+ from sysetup.models import Path
6
+ from sysetup.utils import download_directory
7
+
8
+
9
+ def setup() -> None:
10
+ set_git_permissions()
11
+ set_ssh_permissions()
12
+
13
+
14
+ def set_git_permissions() -> None:
15
+ git_hooks_folder = Path.HOME / ".config" / "git" / "hooks"
16
+ download_directory(git_hooks_folder)
17
+ for path in git_hooks_folder.iterdir():
18
+ cli.run("chmod +x", path)
19
+
20
+
21
+ def set_ssh_permissions() -> None:
22
+ directory = Path.HOME / ".ssh"
23
+ download_directory(directory)
24
+ for path in directory.glob("id_*"):
25
+ if path.suffix != ".pub":
26
+ check_permissions(path)
27
+
28
+
29
+ def check_permissions(path: Path) -> None:
30
+ permissions = path.stat().st_mode
31
+ other_users_can_read = permissions & (stat.S_IRGRP | stat.S_IROTH)
32
+ if other_users_can_read:
33
+ path.chmod(33152)
@@ -0,0 +1,45 @@
1
+ import cli
2
+
3
+ from sysetup.context import context
4
+ from sysetup.models import Path
5
+ from sysetup.utils import download_directory
6
+
7
+
8
+ def remove_clutter() -> None:
9
+ names = (
10
+ "Desktop",
11
+ "Downloads",
12
+ "Music",
13
+ "Pictures",
14
+ "Public",
15
+ "Templates",
16
+ "Videos",
17
+ )
18
+ for name in names:
19
+ path = Path.HOME / name
20
+ path.rmtree(missing_ok=True)
21
+
22
+ nginx_path = Path("/") / "etc" / "nginx" / "sites-enabled" / "default"
23
+ if nginx_path.exists():
24
+ cli.run("rm", nginx_path, root=True)
25
+
26
+
27
+ def set_background() -> None: # pragma: nocover
28
+ wallpaper_path = (
29
+ Path.HOME / ".local" / "share" / "wallpapers" / "Qwallpapers" / "background.jpg"
30
+ )
31
+ download_directory(wallpaper_path.parent)
32
+ wallpaper_uri = wallpaper_path.as_uri()
33
+ script = Path.update_wallpaper_script.text.replace(
34
+ "__wallpaper_uri__",
35
+ wallpaper_uri,
36
+ )
37
+ run_kde_script(script)
38
+
39
+
40
+ def run_kde_script(script: str) -> None: # pragma: nocover
41
+ command = (
42
+ "qdbus org.kde.plasmashell /PlasmaShell org.kde.PlasmaShell.evaluateScript"
43
+ )
44
+ if not context.is_running_in_test:
45
+ cli.run(command, script)
@@ -0,0 +1,8 @@
1
+ from sysetup.main.files import assets, permissions, settings
2
+
3
+
4
+ def setup() -> None:
5
+ permissions.setup()
6
+ assets.setup()
7
+ settings.set_background()
8
+ settings.remove_clutter()
@@ -0,0 +1,67 @@
1
+ import os
2
+
3
+ import cli
4
+
5
+ from sysetup.context import context
6
+ from sysetup.models import Path
7
+
8
+
9
+ def setup() -> None:
10
+ install_chromium()
11
+ install_jumpapp()
12
+ install_language_support()
13
+ install_linter_env()
14
+ install_personal_git_repositories()
15
+
16
+
17
+ def install_personal_git_repositories() -> None:
18
+ base_url = "https://github.com/quintenroets"
19
+ token = os.getenv("GITHUB", None)
20
+ if token is not None:
21
+ base_url = base_url.replace("github.com", f"{token}@github.com")
22
+ if not Path.extensions.exists():
23
+ command = f"git clone {base_url}/extensions.git"
24
+ cli.run(command, Path.extensions)
25
+ cli.run(f"pip install git+{base_url}/system.git")
26
+
27
+
28
+ def install_language_support() -> None:
29
+ try:
30
+ packages = cli.capture_output("check-language-support")
31
+ except FileNotFoundError:
32
+ pass
33
+ else:
34
+ if packages:
35
+ cli.install(packages)
36
+
37
+
38
+ def install_chromium() -> None:
39
+ if not cli.capture_output("which chromium-browser", check=False):
40
+ _install_chromium()
41
+
42
+
43
+ def _install_chromium() -> None:
44
+ release_name = cli.capture_output_lines("lsb_release -sc")[-1]
45
+ repo_url = f"https://freeshell.de/phd/chromium/{release_name}"
46
+ commands = (
47
+ f'echo "deb {repo_url} /" | sudo tee /etc/apt/sources.list.d/phd-chromium.list',
48
+ "apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 869689FE09306074",
49
+ "apt-get update",
50
+ "apt-get install -y chromium",
51
+ )
52
+ check = not context.is_running_in_test
53
+ cli.run_commands(*commands, shell=True, root=True, check=check) # noqa: S604
54
+
55
+
56
+ def install_linter_env() -> None:
57
+ if not Path.linter_env.exists():
58
+ cli.run("python -m venv", Path.linter_env.name, cwd=Path.linter_env.parent)
59
+ python_path = Path.linter_env / "bin" / "python"
60
+ cli.run(f"{python_path} -m pip install autoimport powertrace-hooks")
61
+
62
+
63
+ def install_jumpapp() -> None:
64
+ if not cli.capture_output("which jumpapp", check=False):
65
+ with Path.tempdir() as directory:
66
+ cli.run("git clone https://github.com/mkropat/jumpapp", directory)
67
+ cli.run_commands("make", "sudo make install", cwd=directory)
@@ -1,8 +1,9 @@
1
1
  import cli
2
2
 
3
- from ..context import context
4
- from ..models import Action
5
- from . import environment, files, installer
3
+ from sysetup.context import context
4
+ from sysetup.models import Action
5
+
6
+ from . import environment, files, installations, packages
6
7
 
7
8
 
8
9
  def main() -> None:
@@ -11,9 +12,10 @@ def main() -> None:
11
12
  """
12
13
  action_mapper = {
13
14
  Action.all.value: setup,
14
- Action.files.value: files.setup,
15
- Action.install.value: installer.setup,
16
15
  Action.env.value: environment.setup,
16
+ Action.files.value: files.setup,
17
+ Action.install.value: installations.setup,
18
+ Action.packages.value: packages.setup,
17
19
  }
18
20
  action = action_mapper[context.options.action.value]
19
21
  action()
@@ -21,6 +23,8 @@ def main() -> None:
21
23
 
22
24
  def setup() -> None:
23
25
  environment.setup()
26
+ packages.setup()
24
27
  files.setup()
25
- installer.setup()
26
- cli.run("reboot now", root=True)
28
+ installations.setup()
29
+ if not context.is_running_in_test:
30
+ cli.run("reboot now", root=True)
@@ -0,0 +1,60 @@
1
+ import cli
2
+
3
+ from sysetup.context import context
4
+ from sysetup.models import Path
5
+ from sysetup.utils import download_directory
6
+
7
+
8
+ def setup() -> None:
9
+ update_package_manager()
10
+ install_packages()
11
+ cleanup_after_install()
12
+
13
+
14
+ def install_packages() -> None:
15
+ download_directory(Path.packages)
16
+ installations = {"packages": None, "snap": "snap install"}
17
+ for name, command in installations.items():
18
+ path = (Path.packages / name).with_suffix(".yaml")
19
+ packages: list[str] = path.yaml
20
+ cli.install(*packages, install_command=command)
21
+
22
+
23
+ def update_package_manager() -> None:
24
+ if context.apt_is_installed:
25
+ update_apt()
26
+ else:
27
+ cli.run("pacman -Syy", root=True)
28
+
29
+
30
+ def update_apt() -> None:
31
+ agree_eula_command = (
32
+ "echo ttf-mscorefonts-installer msttcorefonts/accepted-mscorefonts-eula"
33
+ "select true | sudo debconf-set-selections"
34
+ )
35
+ commands = ["sudo apt-get update", agree_eula_command]
36
+ if not context.is_running_in_test:
37
+ # snap currently doesn't work on arm
38
+ commands.append("sudo systemctl enable --now snapd.socket")
39
+ cli.run_commands_in_shell(*commands)
40
+ if not Path("/snap").exists():
41
+ cli.run("ln -s /var/lib/snapd/snap /snap", root=True)
42
+
43
+
44
+ def cleanup_after_install() -> None:
45
+ after_install_command = (
46
+ "sudo apt-get autoremove -y"
47
+ if context.apt_is_installed
48
+ else (
49
+ "sudo pacman -S --noconfirm python-pip; sudo pacman -S --noconfirm"
50
+ " base-devel; pip install wheel"
51
+ )
52
+ )
53
+ cli.run_commands_in_shell(after_install_command, "sudo tlp start")
54
+ cli.run("systemctl enable ssh", root=True) # start ssh server before log in
55
+ delete = "apt purge -y" if context.apt_is_installed else "pacman -R --noconfirm"
56
+ commands = (
57
+ "auto-cpufreq --install", # Fails on VM
58
+ f"{delete} firefox", # fails if firefox not installed
59
+ )
60
+ cli.run_commands(*commands, check=False, root=True)
@@ -1,5 +1,3 @@
1
1
  from .action import Action
2
- from .config import Config
3
2
  from .options import Options
4
3
  from .path import Path
5
- from .secrets_ import Secrets
@@ -4,5 +4,6 @@ from enum import Enum
4
4
  class Action(str, Enum):
5
5
  all = "all"
6
6
  files = "files"
7
+ packages = "packages"
7
8
  install = "install"
8
9
  env = "env"
@@ -10,7 +10,7 @@ class Path(superpathlib.Path):
10
10
  @classmethod
11
11
  @classproperty
12
12
  def source_root(cls: type[T]) -> T:
13
- return cls(__file__).parent
13
+ return cls(__file__).parent.parent
14
14
 
15
15
  @classmethod
16
16
  @classproperty
@@ -0,0 +1 @@
1
+ from .download import download_directory, download_file
@@ -0,0 +1,12 @@
1
+ from backup.backups import Backup
2
+ from backup.models import Path as BackupPath
3
+
4
+ from sysetup.models import Path
5
+
6
+
7
+ def download_directory(path: Path) -> None:
8
+ Backup(sub_check_path=BackupPath(path), confirm=False).pull()
9
+
10
+
11
+ def download_file(path: Path) -> None:
12
+ Backup(path=BackupPath(path), confirm=False).pull()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: sysetup
3
- Version: 1.1.0
3
+ Version: 1.2.0
4
4
  Summary: Personal system setup
5
5
  Author-email: Quinten Roets <qdr2104@columbia.edu>
6
6
  License: MIT
@@ -8,7 +8,7 @@ Project-URL: Source Code, https://github.com/quintenroets/sysetup
8
8
  Requires-Python: >=3.10
9
9
  Description-Content-Type: text/markdown
10
10
  License-File: LICENSE
11
- Requires-Dist: backupmaster<2,>=1.2.2
11
+ Requires-Dist: backupmaster<2,>=1.2.6
12
12
  Requires-Dist: dbus-next<1,>=0.2.3
13
13
  Requires-Dist: package-utils[context]<1,>=0.6.1
14
14
  Requires-Dist: powercli<1,>=0.3.1
@@ -42,11 +42,11 @@ Requires-Dist: package-dev-utils<1,>=0.1.6; extra == "dev"
42
42
  * Enable GPU acceleration in chrome://flags
43
43
  * PDF viewer: set page zoom to page fit
44
44
  * Import certificate from Scripts/assets/sysetup/certificates/certificate.crt
45
+ * Click experimental: enable tab groups save and sync
45
46
  5) Login to
46
47
  * Pycharm professional
47
48
  * VNC Server
48
49
  6) For new device: set touchpad scroll direction and click on touch
49
- ## Usage
50
50
 
51
51
  ## Installation
52
52
  ```shell
@@ -17,15 +17,20 @@ src/sysetup/context/__init__.py
17
17
  src/sysetup/context/context.py
18
18
  src/sysetup/main/__init__.py
19
19
  src/sysetup/main/environment.py
20
- src/sysetup/main/files.py
21
- src/sysetup/main/installer.py
20
+ src/sysetup/main/installations.py
22
21
  src/sysetup/main/main.py
22
+ src/sysetup/main/packages.py
23
+ src/sysetup/main/files/__init__.py
24
+ src/sysetup/main/files/assets.py
25
+ src/sysetup/main/files/permissions.py
26
+ src/sysetup/main/files/settings.py
27
+ src/sysetup/main/files/setup.py
23
28
  src/sysetup/models/__init__.py
24
29
  src/sysetup/models/action.py
25
- src/sysetup/models/config.py
26
30
  src/sysetup/models/options.py
27
31
  src/sysetup/models/path.py
28
- src/sysetup/models/secrets_.py
32
+ src/sysetup/utils/__init__.py
33
+ src/sysetup/utils/download.py
29
34
  tests/test_background.py
30
35
  tests/test_cli_entry_point.py
31
36
  tests/test_installer.py
@@ -0,0 +1,3 @@
1
+ [console_scripts]
2
+ exportcrontab = sysetup.main.files.assets:move_crontab
3
+ sysetup = sysetup.cli:entry_point
@@ -1,4 +1,4 @@
1
- backupmaster<2,>=1.2.2
1
+ backupmaster<2,>=1.2.6
2
2
  dbus-next<1,>=0.2.3
3
3
  package-utils[context]<1,>=0.6.1
4
4
  powercli<1,>=0.3.1
@@ -5,13 +5,13 @@ import cli
5
5
  import pytest
6
6
  from backup.context import context
7
7
  from backup.utils import setup
8
- from sysetup.main.files import set_background
8
+ from sysetup.main.files.settings import set_background
9
9
  from sysetup.models import Path
10
10
 
11
11
  plasma_config_path = Path.HOME / ".config" / "plasma-org.kde.plasma.desktop-appletsrc"
12
12
 
13
13
 
14
- @pytest.fixture
14
+ @pytest.fixture()
15
15
  def restore(path: Path) -> Callable[[Path], Iterator[None]]:
16
16
  def _restore(restored_path: Path) -> Iterator[None]:
17
17
  exists = restored_path.exists()
@@ -24,9 +24,9 @@ def restore(path: Path) -> Callable[[Path], Iterator[None]]:
24
24
  return _restore
25
25
 
26
26
 
27
- @pytest.fixture
27
+ @pytest.fixture()
28
28
  def restore_and_check(
29
- path: Path, restore: Callable[[Path], Iterator[None]]
29
+ restore: Callable[[Path], Iterator[None]],
30
30
  ) -> Callable[[Path], Iterator[None]]:
31
31
  setup.check_setup()
32
32
  env = os.environ | {"RCLONE_CONFIG_PASS": context.secrets.rclone}
@@ -35,7 +35,10 @@ def restore_and_check(
35
35
  def _restore_and_check(restored_path: Path) -> Iterator[None]:
36
36
  def extract_content_hash() -> str:
37
37
  return cli.capture_output(
38
- "rclone hashsum MD5", restored_path, env=env, check=False
38
+ "rclone hashsum MD5",
39
+ restored_path,
40
+ env=env,
41
+ check=False,
39
42
  )
40
43
 
41
44
  content_hash = extract_content_hash()
@@ -45,14 +48,16 @@ def restore_and_check(
45
48
  return _restore_and_check
46
49
 
47
50
 
48
- @pytest.fixture
51
+ @pytest.fixture()
49
52
  def restore_config_path(
50
53
  restore_and_check: Callable[[Path], Iterator[None]],
51
54
  ) -> Iterator[None]:
52
55
  yield from restore_and_check(plasma_config_path)
53
56
 
54
57
 
55
- def test_wallpaper(restore_config_path: Callable[[Path], Iterator[None]]) -> None:
58
+ def test_wallpaper(
59
+ restore_config_path: Callable[[Path], Iterator[None]], # noqa: ARG001
60
+ ) -> None:
56
61
  # "org.kde.PlasmaShell.evaluateScript missing in GITHUB_ACTIONS"
57
62
  # still run existing test case to maximize code under coverage
58
63
  if "GITHUB_ACTIONS" not in os.environ:
@@ -1,7 +1,7 @@
1
1
  from unittest.mock import PropertyMock, patch
2
2
 
3
3
  import cli
4
- from sysetup.main.installer import install_linter_env
4
+ from sysetup.main.installations import install_linter_env
5
5
  from sysetup.models import Path
6
6
 
7
7
 
@@ -1,5 +0,0 @@
1
- from package_utils.context import Context
2
-
3
- from ..models import Config, Options, Secrets
4
-
5
- context = Context(Options, Config, Secrets)
@@ -1,12 +0,0 @@
1
- import os
2
-
3
- from backup.backups.remote import Backup
4
- from backup.models import Path
5
- from dotenv import load_dotenv
6
-
7
-
8
- def setup() -> None:
9
- if "SUDO_ASKPASS" not in os.environ:
10
- path = Path(".bash_profile")
11
- Backup(path=path).pull()
12
- load_dotenv(dotenv_path=Path.HOME / path)
@@ -1,96 +0,0 @@
1
- import cli
2
- from backup.backups import Backup
3
- from backup.backups.cache import cache
4
- from backup.models import Path as BackupPath
5
-
6
- from ..models import Path
7
-
8
-
9
- def setup() -> None:
10
- kwargs_mapper = {
11
- "Script assets": dict(sub_check_path=BackupPath.script_assets),
12
- "environment": dict(
13
- sub_check_path=BackupPath("/") / "etc",
14
- filter_rules=["+ /environment", "- *"],
15
- ),
16
- "setup files": dict(
17
- sub_check_path=BackupPath.script_assets / "sysetup" / "files"
18
- ),
19
- }
20
- for name, kwargs in kwargs_mapper.items():
21
- print(f"Downloading {name}..")
22
- Backup(confirm=False, **kwargs).pull()
23
-
24
- move_crontab()
25
- move_setup_files()
26
- set_permissions()
27
- set_background()
28
- remove_clutter()
29
-
30
-
31
- def remove_clutter() -> None:
32
- names = (
33
- "Desktop",
34
- "Downloads",
35
- "Music",
36
- "Pictures",
37
- "Public",
38
- "Templates",
39
- "Videos",
40
- )
41
- for name in names:
42
- path = Path.HOME / name
43
- path.rmtree()
44
-
45
- nginx_path = Path("/") / "etc" / "nginx" / "sites-enabled" / "default"
46
- if nginx_path.exists():
47
- cli.run("rm", nginx_path, root=True)
48
-
49
-
50
- def set_background() -> None: # pragma: nocover
51
- wallpaper_path = (
52
- Path.HOME / ".local" / "share" / "wallpapers" / "Qwallpapers" / "background.jpg"
53
- )
54
- wallpaper_uri = wallpaper_path.as_uri()
55
- script = Path.update_wallpaper_script.text.replace(
56
- "__wallpaper_uri__", wallpaper_uri
57
- )
58
- run_kde_script(script)
59
-
60
-
61
- def run_kde_script(script: str) -> None: # pragma: nocover
62
- command = (
63
- "qdbus org.kde.plasmashell /PlasmaShell org.kde.PlasmaShell.evaluateScript"
64
- )
65
- cli.run(command, script)
66
-
67
-
68
- def set_permissions() -> None:
69
- git_hooks_folder = Path.HOME / ".config" / "git" / "hooks"
70
- for path in git_hooks_folder.iterdir():
71
- cli.run("chmod +x", path)
72
-
73
-
74
- def move_crontab() -> None:
75
- src = Path.assets / "crontab" / "crontab"
76
- cli.run("crontab -", input=src.text)
77
-
78
-
79
- def move_setup_files() -> None:
80
- setup_files_root = BackupPath.script_assets / "sysetup" / "files"
81
- setup_files = []
82
- archived_setup_files = []
83
- for path in setup_files_root.rglob("*"):
84
- if path.is_file():
85
- if path.archive_format is None:
86
- setup_files.append(path)
87
- else:
88
- archived_setup_files.append(path)
89
-
90
- backup = cache.Backup(paths=setup_files)
91
- backup.pull()
92
-
93
- for path in archived_setup_files:
94
- dest = (backup.source / path.relative_to(setup_files_root)).parent
95
- with cli.status(f"Unpacking {path.relative_to(setup_files_root)}"):
96
- cli.capture_output("unzip -o", path, "-d", dest, root=dest.is_root)
@@ -1,124 +0,0 @@
1
- import cli
2
- from cli.commands.install import extract_package_manager_command
3
-
4
- from ..models import Path
5
-
6
-
7
- def setup() -> None:
8
- package_manager = "apt" if "apt" in extract_package_manager_command() else "pacman"
9
- update_package_manager(package_manager)
10
- install()
11
- install_chromium()
12
- install_extensions()
13
- install_jumpapp()
14
- install_language_support()
15
- install_linter_env()
16
- after_install(package_manager)
17
-
18
-
19
- def install_extensions() -> None:
20
- if not Path.extensions.exists():
21
- command = "git clone https://github.com/quintenroets/extensions"
22
- cli.run(command, cwd=Path.extensions.parent)
23
-
24
-
25
- def install_language_support() -> None:
26
- packages = cli.capture_output("check-language-support")
27
- cli.install(packages)
28
-
29
-
30
- def install_chromium() -> None:
31
- if not cli.capture_output("which chromium-browser", check=False):
32
- _install_chromium()
33
-
34
-
35
- def _install_chromium() -> None:
36
- release_name = cli.capture_output_lines("lsb_release -sc")[-1]
37
- repo_url = f"https://freeshell.de/phd/chromium/{release_name}"
38
- commands = (
39
- f'echo "deb {repo_url} /" | sudo tee /etc/apt/sources.list.d/phd-chromium.list',
40
- "apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 869689FE09306074",
41
- "apt-get update",
42
- "apt-get install -y chromium",
43
- )
44
- cli.run_commands(*commands, shell=True, root=True)
45
-
46
-
47
- def install_linter_env() -> None:
48
- if not Path.linter_env.exists():
49
- cli.run("python -m venv", Path.linter_env.name, cwd=Path.linter_env.parent)
50
- python_path = Path.linter_env / "bin" / "python"
51
- cli.run(f"{python_path} -m pip install autoimport powertrace-hooks")
52
-
53
-
54
- def install() -> None:
55
- installations = {
56
- "packages": None,
57
- "snap": "snap install",
58
- }
59
- for name, command in installations.items():
60
- path = (Path.packages / name).with_suffix(".yaml")
61
- packages: list[str] = path.yaml
62
- cli.install(*packages, install_command=command)
63
-
64
-
65
- def update_package_manager(package_manager: str) -> None:
66
- if package_manager == "apt":
67
- cli.run_commands_in_shell(
68
- "sudo apt update",
69
- # agree eula
70
- (
71
- "echo ttf-mscorefonts-installer msttcorefonts/accepted-mscorefonts-eula"
72
- "select true | sudo debconf-set-selections"
73
- ),
74
- "sudo systemctl enable --now snapd.socket",
75
- # snap currently doesnt work on arm
76
- )
77
- if not Path("/snap").exists():
78
- cli.run("ln -s /var/lib/snapd/snap /snap", root=True)
79
- elif package_manager == "pacman":
80
- cli.run("pacman -Syy", root=True)
81
- else:
82
- raise Exception("No package manager found")
83
-
84
-
85
- def after_install(package_manager: str) -> None:
86
- after_install_command = (
87
- "sudo apt autoremove -y"
88
- if package_manager == "apt"
89
- else (
90
- "sudo pacman -S --noconfirm python-pip; sudo pacman -S --noconfirm"
91
- " base-devel; pip install wheel"
92
- )
93
- )
94
- cli.run_commands_in_shell(after_install_command, "sudo tlp start")
95
- cli.run("systemctl enable ssh", root=True) # start ssh server before log in
96
-
97
- delete = "apt purge -y" if package_manager == "apt" else "pacman -R --noconfirm"
98
- cli.run_commands(
99
- "auto-cpufreq --install", # Fails on VM
100
- f"{delete} firefox", # fails if firefox not installed
101
- check=False,
102
- root=True,
103
- )
104
-
105
-
106
- def install_jumpapp() -> None:
107
- if not cli.capture_output("which jumpapp", check=False):
108
- cli.run("git clone https://github.com/mkropat/jumpapp")
109
- cli.run_commands("make", "sudo make install", cwd="jumpapp")
110
- cli.run("rm -rf jumpapp")
111
-
112
-
113
- def install_vpn() -> None:
114
- add_source_command = (
115
- 'echo "deb https://repo.windscribe.com/ubuntu bionic main" | sudo tee'
116
- " /etc/apt/sources.list.d/windscribe-repo.list"
117
- )
118
- commands = (
119
- "sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-key FDC247B7",
120
- add_source_command,
121
- "install windscribe-cli",
122
- )
123
- cli.run_commands_in_shell(*commands)
124
- # login: $email2
@@ -1,9 +0,0 @@
1
- from dataclasses import dataclass
2
-
3
- from superpathlib import Path
4
-
5
-
6
- @dataclass
7
- class Config:
8
- output_path: Path | None = None
9
- secrets_path: Path | None = None
@@ -1,11 +0,0 @@
1
- from dataclasses import dataclass
2
-
3
-
4
- @dataclass
5
- class ApiSecrets:
6
- token: str = "token"
7
-
8
-
9
- @dataclass
10
- class Secrets:
11
- api: ApiSecrets
@@ -1,3 +0,0 @@
1
- [console_scripts]
2
- exportcrontab = sysetup.main.files:move_crontab
3
- sysetup = sysetup.cli:entry_point
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes