Compare commits

...

2 Commits

Author SHA1 Message Date
pegasust f969912c08 flake lock 2023-08-01 00:36:14 -07:00
pegasust 7b5a6cfa94 feat(pixi): some repl around, cannot match heic with mov 2023-08-01 00:35:06 -07:00
10 changed files with 298 additions and 14 deletions

1
dev/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
__pycache__

101
dev/pixi/poetry.lock generated Normal file
View File

@ -0,0 +1,101 @@
# This file is automatically @generated by Poetry 1.5.1 and should not be changed by hand.
[[package]]
name = "colorama"
version = "0.4.6"
description = "Cross-platform colored terminal text."
optional = false
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7"
files = [
{file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"},
{file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"},
]
[[package]]
name = "exceptiongroup"
version = "1.1.2"
description = "Backport of PEP 654 (exception groups)"
optional = false
python-versions = ">=3.7"
files = [
{file = "exceptiongroup-1.1.2-py3-none-any.whl", hash = "sha256:e346e69d186172ca7cf029c8c1d16235aa0e04035e5750b4b95039e65204328f"},
{file = "exceptiongroup-1.1.2.tar.gz", hash = "sha256:12c3e887d6485d16943a309616de20ae5582633e0a2eda17f4e10fd61c1e8af5"},
]
[package.extras]
test = ["pytest (>=6)"]
[[package]]
name = "iniconfig"
version = "2.0.0"
description = "brain-dead simple config-ini parsing"
optional = false
python-versions = ">=3.7"
files = [
{file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"},
{file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"},
]
[[package]]
name = "packaging"
version = "23.1"
description = "Core utilities for Python packages"
optional = false
python-versions = ">=3.7"
files = [
{file = "packaging-23.1-py3-none-any.whl", hash = "sha256:994793af429502c4ea2ebf6bf664629d07c1a9fe974af92966e4b8d2df7edc61"},
{file = "packaging-23.1.tar.gz", hash = "sha256:a392980d2b6cffa644431898be54b0045151319d1e7ec34f0cfed48767dd334f"},
]
[[package]]
name = "pluggy"
version = "1.2.0"
description = "plugin and hook calling mechanisms for python"
optional = false
python-versions = ">=3.7"
files = [
{file = "pluggy-1.2.0-py3-none-any.whl", hash = "sha256:c2fd55a7d7a3863cba1a013e4e2414658b1d07b6bc57b3919e0c63c9abb99849"},
{file = "pluggy-1.2.0.tar.gz", hash = "sha256:d12f0c4b579b15f5e054301bb226ee85eeeba08ffec228092f8defbaa3a4c4b3"},
]
[package.extras]
dev = ["pre-commit", "tox"]
testing = ["pytest", "pytest-benchmark"]
[[package]]
name = "pytest"
version = "7.4.0"
description = "pytest: simple powerful testing with Python"
optional = false
python-versions = ">=3.7"
files = [
{file = "pytest-7.4.0-py3-none-any.whl", hash = "sha256:78bf16451a2eb8c7a2ea98e32dc119fd2aa758f1d5d66dbf0a59d69a3969df32"},
{file = "pytest-7.4.0.tar.gz", hash = "sha256:b4bf8c45bd59934ed84001ad51e11b4ee40d40a1229d2c79f9c592b0a3f6bd8a"},
]
[package.dependencies]
colorama = {version = "*", markers = "sys_platform == \"win32\""}
exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""}
iniconfig = "*"
packaging = "*"
pluggy = ">=0.12,<2.0"
tomli = {version = ">=1.0.0", markers = "python_version < \"3.11\""}
[package.extras]
testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"]
[[package]]
name = "tomli"
version = "2.0.1"
description = "A lil' TOML parser"
optional = false
python-versions = ">=3.7"
files = [
{file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"},
{file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"},
]
[metadata]
lock-version = "2.0"
python-versions = "^3.10"
content-hash = "1cf751550a88abe6c6ea8896fe41073f08488ebbd3fb959572a2038d4d944ebc"

20
dev/pixi/pyproject.toml Normal file
View File

@ -0,0 +1,20 @@
[tool.poetry]
name = "pixi"
version = "0.0.1"
description = "Toy project to investigate about apple photos synced iphone -> mac"
authors = ["Pegasust <pegasucksgg@gmail.com>"]
readme = "README.md"
[tool.poetry.dependencies]
python = "^3.10"
[tool.poetry.group.dev.dependencies]
pytest = "^7.3.1"
[[tool.poetry.packages]]
include = "repl"
[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"

View File

@ -0,0 +1,118 @@
#!/usr/bin/env python
"""
REPL-friendly python mono-module for importing and execution singleton
"""
import os
from dataclasses import dataclass
from itertools import groupby
from typing import Iterable
mac_photos = os.getenv("MAC_PHOTOS_PATH", default="mac_photos")
@dataclass(slots=True, frozen=True)
class PhotosKExt:
name: str
parent: tuple[str, ...]
exts_lowered: tuple[str, ...]
@classmethod
def from_root_file(cls, root: str, filename: str):
ext_elems = filename.split('.')
return cls(
name=ext_elems[0],
parent=os.path.split(root),
exts_lowered=tuple(
ext.lower() for ext in ext_elems[1:]
)
)
@dataclass(slots=True, frozen=True)
class PhotosKey:
filename: str
parent: tuple[str, ...]
@classmethod
def from_key_ext(cls, ext: PhotosKExt):
return cls(filename=ext.name, parent=ext.parent)
@dataclass(slots=True)
class PhotosValue:
exts: dict[str, list[str]]
def heic_paths(self) -> list[str]:
return self.exts.get("heic", list())
def mov_paths(self) -> list[str]:
return self.exts.get("mov", list())
def candidate_exts(file_exts: Iterable[PhotosKExt]):
"""
>>> {ext: len(files)for ext, files in cexts.items()}
stdout> {... 'mov': 2769, 'heic': 2354 ...}
We could make a bold guess that iPhone 11 stores both `heic` and `mov`
for materialized best capture and live movie for live capture.
"""
exts_rv: dict[str, list[PhotosKExt]] = dict()
for file in file_exts:
for ext in file.exts_lowered:
exts_rv.setdefault(ext, list()).append(file)
return exts_rv
def file_exts(photos_dir: str = mac_photos):
return {
PhotosKExt.from_root_file(filename=file, root=root)
for root, _, files in os.walk(photos_dir, followlinks=True)
for file in files
}
def photos_exts(files_with_ext: Iterable[PhotosKExt]):
return {
k: list(v)
for k, v in groupby(files_with_ext, key=lambda x: (x.name, x.parent))
}
def main():
fexts = file_exts()
cexts = candidate_exts(fexts)
print(f"{photos_exts(fexts)=}")
print(f"{cexts=}")
ext_counts = {ext: len(files)for ext, files in cexts.items()}
print(ext_counts)
# stdout>
"""
{'jpeg': 6023, 'mov': 2769, 'heic': 2354, 'thm': 197, 'png': 168, 'plist': 163,
'log': 1, 'aae': 102, 'kgdb': 3, 'mp4': 26, 'data': 3, 'db': 3, 'xml': 26,
'cmap': 2, 'plj': 16, 'kgdb-wal': 3, 'sqlite-shm': 11, 'cloudphotodb-wal': 1,
'kgdb-shm': 3, '00001]': 1, 'frag': 2, 'ithmb': 3, 'sqlite': 15, 'lock': 1,
'sqlite-wal': 11, 'aoi': 3, '0': 1,
'm3u8-8f37dbfb-b3a6-4d52-beca-d17aaed01606': 2, 'jpg': 2, 'roi': 3, 'poi': 3,
'db-shm': 1, 'm3u8-37f64716-0b2d-4a82-854a-5a6c78ce505a': 1, 'descriptor': 3,
'bin': 2, 'm3u8': 5, 'cloudphotodb': 1, 'db-wal': 1, 'nature': 3,
'm3u8-d8faad08-4fcc-4161-a600-1562d755c97b': 1, 'initfrag': 2, '20201]': 1,
'cloudphotodb-shm': 1}
"""
movs = cexts['mov']
heics = cexts['heic']
heic_name_set = {heic.name.lower() for heic in heics}
mov_name_set = {mov.name.lower() for mov in movs}
print(len(heic_name_set - mov_name_set) - len(heic_name_set))
# stdout> (not 0)
# Hence, we are not able to match `.heic` with its `.mov` with just names
# Could it be that the `.heic` also contains the high-quality live?
if __name__ == "__main__":
main()

View File

@ -811,11 +811,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1689495092, "lastModified": 1690846837,
"narHash": "sha256-yZu2j5FpLZEPhJQQutMCPTxa1VMigLPabLYvLTq6ASM=", "narHash": "sha256-ZZ8YPOEdZG0zz61U4sfUAx28oEdqLdtG1iWTTH/98uc=",
"owner": "nix-community", "owner": "nix-community",
"repo": "home-manager", "repo": "home-manager",
"rev": "2f84579a70b8c74e5ebb37299a0c3ba279f09382", "rev": "4fd794d3df88735dcf9662155d77b08a2e2dde29",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -1011,11 +1011,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1689479461, "lastModified": 1690687539,
"narHash": "sha256-Ak+PTYdmfOQEmcOsOEnrwqdP0HP20PLraRwpjSAzSeE=", "narHash": "sha256-Lnwz9XKtshm+5OeWqCbj/3tKuKK+DL5tUTdKSRrKBlY=",
"owner": "mic92", "owner": "mic92",
"repo": "nix-index-database", "repo": "nix-index-database",
"rev": "22fa44b7f14684d184733fb26a628f3878ff7aaf", "rev": "d74b8171153ae35d7d323a9b1ad6c4cf7a995591",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -1168,11 +1168,11 @@
}, },
"nixpkgs-latest": { "nixpkgs-latest": {
"locked": { "locked": {
"lastModified": 1689615243, "lastModified": 1690872690,
"narHash": "sha256-FbR3tYDggqSekDd2Yv+t/mY6n1F+2JOCpYBB0HVH38M=", "narHash": "sha256-vrU9U97zVpq+H4qJ4iywYNmxGbK4Y0bN2Q/vUcgVrQE=",
"owner": "nixos", "owner": "nixos",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "14ef6934ca5cdf2a17c0dda30d4bf3d3e8ecff23", "rev": "714bd4a3e3cc6d97dea0c658942204ef4d66fce5",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -1267,11 +1267,11 @@
}, },
"nixpkgs_11": { "nixpkgs_11": {
"locked": { "locked": {
"lastModified": 1689534811, "lastModified": 1690789960,
"narHash": "sha256-jnSUdzD/414d94plCyNlvTJJtiTogTep6t7ZgIKIHiE=", "narHash": "sha256-3K+2HuyGTiJUSZNJxXXvc0qj4xFx1FHC/ItYtEa7/Xs=",
"owner": "nixos", "owner": "nixos",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "6cee3b5893090b0f5f0a06b4cf42ca4e60e5d222", "rev": "fb942492b7accdee4e6d17f5447091c65897dde4",
"type": "github" "type": "github"
}, },
"original": { "original": {

View File

@ -58,6 +58,7 @@
cellBlocks = let cellBlocks = let
inherit (std.blockTypes) devshells functions anything installables runnables; inherit (std.blockTypes) devshells functions anything installables runnables;
in [ in [
(installables "shells")
(devshells "devshells") (devshells "devshells")
(devshells "userShells") (devshells "userShells")
(functions "home-profiles") (functions "home-profiles")
@ -69,9 +70,12 @@
]; ];
} }
{ {
devShells = std.harvest self [["dotfiles" "devshells"]]; devShells = std.harvest self [["dotfiles" "devshells"] ["dev" "shells"]];
homeModules = std.pick self [["repo" "home-modules"]]; homeModules = std.pick self [["repo" "home-modules"]];
packages = std.harvest self [["repo" "packages"]]; packages = std.harvest self [
["repo" "packages"]
["dev" "packages"]
];
legacyPackages = std.harvest self [["repo" "home-configs"]]; legacyPackages = std.harvest self [["repo" "home-configs"]];
lib = std.pick self [["repo" "lib"]]; lib = std.pick self [["repo" "lib"]];

1
mac_photos Symbolic link
View File

@ -0,0 +1 @@
/Users/hungtran/Pictures/Photos Library.photoslibrary

22
nix/dev/packages.nix Normal file
View File

@ -0,0 +1,22 @@
{
inputs,
cell,
}: let
inherit (inputs.nixpkgs) system;
poetry2nix = inputs.nix-boost.inputs.poetry2nix.legacyPackages.${system};
pixi-src = "${inputs.self}/dev/pixi";
in {
pixi-deps = poetry2nix.mkPoetryEnv {
projectDir = pixi-src;
editablePackageSources = {
pixi = pixi-src;
};
};
pixi-edit = poetry2nix.mkPoetryEditablePackage {
projectDir = pixi-src;
editablePackageSources = {
pixi = pixi-src;
};
};
}

15
nix/dev/shells.nix Normal file
View File

@ -0,0 +1,15 @@
{
inputs,
cell,
}: let
inherit (inputs.nixpkgs) system;
inherit (cell.packages) pixi-deps pixi-edit;
in {
pixi = inputs.nixpkgs.mkShell {
buildInputs = [
pixi-deps
# pixi-edit
inputs.std.packages.${system}.default
];
};
}

View File

@ -34,4 +34,6 @@ in {
description = "Wrapper for keepassxc and keepassxc-cli with additional Darwin-specific fixes"; description = "Wrapper for keepassxc and keepassxc-cli with additional Darwin-specific fixes";
}; };
}; };
pixi-edit = inputs.cells.dev.packages.pixi-edit;
} }