Skip to content
Open
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ ignore = [
]

[tool.ruff.lint.per-file-ignores]
"**/tests/**/*.py" = ["S101", "SLF001"] # assert + private member access OK in tests
"**/tests/**/*.py" = ["S101", "S105", "S108", "SLF001"] # assert + test data + private access OK in tests

[tool.ruff.lint.isort]
known-first-party = ["mac2nix"]
Expand Down
108 changes: 106 additions & 2 deletions src/mac2nix/models/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,34 +3,92 @@
from mac2nix.models.application import (
ApplicationsResult,
AppSource,
BinarySource,
BrewCask,
BrewFormula,
BrewService,
HomebrewState,
InstalledApp,
MasApp,
PathBinary,
)
from mac2nix.models.files import (
AppConfigEntry,
AppConfigResult,
BundleEntry,
ConfigFileType,
DotfileEntry,
DotfileManager,
DotfilesResult,
FontCollection,
FontEntry,
FontSource,
FontsResult,
KeyBindingEntry,
LibraryAuditResult,
LibraryDirEntry,
LibraryFileEntry,
WorkflowEntry,
)
from mac2nix.models.hardware import (
AudioConfig,
AudioDevice,
DisplayConfig,
Monitor,
NightShiftConfig,
)
from mac2nix.models.package_managers import (
CondaEnvironment,
CondaPackage,
CondaState,
ContainerRuntimeInfo,
ContainerRuntimeType,
ContainersResult,
DevboxProject,
DevenvProject,
HomeManagerState,
MacPortsPackage,
MacPortsState,
ManagedRuntime,
NixChannel,
NixConfig,
NixDarwinState,
NixDirenvConfig,
NixFlakeInput,
NixInstallation,
NixInstallType,
NixProfile,
NixProfilePackage,
NixRegistryEntry,
NixState,
PackageManagersResult,
VersionManagerInfo,
VersionManagersResult,
VersionManagerType,
)
from mac2nix.models.hardware import AudioConfig, AudioDevice, DisplayConfig, Monitor
from mac2nix.models.preferences import PreferencesDomain, PreferencesResult, PreferenceValue
from mac2nix.models.services import (
CronEntry,
LaunchAgentEntry,
LaunchAgentSource,
LaunchAgentsResult,
LaunchdScheduledJob,
ScheduledTasks,
ShellConfig,
ShellFramework,
)
from mac2nix.models.system import (
FirewallAppRule,
ICloudState,
NetworkConfig,
NetworkInterface,
PrinterInfo,
SecurityState,
SystemConfig,
SystemExtension,
TimeMachineConfig,
VpnProfile,
)
from mac2nix.models.system import NetworkConfig, NetworkInterface, SecurityState, SystemConfig
from mac2nix.models.system_state import SystemState

__all__ = [
Expand All @@ -40,32 +98,78 @@
"ApplicationsResult",
"AudioConfig",
"AudioDevice",
"BinarySource",
"BrewCask",
"BrewFormula",
"BrewService",
"BundleEntry",
"CondaEnvironment",
"CondaPackage",
"CondaState",
"ConfigFileType",
"ContainerRuntimeInfo",
"ContainerRuntimeType",
"ContainersResult",
"CronEntry",
"DevboxProject",
"DevenvProject",
"DisplayConfig",
"DotfileEntry",
"DotfileManager",
"DotfilesResult",
"FirewallAppRule",
"FontCollection",
"FontEntry",
"FontSource",
"FontsResult",
"HomeManagerState",
"HomebrewState",
"ICloudState",
"InstalledApp",
"KeyBindingEntry",
"LaunchAgentEntry",
"LaunchAgentSource",
"LaunchAgentsResult",
"LaunchdScheduledJob",
"LibraryAuditResult",
"LibraryDirEntry",
"LibraryFileEntry",
"MacPortsPackage",
"MacPortsState",
"ManagedRuntime",
"MasApp",
"Monitor",
"NetworkConfig",
"NetworkInterface",
"NightShiftConfig",
"NixChannel",
"NixConfig",
"NixDarwinState",
"NixDirenvConfig",
"NixFlakeInput",
"NixInstallType",
"NixInstallation",
"NixProfile",
"NixProfilePackage",
"NixRegistryEntry",
"NixState",
"PackageManagersResult",
"PathBinary",
"PreferenceValue",
"PreferencesDomain",
"PreferencesResult",
"PrinterInfo",
"ScheduledTasks",
"SecurityState",
"ShellConfig",
"ShellFramework",
"SystemConfig",
"SystemExtension",
"SystemState",
"TimeMachineConfig",
"VersionManagerInfo",
"VersionManagerType",
"VersionManagersResult",
"VpnProfile",
"WorkflowEntry",
]
42 changes: 42 additions & 0 deletions src/mac2nix/models/application.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,27 @@ class AppSource(StrEnum):
MANUAL = "manual"


class BinarySource(StrEnum):
ASDF = "asdf"
BREW = "brew"
CARGO = "cargo"
CONDA = "conda"
GEM = "gem"
GO = "go"
JENV = "jenv"
MACPORTS = "macports"
MANUAL = "manual"
MISE = "mise"
NIX = "nix"
NPM = "npm"
NVM = "nvm"
PIPX = "pipx"
PYENV = "pyenv"
RBENV = "rbenv"
SDKMAN = "sdkman"
SYSTEM = "system"


