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
4 changes: 2 additions & 2 deletions prek.toml
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ hooks = [
name = "Python lint (ruff check)",
entry = "uv run ruff check src/ tests/",
language = "system",
files = '\\.py$',
files = '\.py$',
pass_filenames = false,
priority = 0
},
Expand All @@ -72,7 +72,7 @@ hooks = [
name = "Python format check (ruff format)",
entry = "uv run ruff format --check src/ tests/",
language = "system",
files = '\\.py$',
files = '\.py$',
pass_filenames = false,
priority = 0
}
Expand Down
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] = []
Loading
Loading