class InstalledApp(BaseModel):
name: str
bundle_id: str | None = None
Expand All @@ -22,13 +43,25 @@ class InstalledApp(BaseModel):
source: AppSource


class PathBinary(BaseModel):
name: str
path: Path
source: BinarySource
version: str | None = None


class ApplicationsResult(BaseModel):
apps: list[InstalledApp]
path_binaries: list[PathBinary] = []
xcode_path: str | None = None
xcode_version: str | None = None
clt_version: str | None = None


class BrewFormula(BaseModel):
name: str
version: str | None = None
pinned: bool = False


class BrewCask(BaseModel):
Expand All @@ -42,8 +75,17 @@ class MasApp(BaseModel):
version: str | None = None


class BrewService(BaseModel):
name: str
status: str
user: str | None = None
plist_path: Path | None = None


class HomebrewState(BaseModel):
taps: list[str] = []
formulae: list[BrewFormula] = []
casks: list[BrewCask] = []
mas_apps: list[MasApp] = []
services: list[BrewService] = []
prefix: str | None = None
75 changes: 74 additions & 1 deletion src/mac2nix/models/files.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,22 @@
"""Dotfile, app config, and font models."""
"""Dotfile, app config, font, and library audit models."""

from __future__ import annotations

from datetime import datetime
from enum import StrEnum
from pathlib import Path
from typing import Any

from pydantic import BaseModel


class DotfileManager(StrEnum):
GIT = "git"
STOW = "stow"
CHEZMOI = "chezmoi"
YADM = "yadm"
HOME_MANAGER = "home_manager"
RCM = "rcm"
MANUAL = "manual"
UNKNOWN = "unknown"

Expand All @@ -20,6 +26,9 @@ class DotfileEntry(BaseModel):
content_hash: str | None = None
managed_by: DotfileManager = DotfileManager.UNKNOWN
symlink_target: Path | None = None
is_directory: bool = False
file_count: int | None = None
sensitive: bool = False


class DotfilesResult(BaseModel):
Expand All @@ -44,6 +53,7 @@ class AppConfigEntry(BaseModel):
file_type: ConfigFileType = ConfigFileType.UNKNOWN
content_hash: str | None = None
scannable: bool = True # False for databases
modified_time: datetime | None = None


class AppConfigResult(BaseModel):
Expand All @@ -61,5 +71,68 @@ class FontEntry(BaseModel):
source: FontSource


class FontCollection(BaseModel):
name: str
path: Path


class FontsResult(BaseModel):
entries: list[FontEntry]
collections: list[FontCollection] = []


class LibraryDirEntry(BaseModel):
name: str
path: Path
file_count: int | None = None
total_size_bytes: int | None = None
covered_by_scanner: str | None = None
has_user_content: bool = False
newest_modification: datetime | None = None


class LibraryFileEntry(BaseModel):
path: Path
file_type: str | None = None
content_hash: str | None = None
plist_content: dict[str, Any] | None = None
text_content: str | None = None
migration_strategy: str | None = None
size_bytes: int | None = None


class WorkflowEntry(BaseModel):
name: str
path: Path
identifier: str | None = None
workflow_definition: dict[str, Any] | None = None


class BundleEntry(BaseModel):
name: str
path: Path
bundle_id: str | None = None
version: str | None = None
bundle_type: str | None = None


class KeyBindingEntry(BaseModel):
key: str
action: str | dict[str, Any]


class LibraryAuditResult(BaseModel):
bundles: list[BundleEntry] = []
directories: list[LibraryDirEntry] = []
uncovered_files: list[LibraryFileEntry] = []
workflows: list[WorkflowEntry] = []
key_bindings: list[KeyBindingEntry] = []
spelling_words: list[str] = []
spelling_dictionaries: list[str] = []
input_methods: list[BundleEntry] = []
keyboard_layouts: list[str] = []
color_profiles: list[str] = []
compositions: list[str] = []
scripts: list[str] = []
text_replacements: list[dict[str, str]] = []
system_bundles: list[BundleEntry] = []
12 changes: 12 additions & 0 deletions src/mac2nix/models/hardware.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,25 @@
from pydantic import BaseModel


class NightShiftConfig(BaseModel):
enabled: bool | None = None
schedule: str | None = None


class Monitor(BaseModel):
name: str
resolution: str | None = None # e.g. "3456x2234"
scaling: float | None = None
retina: bool = False
arrangement_position: str | None = None # e.g. "primary", "left", "right"
refresh_rate: str | None = None
color_profile: str | None = None


class DisplayConfig(BaseModel):
monitors: list[Monitor] = []
night_shift: NightShiftConfig | None = None
true_tone_enabled: bool | None = None


class AudioDevice(BaseModel):
Expand All @@ -28,3 +37,6 @@ class AudioConfig(BaseModel):
default_input: str | None = None
default_output: str | None = None
alert_volume: float | None = None
output_volume: int | None = None
input_volume: int | None = None
output_muted: bool | None = None
Loading
Loading