bppicker 0.2.3__tar.gz → 0.2.4__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.
- {bppicker-0.2.3 → bppicker-0.2.4}/CHANGELOG.md +29 -1
- {bppicker-0.2.3 → bppicker-0.2.4}/PKG-INFO +9 -5
- {bppicker-0.2.3 → bppicker-0.2.4}/README.md +8 -4
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/__init__.py +1 -1
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/cli.py +21 -0
- bppicker-0.2.4/bpp/commands/selfcheck.py +147 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/commands/serve.py +3 -0
- bppicker-0.2.4/bpp/web/wsgi_bind.py +40 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/docs/architecture-notes.md +6 -3
- {bppicker-0.2.3 → bppicker-0.2.4}/docs/macos-signing.md +9 -1
- {bppicker-0.2.3 → bppicker-0.2.4}/pyproject.toml +1 -1
- {bppicker-0.2.3 → bppicker-0.2.4}/scripts/third_party_bundled.py +101 -6
- bppicker-0.2.4/tests/test_desktop_shell_boot.py +241 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_hardening_regressions.py +3 -3
- bppicker-0.2.4/tests/test_selfcheck.py +174 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_sidecar_entry.py +5 -3
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_sidecar_hidden_imports.py +19 -5
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_third_party_inventory.py +100 -4
- bppicker-0.2.4/tests/test_wsgi_bind.py +83 -0
- bppicker-0.2.3/tests/test_desktop_shell_boot.py +0 -131
- {bppicker-0.2.3 → bppicker-0.2.4}/.eslint-globals.json +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/.gitignore +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/CODE_OF_CONDUCT.md +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/CONTRIBUTING.md +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/Dockerfile +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/LICENSE +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/MANIFEST.in +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/MODEL_POLICY.md +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/NOTICE.txt +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/SECURITY.md +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/ai/__init__.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/ai/inpainting.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/commands/__init__.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/commands/analyze.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/commands/db_restore.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/commands/db_restore_impl.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/commands/demo.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/commands/model.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/commands/model_attribution.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/commands/model_commands.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/commands/pick.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/config.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/config_builtins.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/config_resolver.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/config_schema.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/constants.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/db/__init__.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/db/album_photos.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/db/albums.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/db/backup.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/db/batch_rename.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/db/calendar.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/db/clip.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/db/connection.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/db/dedupe.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/db/dialect.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/db/edits.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/db/event_hooks.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/db/face_cluster_ids.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/db/face_cluster_ops.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/db/face_embedding_safety.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/db/face_feedback.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/db/face_identity_remap.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/db/face_name_matching.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/db/face_name_placement.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/db/face_name_relocate.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/db/face_queries.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/db/face_same_photo.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/db/face_switch_finish.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/db/face_switch_record.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/db/groups.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/db/integrity.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/db/journal.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/db/library.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/db/library_copy.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/db/live_photo.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/db/live_photo_scan.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/db/memories.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/db/migrate.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/db/migrations.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/db/migrations_latest.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/db/migrations_recent.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/db/moments.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/db/people_placement.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/db/pets.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/db/photo_hooks.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/db/photos.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/db/photos_dates.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/db/photos_gps.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/db/photos_lifecycle.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/db/photos_missing.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/db/photos_sha.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/db/photos_updates.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/db/presets.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/db/registry.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/db/schema.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/db/schema_migrate.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/db/settings.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/db/smart_album_builtins.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/db/smart_album_document.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/db/smart_album_domains.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/db/smart_album_ensure.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/db/smart_album_groups.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/db/smart_album_people.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/db/smart_album_pets.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/db/smart_album_queries.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/db/smart_album_refreshers.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/db/smart_album_sensitive.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/db/smart_album_tags.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/db/smart_albums.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/db/sql_batches.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/db/stats.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/db/tags.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/dedupe/__init__.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/dedupe/cluster.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/dedupe/common.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/dedupe/phash.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/dedupe/select.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/dedupe/semantic.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/dedupe/strategy.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/demo/__init__.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/demo/generate.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/errors.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/exif_utils.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/io_scan.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/media_types.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/output/__init__.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/output/export.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/output/export_metadata.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/output/export_modes.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/output/export_pixels.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/output/export_reports.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/output/gallery.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/plugin_protocol.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/plugins/__init__.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/plugins/example.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/plugins/registry_protocol.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/registry/__init__.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/registry/acceptance.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/registry/acceptance_log.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/registry/acceptance_log_files.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/registry/acceptance_log_parse.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/registry/attribution_bundle.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/registry/builtins.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/registry/builtins_bundled.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/registry/byom.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/registry/derived_data_purge.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/registry/disclaimers.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/registry/download_chokepoint.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/registry/labels.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/registry/manifest_rollback.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/registry/model_registry.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/registry/overlay.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/registry/policy.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/registry/remote_registry.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/registry/removal.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/registry/signed_manifest.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/registry/trusted_keys.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/registry/use_context.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/registry/use_context_store.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/scoring/__init__.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/scoring/_registry_base.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/scoring/aggregate.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/scoring/aggregate_video.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/scoring/blur.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/scoring/clip_embed.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/scoring/clip_tokenizer.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/scoring/composition.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/scoring/cpu_support.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/scoring/enhance.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/scoring/exposure.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/scoring/face.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/scoring/face_blazeface_fr.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/scoring/face_cluster.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/scoring/face_detector_registry.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/scoring/face_embed.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/scoring/face_embed_buffalo.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/scoring/face_embed_buffalo_s.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/scoring/face_embed_detect.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/scoring/face_embed_extractors.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/scoring/face_embed_landmarks.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/scoring/face_embed_plugin.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/scoring/face_embed_sface.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/scoring/face_embed_sface_runtime.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/scoring/face_embedder_registry.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/scoring/face_expression.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/scoring/face_fallback.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/scoring/face_hand_filter.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/scoring/face_mediapipe.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/scoring/face_pipeline.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/scoring/face_recognition_loader.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/scoring/face_score.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/scoring/face_scrfd.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/scoring/face_threshold.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/scoring/face_yunet.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/scoring/inference_log.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/scoring/install_hold.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/scoring/model_base.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/scoring/model_download.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/scoring/model_lifecycle.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/scoring/model_load_gate.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/scoring/model_manifest.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/scoring/models/blaze_face_short_range.tflite +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/scoring/nudity.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/scoring/onnx_providers.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/scoring/pets.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/scoring/pose.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/scoring/registry.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/scoring/segmentation.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/scoring/skin.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/scoring/toggles.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/selection/__init__.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/selection/choose.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/selection/diversity.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/utils/__init__.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/utils/cancel.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/utils/concurrency.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/utils/config_snapshot.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/utils/download.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/utils/fresh_file.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/utils/json_utils.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/utils/logging.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/utils/path_validation.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/utils/paths.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/utils/raw.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/utils/retry.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/utils/safe_subprocess.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/utils/serving_lock.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/utils/subprocess_runner.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/utils/timing.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/utils/video.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/__init__.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/_deprecated_attr.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/album_siblings.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/analysis_store.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/analyze_archive.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/analyze_face_extract.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/analyze_finalize.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/analyze_model_preflight.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/analyze_phases.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/analyze_run_steps.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/analyze_scoring.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/analyze_subprocess.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/analyze_worker.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/app.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/auth_boundary.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/base_worker.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/box_crop.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/bp_album_overrides.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/bp_albums.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/bp_analysis.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/bp_attribution.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/bp_calendar.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/bp_catalog.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/bp_clip.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/bp_core.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/bp_export.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/bp_faces.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/bp_faces_bbox.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/bp_faces_cluster_ops.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/bp_faces_extract.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/bp_faces_manage.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/bp_faces_photo.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/bp_faces_recluster.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/bp_faces_review.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/bp_groups.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/bp_health.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/bp_inpaint.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/bp_install.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/bp_library.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/bp_logs.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/bp_media.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/bp_memories.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/bp_model_admin.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/bp_model_registry.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/bp_models.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/bp_os_integration.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/bp_pets.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/bp_photos.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/bp_photos_lifecycle.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/bp_photos_manage.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/bp_photos_missing.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/bp_recompute.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/bp_search.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/bp_settings.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/bp_share.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/bp_tags.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/catalog_loaders.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/clip_cap.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/clip_worker.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/derived_recovery.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/download_gates.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/e2e_fixture.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/export_worker.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/face_create_helpers.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/face_crop.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/face_extraction_journal.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/face_extraction_phase5.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/face_extraction_phase6.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/face_extraction_phases.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/face_lock.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/face_merge_core.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/face_method_reconcile.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/face_orchestrator.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/face_phase_classes.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/face_phase_pipeline.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/face_phase_types.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/face_recovery.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/face_worker.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/faces_review_match.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/filters.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/health.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/host_allowlist.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/import_worker.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/install_busy.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/install_specs.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/install_status.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/install_stream.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/lan_redaction.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/library_lifecycle.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/media_support.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/model_cache.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/model_download_jobs.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/model_filter.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/models_status.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/paging.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/permanent_delete.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/photo_cache.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/photo_dict.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/photo_edits.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/picker_fields.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/pip_process.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/recompute.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/request_validation.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/review_meta.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/share.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/share_devices.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/share_proxy.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/share_qr.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/share_runtime.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/sse.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/state.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/state_compat.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/state_helpers.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/state_init.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/state_init_phases.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/state_lifecycle.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/state_ops.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/state_startup_steps.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/css/app.css +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/img/apple-touch-icon.png +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/img/icon-192.png +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/img/icon-512.png +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/globals.js +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/action-registry.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/activity-humanize.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/activity-log.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/albums-menus.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/albums-render-helpers.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/albums-render-smart.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/albums-render.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/albums-switch.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/albums.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/analysis-install.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/analysis-preflight.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/analysis-recompute.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/analysis-status.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/analysis.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/api-client.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/app.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/attribution-consent.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/batch-rename.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/boot-health.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/boot-proof.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/calendar-render.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/calendar-selection.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/calendar.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/client-error-beacon.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/clip.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/compare-sibling.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/compare.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/constants.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/core.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/date-format.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/deleted-ctx-menu.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/deleted-enhance.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/deleted.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/dialog-focus.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/dialogs.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/download-jobs.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/dupe-review.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/editor-constants.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/editor-crop.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/editor-inpaint.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/editor-preview.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/editor-redeye.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/editor-rendering.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/editor-styles.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/editor-tools.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/editor.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/face-embedders-acceptance.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/face-embedders-actions.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/face-embedders-busy.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/face-embedders-catalog.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/face-embedders-cells.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/face-embedders-guesses.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/face-embedders-license.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/face-embedders-menu-render.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/face-embedders-popover.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/face-embedders-row-facts.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/face-embedders-rowstate.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/face-embedders-state.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/faces-extraction.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/faces.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/format-helpers.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/groups.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/import-worker.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/inspector.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/install-done.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/library.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/lightbox-actions.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/lightbox-ctxmenu.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/lightbox-face-assign.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/lightbox-face-commit.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/lightbox-face-edit.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/lightbox-face-overlays.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/lightbox-face-picker-actions.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/lightbox-face-picker.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/lightbox-info.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/lightbox-input.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/lightbox-open.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/lightbox.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/map.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/memories.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/menu-a11y.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/modal.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/modals-face-embedders.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/modals.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/models-changed.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/moments-stacks.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/moments-view.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/native-pick.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/navigation.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/nudges.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/on-this-day.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/onboarding.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/paging.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/people-actions.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/people-album-bar.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/people-ctx-menu.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/people-merge.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/people-pair-review.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/people-pickers.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/people-rename.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/people-review-card.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/people-review.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/people-view.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/people.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/pets-pickers.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/pets.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/phash-status.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/photo-preview.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/photos-batch.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/photos-card.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/photos-grid-filter.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/photos-helpers.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/photos-hover.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/photos-select.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/photos-vgrid.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/photos.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/picker-overlay.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/presets.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/review-meta.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/score-format.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/search-results-html.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/search.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/sensitive.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/settings-client.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/share-tab.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/sidebar-safety.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/slideshow.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/state.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/tags-view.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/tags.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/text-format.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/theme.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/timeline.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/toast.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/toolbar.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/tooltip.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/tour.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/ui-helpers.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/update-checker.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/use-context-options.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/utils.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/view-guard.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/js/modules/wizard.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/manifest.json +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/vendor/README.md +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/vendor/leaflet/LICENSE +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/vendor/leaflet/dist/images/layers-2x.png +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/vendor/leaflet/dist/images/layers.png +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/vendor/leaflet/dist/images/marker-icon-2x.png +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/vendor/leaflet/dist/images/marker-icon.png +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/vendor/leaflet/dist/images/marker-shadow.png +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/vendor/leaflet/dist/leaflet.css +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/vendor/leaflet/dist/leaflet.js +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/vendor/leaflet.markercluster/MIT-LICENCE.txt +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/vendor/leaflet.markercluster/dist/MarkerCluster.Default.css +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/vendor/leaflet.markercluster/dist/MarkerCluster.css +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/static/vendor/leaflet.markercluster/dist/leaflet.markercluster.js +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/templates/index.html +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/templates/loopback_locked.html +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/templates/pair.html +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/templates/pair_needs_link.html +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/thumbnails.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/update_checker.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/worker_pool.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/bpp/web/worker_registry.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/docs/API.md +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/docs/adding-a-model.md +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/docs/adr/0001-subprocess-runner.md +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/docs/adr/0002-cancellation-contract.md +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/docs/adr/0003-plugin-protocol.md +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/docs/adr/0004-error-hierarchy.md +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/docs/adr/0005-legal-posture-and-model-registry.md +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/docs/adr/README.md +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/docs/configuration.md +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/docs/landing/assets/02-lightbox-1600.webp +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/docs/landing/assets/02-lightbox-900.webp +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/docs/landing/assets/03-faces-1600.webp +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/docs/landing/assets/03-faces-900.webp +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/docs/landing/assets/10-duplicates-1600.webp +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/docs/landing/assets/10-duplicates-900.webp +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/docs/landing/assets/apple-touch-icon.png +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/docs/landing/assets/demo-960.mp4 +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/docs/landing/assets/demo-poster.jpg +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/docs/landing/assets/demo-poster.webp +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/docs/landing/assets/demo.mp4 +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/docs/landing/assets/favicon-32.png +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/docs/landing/assets/favicon-64.png +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/docs/landing/assets/favicon.svg +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/docs/landing/assets/og.jpg +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/docs/landing/index.html +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/docs/plugins.md +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/docs/quickstart-gallery.md +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/docs/security.md +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/examples/plugin_example/README.md +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/examples/plugin_example/bpp_example_plugin/__init__.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/examples/plugin_example/bpp_example_plugin/plugin.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/examples/plugin_example/pyproject.toml +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/launch.command.template +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/sample_config.yaml +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/scripts/check_no_bundled_weights.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/scripts/export_clip_onnx.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/scripts/extract-js-names.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/scripts/function-loc.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/scripts/generate-eslint-globals.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/scripts/generate_demo_library.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/scripts/publish_registry_manifest.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/scripts/run_e2e.sh +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/scripts/run_mock_registry.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/scripts/setup_e2e_library.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/scripts/sign_registry_manifest.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/scripts/third_party_inventory.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/scripts/third_party_sources.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/scripts/verify_live_registry.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/__init__.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/_authorize_request_shared.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/_blueprint_coverage_shared.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/_bp_analysis_photos_shared.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/_clip_shared.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/_clustering_stability_shared.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/_coverage_gaps_shared.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/_db_restore_command_shared.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/_db_shared.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/_detector_stubs.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/_enhance_shared.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/_export_sidecar_shared.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/_export_utils_shared.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/_face_extraction_journal_shared.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/_face_landmark_validation_shared.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/_face_name_preservation_shared.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/_face_review_flow_shared.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/_face_scan_scoring_shared.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/_faces_create_shared.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/_faces_new_endpoints_shared.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/_git.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/_install_support.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/_integration_shared.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/_js_source_scan_shared.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/_log_redaction_shared.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/_media_state_shared.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/_model_quality_shared.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/_models.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/_packaging_shared.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/_plugin_loader_shared.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/_recompute_coverage_shared.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/_robustness_shared.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/_smart_album_coverage_shared.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/_trust_proxy_shared.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/_video_shared.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/_web_shared.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/conftest.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/owner_only/__init__.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/owner_only/_owner.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/owner_only/conftest.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/owner_only/test_install_info_owner_only.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/owner_only/test_owner_only_endpoints.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/owner_only/test_owner_only_mutations.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/owner_only/test_owner_only_paths.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/registry/__init__.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/registry/_acceptance_shared.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/registry/_download_chokepoint_shared.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/registry/_model_registry_shared.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/registry/conftest.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/registry/test_acceptance.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/registry/test_acceptance_endpoint_status.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/registry/test_acceptance_revocation.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/registry/test_acceptance_row_coercion.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/registry/test_acceptance_state.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/registry/test_acceptance_strict_answers.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/registry/test_attribution_bundle.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/registry/test_attribution_bundle_endpoints.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/registry/test_buffalo_s_entry.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/registry/test_byom.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/registry/test_catalog_weights_endpoints.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/registry/test_default_safety.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/registry/test_download_chokepoint.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/registry/test_download_chokepoint_single_gate.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/registry/test_download_status_gate.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/registry/test_load_state_endpoints.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/registry/test_manifest_rollback.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/registry/test_model_policy.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/registry/test_model_registry.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/registry/test_picker_entry_fields.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/registry/test_policy.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/registry/test_primary_for_kind.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/registry/test_redownload_legal_map.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/registry/test_removal.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/registry/test_restricted_entries.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/registry/test_runtime_enforcement.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/registry/test_signed_manifest.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/registry/test_stale_acceptance.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/registry/test_surface_parity.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/scoring/test_face_embed_buffalo_s.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/scoring/test_runtime_reset.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_acceptance_log_fail_closed.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_activity_log.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_album_hierarchy.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_album_type_constants.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_analysis_store.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_analyze_downstream_uses_worker_ctx.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_analyze_preflight_licenses.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_analyze_preflight_toggles.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_analyze_worker.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_api_doc_no_dead_params.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_api_doc_response_fields.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_api_doc_status_and_install_state.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_api_versioning.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_attr_interpolation_safety.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_auth_token.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_authorize_request.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_authorize_request_constant_time_token_compare.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_auto_purge_containment.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_auto_purge_journaled_with_cache_cleanup.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_auto_restore_uses_backup_wal.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_base_worker_error_emit.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_batch_name_sanitize.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_batch_rename.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_batch_rename_apply_refreshes.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_batching_and_layering.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_blueprint_coverage.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_blueprint_coverage_album_override.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_blueprint_coverage_album_workflow.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_blueprint_coverage_faces_merge.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_blueprint_coverage_faces_restore.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_blueprints.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_bp_analysis_photos.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_bp_analysis_photos_api_batch_favorite.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_bp_analysis_photos_api_export.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_bp_library.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_bulk_untag_batch.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_bundled_model_gating.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_cache_cleanup_on_delete.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_cache_invalidation_audit.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_cache_suffix_registry.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_cached_image_lock.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_calendar.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_cancel.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_cancel_propagation.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_catalog_loader_registry.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_cli_model_accept_attribution.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_cli_pick.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_cli_plugin_lifecycle.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_clip.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_clip_matrix_cache.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_clip_memory.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_clip_search.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_clip_semantic_deduplicate.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_clip_worker_cancel.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_clustering_stability.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_clustering_stability_as_completed_order_bug.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_clustering_stability_edges.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_clustering_stability_reanalysis_preserves_cluster_ids.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_commands.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_config_fallbacks_match_defaults.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_config_resolver.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_config_schema.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_config_snapshot.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_constants.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_container_rough_edges.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_coverage_gaps.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_coverage_gaps_core_blueprint_gaps.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_coverage_gaps_schema_migrations.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_csp.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_db.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_db_connection_count.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_db_migration.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_db_restore_command.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_db_restore_command_restore_proceeds_after_corrupt_quarantine_cleanup.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_db_restore_command_running_server_lock.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_db_smart_albums.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_dedupe_defaults.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_dedupe_one_path.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_dedupe_phash.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_dedupe_strategy_registry.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_default_library_isolation.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_demo.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_desktop_failure_screens.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_dialect.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_diversity.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_dlib_acceptance_gate.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_docker_healthcheck.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_docs_paths_exist.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_download.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_dupe_review.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_embedding_size_contract.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_empty_states.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_endpoint_docstrings.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_enhance.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_enhance_apply_advanced_edits.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_enhance_apply_edits.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_enhance_blur.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_enhance_new_apply_edits.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_env_var_docs.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_errors.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_errors_flask_handler.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_eslint_globals_generator.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_exif.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_exif_parse_cache.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_export_disk_full.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_export_metadata_fail_closed.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_export_mode_registry.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_export_never_writes_through_links.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_export_process_orientation.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_export_raw_converted.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_export_resized_strips_metadata.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_export_sidecar.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_export_sidecar_export_selected_manifest.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_export_sync_uses_shared_validation.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_export_utils.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_export_utils_export_metadata_privacy.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_export_utils_generate_gallery.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_export_utils_setup_logging.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_export_worker.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_export_zip_keeps_existing_files.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_face_cap.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_face_chunk_clustering.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_face_cluster_id_safety.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_face_cluster_map_cache.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_face_cluster_map_invalidated_after_extraction.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_face_cluster_ops.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_face_count_sync.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_face_data_safety_round2.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_face_data_safety_round3.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_face_data_safety_round4.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_face_detector_single_binding.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_face_embed_detect.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_face_embedding_method_dispatch.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_face_embedding_safety.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_face_extract_batching.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_face_extraction_journal.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_face_extraction_journal_orchestrator_resume.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_face_extraction_journal_resume_recaptures_dismissed_slots.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_face_extraction_journal_ship_criterion6k_signal_injection.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_face_extraction_max_long_side.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_face_extraction_phases.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_face_extraction_phases_late.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_face_extraction_wal_checkpoint.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_face_fallback_blocked.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_face_feedback.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_face_group_photos.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_face_grouping_threshold.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_face_identity_boundaries.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_face_identity_by_face.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_face_landmark_validation.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_face_landmark_validation_tiled_detection.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_face_lock_coverage.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_face_lock_timeout.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_face_name_final_placement.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_face_name_matching.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_face_name_placement.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_face_name_preservation.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_face_name_preservation_empty_cluster_guard.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_face_name_retry_and_tags.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_face_name_switch.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_face_name_switch_edges.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_face_no_dlib_second_try.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_face_pipeline.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_face_recognition_loader.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_face_recovery_serialized.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_face_recovery_thread.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_face_registries.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_face_review_e2e.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_face_review_flow.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_face_scan_scoring.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_face_scan_scoring_hamming_distance.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_face_scan_scoring_suppress_hand_faces.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_face_switch_album_contents.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_face_switch_coverage.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_face_switch_guard.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_face_switch_races.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_face_switch_resume.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_face_thread_safety.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_face_worker_row_factory.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_faces_create.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_faces_create_new_person.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_faces_new_endpoints.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_faces_new_endpoints_embedding_validation.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_faces_photo_bbox_dims.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_faces_update_bbox.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_final_sweep_lifecycle.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_final_sweep_perf.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_fresh_file.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_function_loc_cap.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_get_handlers_survive_write_failure.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_gps_columns_migration.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_gps_pagination.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_groups.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_health_and_startup_logging.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_health_endpoint.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_health_install_downloads_phash.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_heif_registration.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_host_allowlist.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_image_decode_cap.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_import_crash_safety.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_import_raw_and_video_by_default.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_import_scoring_settings.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_init_app_db_helpers.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_inpainting.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_install_claims.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_install_hold.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_install_left_over.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_install_paired_devices.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_install_progress.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_install_refusals.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_integration.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_integration_library_switch_workflow.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_item14_followups.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_journal.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_journal_recovery.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_js_source_scan.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_js_source_scan_critical_function_refs.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_js_source_scan_mobile_lightbox.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_json_set_aside.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_json_shape.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_lan_payload_paths.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_large_library_caps.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_layering_endpoint_helpers.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_libraries_paths.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_library_binding.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_library_lifecycle.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_library_rename_traversal.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_library_switch.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_license_check_per_photo.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_licenses.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_live_photo.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_live_photo_detect_and_link.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_loc_cap.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_log_redaction.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_log_redaction_werkzeug_redaction.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_loopback_boot_key.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_map.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_max_content_length.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_media_auth_integration.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_media_state.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_media_state_build_photo_dict.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_media_state_check_dedup_feedback.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_media_state_thumbnail_verified_integration.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_media_types.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_mediapipe_inference_failures_logged.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_mediapipe_thread_safety.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_memories.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_memory_soak.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_migration_multi_step.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_missing_coverage.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_missing_files_guard.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_missing_scan_flag_lifecycle.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_missing_scan_refusal_surfaced.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_model_cache.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_model_constants_documented.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_model_download_jobs.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_model_download_locks.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_model_download_robustness.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_model_license_single_source.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_model_license_status.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_model_load_gate_freshness.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_model_manifest.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_model_quality.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_model_quality_pose_classification.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_model_registry.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_model_singleton.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_model_singleton_unpinned.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_models_pending_endpoint.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_moments.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_mypy_gate.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_nas_resilience.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_near_duplicate_clusters.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_no_duplicate_test_names.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_no_import_cycles.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_no_third_party_cdn.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_nudity.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_nudity_active_switch.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_nudity_decode.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_nudity_download.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_nudity_integrity.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_nudity_label_validation.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_on_this_day.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_onnx_providers.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_open_folder_restrict.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_orphan_person_albums.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_packaging.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_packaging_docs_consistency.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_pair_endpoints.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_pair_status_touch.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_pairing_requires_share_token.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_parallel_map_window.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_path_validation_helper.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_paths.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_pattern_lint.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_perf_assign_new_faces_vectorized.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_perf_cache_cleanup_no_listing.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_perf_face_cluster_blocked.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_perf_face_clusters_no_decode.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_perf_groups_single_pass.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_perf_jpeg_draft.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_perf_live_photo_backfill_queries.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_perf_pagination.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_perf_phash_backfill_batches.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_perf_semantic_pass2_blocked.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_perf_top_rated_refresh.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_perf_yunet_detector_reuse.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_permanent_delete_guard.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_permanent_delete_quarantine_edges.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_permanent_delete_recycle_bin.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_persist_atomicity.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_pet_cluster_iou_match.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_pet_crop_cache_key.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_pets.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_pets_pet_detections_crud.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_pets_smart_albums.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_phash_backfill_throttle.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_phash_generation_guard.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_photo_cache_edit_sweep.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_photo_dict_typed.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_photo_hooks.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_photo_summary_builders.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_photos_pagination.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_picker_tables_in_sync.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_pip_process.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_pipeline_fixes.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_plugin_albums_exports_hooks.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_plugin_extensibility.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_plugin_face_backends.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_plugin_lifecycle_and_indexed_smart_person.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_plugin_loader.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_plugin_loader_loader_respects_version_requirement.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_plugin_models_visible.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_plugin_protocol.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_plugin_run_toggle_handoff.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_plugin_switch_in_picker.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_plugin_toggle_keys.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_plugin_weight_keys_lazy.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_plugins_doc_claims.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_polish_features.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_post_cluster_dispatch.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_privacy_claims.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_property_exif.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_property_paths.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_property_share.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_raw.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_raw_decode.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_raw_full_photo_edits.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_raw_readers.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_reanalyze_keeps_provenance.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_recent_hidden.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_recompute_coverage.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_recompute_coverage_optimize.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_recompute_dedupe_cache.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_recompute_override_clamp.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_recovery_library_bound.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_redeye_points.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_refresh_domains_used.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_refresh_smart_albums_kinds.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_registry.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_registry_protocol.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_release_hardening.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_remap_person_tags.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_rename_overwrite_guard.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_request_validation.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_review_meta.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_robustness.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_robustness_first_run_api.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_robustness_per_step_migration_backup.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_route_registration.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_sample_config_defaults.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_scan_extensions_config.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_scan_progress.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_scan_skips_internal_dirs_deep.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_scorer_registry.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_scores_sync.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_scoring_blur.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_scoring_subprocess.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_scrfd.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_scrfd_license_gate.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_search.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_search_like_escape.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_security_endpoints.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_sensitive.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_serve_debug_flag.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_serve_host_default.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_serve_log_handler_ordering.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_serving_lock.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_settings_ui.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_share.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_share_access_log.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_share_auth_gate.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_share_cookie.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_share_db.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_share_devices.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_share_endpoints.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_share_schema_migration.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_share_token_rotation_backups.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_smart_album_coverage.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_smart_album_coverage_thumbnail_cache.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_smart_album_presentation.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_smart_album_queries.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_smart_album_registry.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_smart_album_unique.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_smart_person_cluster_id_v36.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_smoke.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_sql_variable_limit.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_sse_event.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_sse_shared_stream.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_ssl_context_normalization.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_startup_backup_failure_is_not_corruption.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_startup_integrity_gate.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_state_change_logging.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_state_compat_delegates_logged.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_stats.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_subprocess_runner.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_subprocess_runner_user_message.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_tag_rename_collision.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_tags.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_thumbnail_write_safety.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_timeline.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_trim_export_rename_safety.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_trust_proxy.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_trust_proxy_behind_proxy_gated_by_trusted_networks.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_update_checker.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_video.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_video_metadata_db.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_video_trim_updates_row.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_web.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_web_batch_routes.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_web_face_recluster.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_whole_tree_review_batch2.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_whole_tree_review_batch3.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_whole_tree_review_batch3b.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_whole_tree_review_fixes.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_worker_finalize.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_worker_pool.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_worker_registry.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_workers.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_yunet_sface.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_yunet_sface_acceptance_gate.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests/test_yunet_sface_integrity.py +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/_albums-setup.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/_analysis-setup.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/_deleted-setup.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/_editor-setup.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/_install-helpers.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/_lightbox-setup.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/_photos-setup.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/_toolbar-setup.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/action-registry.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/activity-humanize.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/activity-log.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/albums-presentation.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/albums-render-album-nav.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/albums-smart-album-context-menu.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/albums.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/analysis-refresh-status-right.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/analysis.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/api-client.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/attribution-consent.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/batch-rename.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/boot-health.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/boot-proof.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/calendar-keys-scope.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/calendar.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/cards-keyboard.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/client-error-beacon.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/clip.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/compare-sibling.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/compare.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/core.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/ctx-menu-shortcuts.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/date-format.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/deleted-batch-enhance.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/deleted.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/dialog-focus.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/dialogs.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/dispatcher.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/download-jobs.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/dupe-review.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/editor-crop.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/editor-inpaint.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/editor-redeye.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/editor.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/escape-order.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/face-embedders-blocker-text.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/face-embedders-escape.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/face-embedders-license-badge.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/face-embedders-load-failures.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/face-embedders-load-state.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/face-embedders-primary.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/face-embedders-reaccept.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/face-embedders-run-toggle.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/faces-reextract.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/faces.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/final-sweep-ui.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/format-helpers.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/function-loc-cap.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/groups.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/import-worker.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/inspector.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/install-done.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/install-packages-note.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/install-prompts.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/library.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/lightbox-add-face.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/lightbox-bbox-edit.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/lightbox-ctx-menu-clamp.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/lightbox-esc-dialog.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/lightbox-face-edit.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/lightbox-lb-delete.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/lightbox-map-guard.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/lightbox-map.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/lightbox.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/map.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/media-error-reload.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/media-url-auth.regression.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/memories.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/menu-a11y.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/menu-actions.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/modal.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/modals-face-embedders-busy-gate.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/modals-face-embedders-derive-row-state.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/modals-face-embedders-redownload-face-embedder-entry.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/modals-face-embedders-status-cell-menu-agree.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/modals-face-embedders.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/modals.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/models-changed-wiring.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/models-changed.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/moments-stacks.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/moments-view.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/mutation-error-toasts.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/native-pick.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/nav-keyboard.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/navigation.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/no-local-escAttr.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/nudges.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/on-this-day.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/onboarding-use-context.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/onboarding.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/optimistic-handlers.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/paging.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/pair-page.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/pair-review-escape.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/pass-event-pattern.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/pattern-lint.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/people-actions.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/people-merge-bulk.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/people-merge-override-revert.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/people-pair-review.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/people-rename.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/people-review-esc.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/people-view-load.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/people-view.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/pet-crop-url.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/pets.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/phash-status.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/photo-load-error.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/photo-preview.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/photos-apply-zoom.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/photos-card-moment-preserve.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/photos-card-moment.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/photos-keynav.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/photos.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/picker-overlays.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/picker-server-fields.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/presets.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/review-meta.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/review15-ui-races.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/score-format.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/search-seq.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/search.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/sensitive.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/settings-client.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/settings-models-load.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/share-tab.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/sidebar-safety.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/sliders-delegation.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/slideshow.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/state.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/tags-view.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/tags.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/text-format.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/theme.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/timeline.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/toast.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/toolbar.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/tooltip.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/tour.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/types/globals.d.ts +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/ui-helpers.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/update-checker.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/use-context-options.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/utils.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/view-guard.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/whole-tree-review-batch2.module.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/window-pollution.test.mjs +0 -0
- {bppicker-0.2.3 → bppicker-0.2.4}/tests-js/wizard.module.test.mjs +0 -0
|
@@ -6,6 +6,33 @@ this project follows [Semantic Versioning](https://semver.org/).
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
## [0.2.4] — 2026-11-14
|
|
10
|
+
|
|
11
|
+
### Fixed
|
|
12
|
+
- **The Mac app starts again on Macs where its server took longer than
|
|
13
|
+
30 seconds** ("Server failed to start"). The server used to unpack
|
|
14
|
+
itself, about 1 GB, into a temporary folder on every launch, and macOS
|
|
15
|
+
checked those new files each time. It now ships ready to run inside
|
|
16
|
+
the app, so a start takes about a second; the first start after an
|
|
17
|
+
install or update takes longer while macOS checks the new files. The
|
|
18
|
+
app now waits up to two minutes and says when a first start takes a
|
|
19
|
+
while.
|
|
20
|
+
- **The server no longer waits on a network name lookup before it opens
|
|
21
|
+
its port.** On macOS that lookup could hold the start for about 35
|
|
22
|
+
seconds.
|
|
23
|
+
- **Try Again on the "failed to start" screen starts over cleanly.** It
|
|
24
|
+
used to leave the previous server running, so the new one collided
|
|
25
|
+
with it.
|
|
26
|
+
- **Quitting the Mac app stops its server.** Quitting with ⌘Q, the app
|
|
27
|
+
menu or the Dock left the server running in the background until the
|
|
28
|
+
next launch.
|
|
29
|
+
|
|
30
|
+
### Added
|
|
31
|
+
- `bpp selfcheck` loads the native libraries the desktop app bundles and
|
|
32
|
+
reports any that is missing or won't load. The Mac app's release check
|
|
33
|
+
runs it in the signed app, along with a check that the server starts
|
|
34
|
+
quickly.
|
|
35
|
+
|
|
9
36
|
## [0.2.3] — 2026-11-03
|
|
10
37
|
|
|
11
38
|
### Added
|
|
@@ -618,7 +645,8 @@ External calls are limited to documented features:
|
|
|
618
645
|
desktop wrapper currently builds only the macOS bundle.
|
|
619
646
|
- Python 3.11 only (CI tests this version; 3.12+ is unvalidated).
|
|
620
647
|
|
|
621
|
-
[Unreleased]: https://github.com/Arkalogy/best-photo-picker/compare/v0.2.
|
|
648
|
+
[Unreleased]: https://github.com/Arkalogy/best-photo-picker/compare/v0.2.4...HEAD
|
|
649
|
+
[0.2.4]: https://github.com/Arkalogy/best-photo-picker/releases/tag/v0.2.4
|
|
622
650
|
[0.2.3]: https://github.com/Arkalogy/best-photo-picker/releases/tag/v0.2.3
|
|
623
651
|
[0.2.2]: https://github.com/Arkalogy/best-photo-picker/releases/tag/v0.2.2
|
|
624
652
|
[0.2.1]: https://github.com/Arkalogy/best-photo-picker/releases/tag/v0.2.1
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: bppicker
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.4
|
|
4
4
|
Summary: Local-first photo curation tool — score, deduplicate, and select the best photos from large collections
|
|
5
5
|
Project-URL: Homepage, https://github.com/Arkalogy/best-photo-picker
|
|
6
6
|
Project-URL: Repository, https://github.com/Arkalogy/best-photo-picker
|
|
@@ -65,7 +65,7 @@ Description-Content-Type: text/markdown
|
|
|
65
65
|
|
|
66
66
|
# Best Photo Picker
|
|
67
67
|
|
|
68
|
-
[](https://github.com/Arkalogy/best-photo-picker/actions/workflows/ci.yml)
|
|
68
|
+
[](https://github.com/Arkalogy/best-photo-picker/actions/workflows/ci.yml)
|
|
69
69
|
[](https://pypi.org/project/bppicker/)
|
|
70
70
|
[](https://github.com/Arkalogy/best-photo-picker/blob/main/LICENSE)
|
|
71
71
|
[](https://www.python.org/downloads/)
|
|
@@ -537,6 +537,10 @@ bpp model {list|accept|accept-attribution|accepted|use-context|byom|remove|regis
|
|
|
537
537
|
`accept-attribution` accepts every built-in
|
|
538
538
|
Apache 2.0 / BSD-style model in one step.
|
|
539
539
|
bpp db restore-backup --library PATH [--previous] [--yes] [--accept-stale] [--force]
|
|
540
|
+
bpp selfcheck [--require-all]
|
|
541
|
+
— loads the native libraries the desktop app bundles
|
|
542
|
+
(opens no photo library) and names any that is missing
|
|
543
|
+
or won't load. The optional dlib backend isn't checked.
|
|
540
544
|
|
|
541
545
|
Global: --extensions STR (default: every supported photo, camera RAW and video format)
|
|
542
546
|
```
|
|
@@ -656,7 +660,7 @@ cd desktop && npm run dev
|
|
|
656
660
|
For a standalone `.app` bundle (launchable from Finder/Spotlight):
|
|
657
661
|
|
|
658
662
|
```bash
|
|
659
|
-
# Build
|
|
663
|
+
# Build the server (PyInstaller-bundled Python server, as a helper app)
|
|
660
664
|
cd desktop && ./build-sidecar.sh
|
|
661
665
|
|
|
662
666
|
# Build .app + .dmg
|
|
@@ -664,7 +668,7 @@ npm run build
|
|
|
664
668
|
# Output: desktop/src-tauri/target/release/bundle/
|
|
665
669
|
```
|
|
666
670
|
|
|
667
|
-
The
|
|
671
|
+
The server lands at `desktop/src-tauri/helpers/bpp-server.app`, and the app carries it in `Contents/Helpers/`. `desktop/bpp-server.spec` is the PyInstaller build (layout, hidden imports, signing).
|
|
668
672
|
|
|
669
673
|
> **Note:** A build you make yourself isn't signed with an Apple Developer ID, so Gatekeeper will block it the first time. To open it: right-click → Open → Open (once). The release DMG and the app inside are signed with a Developer ID and notarized by Apple, so they open normally.
|
|
670
674
|
|
|
@@ -701,7 +705,7 @@ bpp/
|
|
|
701
705
|
templates/index.html # Single-page HTML shell
|
|
702
706
|
desktop/
|
|
703
707
|
src-tauri/ # Tauri v2 Rust app
|
|
704
|
-
build-sidecar.sh #
|
|
708
|
+
build-sidecar.sh # builds the server helper app (bpp-server.spec)
|
|
705
709
|
scripts/dev-macos.sh # Dev launcher
|
|
706
710
|
```
|
|
707
711
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Best Photo Picker
|
|
2
2
|
|
|
3
|
-
[](https://github.com/Arkalogy/best-photo-picker/actions/workflows/ci.yml)
|
|
3
|
+
[](https://github.com/Arkalogy/best-photo-picker/actions/workflows/ci.yml)
|
|
4
4
|
[](https://pypi.org/project/bppicker/)
|
|
5
5
|
[](https://github.com/Arkalogy/best-photo-picker/blob/main/LICENSE)
|
|
6
6
|
[](https://www.python.org/downloads/)
|
|
@@ -472,6 +472,10 @@ bpp model {list|accept|accept-attribution|accepted|use-context|byom|remove|regis
|
|
|
472
472
|
`accept-attribution` accepts every built-in
|
|
473
473
|
Apache 2.0 / BSD-style model in one step.
|
|
474
474
|
bpp db restore-backup --library PATH [--previous] [--yes] [--accept-stale] [--force]
|
|
475
|
+
bpp selfcheck [--require-all]
|
|
476
|
+
— loads the native libraries the desktop app bundles
|
|
477
|
+
(opens no photo library) and names any that is missing
|
|
478
|
+
or won't load. The optional dlib backend isn't checked.
|
|
475
479
|
|
|
476
480
|
Global: --extensions STR (default: every supported photo, camera RAW and video format)
|
|
477
481
|
```
|
|
@@ -591,7 +595,7 @@ cd desktop && npm run dev
|
|
|
591
595
|
For a standalone `.app` bundle (launchable from Finder/Spotlight):
|
|
592
596
|
|
|
593
597
|
```bash
|
|
594
|
-
# Build
|
|
598
|
+
# Build the server (PyInstaller-bundled Python server, as a helper app)
|
|
595
599
|
cd desktop && ./build-sidecar.sh
|
|
596
600
|
|
|
597
601
|
# Build .app + .dmg
|
|
@@ -599,7 +603,7 @@ npm run build
|
|
|
599
603
|
# Output: desktop/src-tauri/target/release/bundle/
|
|
600
604
|
```
|
|
601
605
|
|
|
602
|
-
The
|
|
606
|
+
The server lands at `desktop/src-tauri/helpers/bpp-server.app`, and the app carries it in `Contents/Helpers/`. `desktop/bpp-server.spec` is the PyInstaller build (layout, hidden imports, signing).
|
|
603
607
|
|
|
604
608
|
> **Note:** A build you make yourself isn't signed with an Apple Developer ID, so Gatekeeper will block it the first time. To open it: right-click → Open → Open (once). The release DMG and the app inside are signed with a Developer ID and notarized by Apple, so they open normally.
|
|
605
609
|
|
|
@@ -636,7 +640,7 @@ bpp/
|
|
|
636
640
|
templates/index.html # Single-page HTML shell
|
|
637
641
|
desktop/
|
|
638
642
|
src-tauri/ # Tauri v2 Rust app
|
|
639
|
-
build-sidecar.sh #
|
|
643
|
+
build-sidecar.sh # builds the server helper app (bpp-server.spec)
|
|
640
644
|
scripts/dev-macos.sh # Dev launcher
|
|
641
645
|
```
|
|
642
646
|
|
|
@@ -18,7 +18,7 @@ _os.environ.setdefault("OPENCV_IO_MAX_IMAGE_PIXELS", str(200_000_000))
|
|
|
18
18
|
# the first import.
|
|
19
19
|
_os.environ.setdefault("NO_ALBUMENTATIONS_UPDATE", "1")
|
|
20
20
|
|
|
21
|
-
__version__ = "0.2.
|
|
21
|
+
__version__ = "0.2.4"
|
|
22
22
|
APP_NAME = "Best Photo Picker"
|
|
23
23
|
|
|
24
24
|
# Eagerly import the model registry so the download chokepoint
|
|
@@ -36,6 +36,7 @@ def build_parser() -> argparse.ArgumentParser:
|
|
|
36
36
|
_add_pick,
|
|
37
37
|
_add_model,
|
|
38
38
|
_add_db,
|
|
39
|
+
_add_selfcheck,
|
|
39
40
|
):
|
|
40
41
|
add(sub)
|
|
41
42
|
return parser
|
|
@@ -252,6 +253,19 @@ def _add_db(sub: argparse._SubParsersAction) -> None:
|
|
|
252
253
|
)
|
|
253
254
|
|
|
254
255
|
|
|
256
|
+
def _add_selfcheck(sub: argparse._SubParsersAction) -> None:
|
|
257
|
+
"""`bpp selfcheck`: load the native libraries bpp uses."""
|
|
258
|
+
p = sub.add_parser(
|
|
259
|
+
"selfcheck",
|
|
260
|
+
help="Check that the native libraries the desktop app bundles load (no photo library)",
|
|
261
|
+
)
|
|
262
|
+
p.add_argument(
|
|
263
|
+
"--require-all",
|
|
264
|
+
action="store_true",
|
|
265
|
+
help="Also fail when an optional part isn't installed (the desktop app has them all)",
|
|
266
|
+
)
|
|
267
|
+
|
|
268
|
+
|
|
255
269
|
def cmd_analyze(args: argparse.Namespace) -> int:
|
|
256
270
|
"""Scan images, extract features, and compute quality scores."""
|
|
257
271
|
from bpp.commands import do_analyze
|
|
@@ -324,6 +338,12 @@ def cmd_db(args: argparse.Namespace) -> int:
|
|
|
324
338
|
return 1
|
|
325
339
|
|
|
326
340
|
|
|
341
|
+
def cmd_selfcheck(args: argparse.Namespace) -> int:
|
|
342
|
+
from bpp.commands.selfcheck import do_selfcheck
|
|
343
|
+
|
|
344
|
+
return do_selfcheck(args)
|
|
345
|
+
|
|
346
|
+
|
|
327
347
|
def main(argv: list[str] | None = None) -> int:
|
|
328
348
|
parser = build_parser()
|
|
329
349
|
args = parser.parse_args(argv)
|
|
@@ -342,6 +362,7 @@ def main(argv: list[str] | None = None) -> int:
|
|
|
342
362
|
"pick": cmd_pick,
|
|
343
363
|
"model": cmd_model,
|
|
344
364
|
"db": cmd_db,
|
|
365
|
+
"selfcheck": cmd_selfcheck,
|
|
345
366
|
}
|
|
346
367
|
if args.command in ("serve", "web", "demo", "run", "analyze", "pick"):
|
|
347
368
|
from bpp.scoring.cpu_support import probe_before_threads
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
"""``bpp selfcheck``: load the native libraries the desktop app bundles.
|
|
2
|
+
|
|
3
|
+
The checks are the list in ``CHECKS``: the base install plus the web,
|
|
4
|
+
HEIC, RAW, faces (MediaPipe, LiteRT, SciPy) and inpainting extras. The
|
|
5
|
+
optional dlib face backend of a pip install is not among them (the app
|
|
6
|
+
leaves it out). It opens no photo library: each check only imports a
|
|
7
|
+
package (or loads the shared library it loads at runtime), exactly as
|
|
8
|
+
bpp does at first use, and reports one of
|
|
9
|
+
|
|
10
|
+
* ``ok`` — it loaded;
|
|
11
|
+
* ``missing`` — the package isn't installed (an optional part of a pip
|
|
12
|
+
install, e.g. ``bppicker[raw]``);
|
|
13
|
+
* ``FAILED`` — it is installed but would not load;
|
|
14
|
+
* ``skipped`` — this processor can't run it, and bpp turns it off
|
|
15
|
+
(MediaPipe on an x86-64 processor without AVX).
|
|
16
|
+
|
|
17
|
+
An import may write what it would write at first use anyway (MediaPipe
|
|
18
|
+
pulls in matplotlib, which builds its font cache once), and starting
|
|
19
|
+
``bpp`` reads the model registry online as every command does (set
|
|
20
|
+
``BPP_DISABLE_REMOTE_REGISTRY=1`` to skip that).
|
|
21
|
+
|
|
22
|
+
The Mac app's release check runs it with ``--require-all`` in the signed
|
|
23
|
+
server, so a library macOS refuses to load fails the release instead of
|
|
24
|
+
a user's first import, face scan or inpaint.
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
from __future__ import annotations
|
|
28
|
+
|
|
29
|
+
import argparse
|
|
30
|
+
import ctypes
|
|
31
|
+
import importlib
|
|
32
|
+
import importlib.util
|
|
33
|
+
import os
|
|
34
|
+
import sys
|
|
35
|
+
from collections.abc import Callable
|
|
36
|
+
|
|
37
|
+
OK = "ok"
|
|
38
|
+
MISSING = "missing"
|
|
39
|
+
FAILED = "FAILED"
|
|
40
|
+
SKIPPED = "skipped"
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def _import(module: str) -> Callable[[], object]:
|
|
44
|
+
return lambda: importlib.import_module(module)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def _opencv() -> None:
|
|
48
|
+
import cv2
|
|
49
|
+
|
|
50
|
+
cascade = os.path.join(cv2.data.haarcascades, "haarcascade_frontalface_default.xml")
|
|
51
|
+
if not os.path.isfile(cascade): # the last-resort face detector reads it
|
|
52
|
+
raise FileNotFoundError(cascade)
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def _onnxruntime() -> None:
|
|
56
|
+
import onnxruntime
|
|
57
|
+
|
|
58
|
+
if not onnxruntime.get_available_providers():
|
|
59
|
+
raise RuntimeError("onnxruntime reports no execution providers")
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def _cryptography() -> None:
|
|
63
|
+
from cryptography.hazmat.primitives.asymmetric import ed25519
|
|
64
|
+
|
|
65
|
+
ed25519.Ed25519PrivateKey.generate() # the model-registry verifier's backend
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def _pillow_heif() -> None:
|
|
69
|
+
from pillow_heif import register_heif_opener
|
|
70
|
+
|
|
71
|
+
register_heif_opener()
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def _mediapipe() -> None:
|
|
75
|
+
from bpp.scoring.cpu_support import refuse_if_cpu_unsupported
|
|
76
|
+
|
|
77
|
+
# Loading it would crash this process on a processor without AVX; bpp
|
|
78
|
+
# checks first everywhere it imports mediapipe, and so does this.
|
|
79
|
+
refuse_if_cpu_unsupported("mediapipe")
|
|
80
|
+
import mediapipe
|
|
81
|
+
|
|
82
|
+
# Load the native code the Tasks API runs on now, so a library the OS
|
|
83
|
+
# refuses shows up here. Newer releases load a C library with ctypes
|
|
84
|
+
# at first use (through mediapipe_c_bindings); older ones (e.g. 0.10.21,
|
|
85
|
+
# which `mediapipe>=0.10` allows) ship a Python extension instead.
|
|
86
|
+
if importlib.util.find_spec("mediapipe.tasks.python.core.mediapipe_c_bindings"):
|
|
87
|
+
name = {"darwin": "libmediapipe.dylib", "linux": "libmediapipe.so"}.get(sys.platform)
|
|
88
|
+
if name:
|
|
89
|
+
ctypes.CDLL(os.path.join(os.path.dirname(mediapipe.__file__), "tasks", "c", name))
|
|
90
|
+
else:
|
|
91
|
+
importlib.import_module("mediapipe.python._framework_bindings")
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def _litert() -> None:
|
|
95
|
+
from ai_edge_litert.interpreter import Interpreter # noqa: F401
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def _inpainting() -> None:
|
|
99
|
+
from simple_lama_inpainting import SimpleLama # noqa: F401 (loads PyTorch)
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
# (name shown, top-level module whose absence means "not installed", check)
|
|
103
|
+
CHECKS: list[tuple[str, str, Callable[[], object]]] = [
|
|
104
|
+
("numpy", "numpy", _import("numpy")),
|
|
105
|
+
("Pillow", "PIL", _import("PIL.Image")),
|
|
106
|
+
("OpenCV", "cv2", _opencv),
|
|
107
|
+
("ONNX Runtime", "onnxruntime", _onnxruntime),
|
|
108
|
+
("cryptography", "cryptography", _cryptography),
|
|
109
|
+
("Flask", "flask", _import("flask")),
|
|
110
|
+
("HEIC (pillow-heif)", "pillow_heif", _pillow_heif),
|
|
111
|
+
("camera RAW (rawpy)", "rawpy", _import("rawpy")),
|
|
112
|
+
("SciPy clustering", "scipy", _import("scipy.cluster.hierarchy")),
|
|
113
|
+
("MediaPipe", "mediapipe", _mediapipe),
|
|
114
|
+
("LiteRT", "ai_edge_litert", _litert),
|
|
115
|
+
("inpainting (PyTorch)", "simple_lama_inpainting", _inpainting),
|
|
116
|
+
]
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
def run_check(top: str, check: Callable[[], object]) -> tuple[str, str]:
|
|
120
|
+
"""(status, detail) for one check. Only the package itself being
|
|
121
|
+
absent is "missing"; an installed package that lacks one of its own
|
|
122
|
+
modules (a partial install, a module a frozen build left out) failed."""
|
|
123
|
+
from bpp.scoring.cpu_support import CpuUnsupported
|
|
124
|
+
|
|
125
|
+
try:
|
|
126
|
+
check()
|
|
127
|
+
except CpuUnsupported as e:
|
|
128
|
+
return SKIPPED, str(e)
|
|
129
|
+
except ModuleNotFoundError as e:
|
|
130
|
+
if e.name == top:
|
|
131
|
+
return MISSING, ""
|
|
132
|
+
return FAILED, f"{type(e).__name__}: {e}"
|
|
133
|
+
except Exception as e: # anything else means installed but broken
|
|
134
|
+
return FAILED, f"{type(e).__name__}: {e}"
|
|
135
|
+
return OK, ""
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
def do_selfcheck(args: argparse.Namespace) -> int:
|
|
139
|
+
failed = absent = 0
|
|
140
|
+
for name, top, check in CHECKS:
|
|
141
|
+
status, detail = run_check(top, check)
|
|
142
|
+
print(f"{status:<8}{name}" + (f": {detail}" if detail else ""), flush=True)
|
|
143
|
+
failed += status == FAILED
|
|
144
|
+
absent += status in (MISSING, SKIPPED)
|
|
145
|
+
if failed or (absent and args.require_all):
|
|
146
|
+
return 1
|
|
147
|
+
return 0
|
|
@@ -15,6 +15,7 @@ import os
|
|
|
15
15
|
from typing import Any
|
|
16
16
|
|
|
17
17
|
from bpp.utils.logging import get_logger, setup_logging
|
|
18
|
+
from bpp.web.wsgi_bind import bind_without_reverse_dns
|
|
18
19
|
|
|
19
20
|
|
|
20
21
|
def do_web(args: argparse.Namespace) -> int:
|
|
@@ -54,6 +55,7 @@ def do_web(args: argparse.Namespace) -> int:
|
|
|
54
55
|
# ``--debug`` means verbose logging (setup_logging above), never
|
|
55
56
|
# Werkzeug's interactive debugger: that would hand a traceback page
|
|
56
57
|
# and a code console to anyone who can reach the port.
|
|
58
|
+
bind_without_reverse_dns()
|
|
57
59
|
app.run(host=host, port=port, debug=False, threaded=True)
|
|
58
60
|
return 0
|
|
59
61
|
|
|
@@ -133,6 +135,7 @@ def do_serve(args: argparse.Namespace) -> int:
|
|
|
133
135
|
# Werkzeug's interactive debugger: with sharing on the server binds the
|
|
134
136
|
# LAN, and the debugger's traceback pages and console would be reachable
|
|
135
137
|
# by any device that can send a loopback Host header.
|
|
138
|
+
bind_without_reverse_dns()
|
|
136
139
|
app.run(
|
|
137
140
|
host=host,
|
|
138
141
|
port=port,
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"""Bind the Werkzeug server without a reverse DNS lookup.
|
|
2
|
+
|
|
3
|
+
``http.server.HTTPServer.server_bind``, which Werkzeug's servers inherit,
|
|
4
|
+
looks up the fully qualified name of the bound host (``socket.getfqdn``)
|
|
5
|
+
only to fill ``server_name``. Werkzeug never reads that attribute: the
|
|
6
|
+
WSGI ``SERVER_NAME`` comes from ``server_address``. On macOS the lookup
|
|
7
|
+
can go to multicast DNS and block. In the desktop app's server it held
|
|
8
|
+
the port unopened for about 35 s while the app was waiting for it. So
|
|
9
|
+
the bind skips the lookup and records the host as given.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from __future__ import annotations
|
|
13
|
+
|
|
14
|
+
import http.server
|
|
15
|
+
import socketserver
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def _server_bind(self: socketserver.TCPServer) -> None:
|
|
19
|
+
# http.server.HTTPServer.server_bind, minus socket.getfqdn(host).
|
|
20
|
+
socketserver.TCPServer.server_bind(self)
|
|
21
|
+
host, port = self.server_address[:2]
|
|
22
|
+
self.server_name = host # type: ignore[attr-defined]
|
|
23
|
+
self.server_port = port # type: ignore[attr-defined]
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def bind_without_reverse_dns() -> None:
|
|
27
|
+
"""Make Werkzeug's servers in this process bind without the lookup.
|
|
28
|
+
|
|
29
|
+
Only while Werkzeug inherits ``server_bind`` from ``http.server``
|
|
30
|
+
unchanged: if a Werkzeug release brings its own, replacing it could
|
|
31
|
+
drop what it does, so the bind is left alone (with the lookup) and
|
|
32
|
+
tests/test_wsgi_bind.py fails until this is looked at again.
|
|
33
|
+
"""
|
|
34
|
+
from werkzeug.serving import BaseWSGIServer
|
|
35
|
+
|
|
36
|
+
if BaseWSGIServer.server_bind is _server_bind:
|
|
37
|
+
return
|
|
38
|
+
if BaseWSGIServer.server_bind is not http.server.HTTPServer.server_bind:
|
|
39
|
+
return
|
|
40
|
+
BaseWSGIServer.server_bind = _server_bind # type: ignore[method-assign]
|
|
@@ -9,7 +9,7 @@ deep dives.
|
|
|
9
9
|
|
|
10
10
|
```
|
|
11
11
|
Mac app (Tauri shell, desktop/) Browser (bpp serve / bpp demo)
|
|
12
|
-
spawns `bpp-server` (PyInstaller)
|
|
12
|
+
spawns `bpp-server` (PyInstaller helper) opens the printed ?_boot= link
|
|
13
13
|
│ boot key, port 5001 │
|
|
14
14
|
▼ ▼
|
|
15
15
|
┌──────────────────── Flask app (bpp/web) ─────────────────────┐
|
|
@@ -42,8 +42,11 @@ deep dives.
|
|
|
42
42
|
and Playwright against the same endpoints.
|
|
43
43
|
- **Why a Tauri sidecar.** The desktop app is the same server frozen
|
|
44
44
|
with PyInstaller and a thin Rust shell that starts it, proves the
|
|
45
|
-
port is ours (a boot key), and shows the page.
|
|
46
|
-
|
|
45
|
+
port is ours (a boot key), and shows the page. The server is a
|
|
46
|
+
one-folder build in a background-only helper app
|
|
47
|
+
(`Contents/Helpers/bpp-server.app`, `desktop/bpp-server.spec`), so
|
|
48
|
+
nothing is unpacked at launch. Python is pinned to 3.11 because the
|
|
49
|
+
frozen runtime is; the pip install matches it.
|
|
47
50
|
- **Long work is a job, not a request.** Analyze and face extraction
|
|
48
51
|
run in subprocesses with journaled progress, so a crash or a quit
|
|
49
52
|
resumes on the next start; cheaper background work (hash backfill,
|
|
@@ -5,6 +5,13 @@ One-time setup so `release-desktop.yml` produces a DMG that is
|
|
|
5
5
|
the DMG and the app inside it — so it opens on double-click with no
|
|
6
6
|
Gatekeeper "Open Anyway" detour.
|
|
7
7
|
|
|
8
|
+
What gets signed first: the app's server is a helper app
|
|
9
|
+
(`Contents/Helpers/bpp-server.app`) that the Tauri bundler copies in but
|
|
10
|
+
does not sign, so the workflow imports the same certificate into a
|
|
11
|
+
temporary keychain and PyInstaller signs every binary in the helper with
|
|
12
|
+
it (hardened runtime, secure timestamp) before the Tauri build. That
|
|
13
|
+
keychain is deleted again before Tauri imports the certificate itself.
|
|
14
|
+
|
|
8
15
|
What gets notarized: Tauri signs the `.app`, submits it to Apple's
|
|
9
16
|
notary service, staples the ticket to the `.app`, then builds the DMG
|
|
10
17
|
around it and signs the DMG. Tauri does not notarize the DMG itself, so
|
|
@@ -95,5 +102,6 @@ build-only path to exercise the full CI build before tagging.)
|
|
|
95
102
|
## Fallback behavior
|
|
96
103
|
|
|
97
104
|
If the secrets are absent (e.g. a fork), the workflow still builds an
|
|
98
|
-
**unsigned** DMG instead of failing
|
|
105
|
+
**unsigned** DMG instead of failing (the server helper is ad-hoc signed)
|
|
106
|
+
— only Arkalogy's releases are signed.
|
|
99
107
|
A fork's users would see the old Gatekeeper warning; Arkalogy's don't.
|
|
@@ -8,7 +8,7 @@ build-backend = "hatchling.build"
|
|
|
8
8
|
# *import* package stays `bpp` — `pip install bppicker` then
|
|
9
9
|
# `import bpp` is the contract.
|
|
10
10
|
name = "bppicker"
|
|
11
|
-
version = "0.2.
|
|
11
|
+
version = "0.2.4"
|
|
12
12
|
description = "Local-first photo curation tool — score, deduplicate, and select the best photos from large collections"
|
|
13
13
|
readme = "README.md"
|
|
14
14
|
requires-python = ">=3.11,<3.12"
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
"""Record what PyInstaller actually packed into the frozen sidecar.
|
|
2
2
|
|
|
3
|
-
Used by ``third_party_inventory.py bundled``.
|
|
4
|
-
|
|
5
|
-
the
|
|
6
|
-
|
|
3
|
+
Used by ``third_party_inventory.py bundled``. The sidecar is the
|
|
4
|
+
``bpp-server.app`` helper app (a one-folder build): its files are read
|
|
5
|
+
from the bundle on disk and its Python modules from the archive inside
|
|
6
|
+
the executable (PyInstaller's own reader, so it must run in the build
|
|
7
|
+
environment). A one-file binary (up to 0.2.3) is still read from its
|
|
8
|
+
archive alone. Every packed file and module is attributed to its owner:
|
|
7
9
|
|
|
8
10
|
* a distribution, via the files its RECORD lists or the top-level
|
|
9
11
|
import names it provides;
|
|
@@ -23,6 +25,7 @@ from __future__ import annotations
|
|
|
23
25
|
|
|
24
26
|
import hashlib
|
|
25
27
|
import importlib.metadata as md
|
|
28
|
+
import os
|
|
26
29
|
import re
|
|
27
30
|
import sys
|
|
28
31
|
from collections.abc import Iterable, Mapping
|
|
@@ -106,6 +109,96 @@ def read_archive(binary: Path) -> tuple[dict, list[str]]:
|
|
|
106
109
|
return reader.toc, modules
|
|
107
110
|
|
|
108
111
|
|
|
112
|
+
_MACHO_MAGIC = {
|
|
113
|
+
bytes.fromhex(m)
|
|
114
|
+
for m in ("feedface", "cefaedfe", "feedfacf", "cffaedfe", "cafebabe", "bebafeca")
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
def _is_binary(path: Path) -> bool:
|
|
119
|
+
with path.open("rb") as fh:
|
|
120
|
+
head = fh.read(4)
|
|
121
|
+
return head in _MACHO_MAGIC or head == b"\x7fELF"
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
def bundle_roots(app: Path) -> list[Path]:
|
|
125
|
+
"""Where a helper app's packed files live: PyInstaller puts binaries
|
|
126
|
+
in Contents/Frameworks and data in Contents/Resources, each relative
|
|
127
|
+
to the same root (sys._MEIPASS), with symlinks between the two."""
|
|
128
|
+
return [app / "Contents" / "Frameworks", app / "Contents" / "Resources"]
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
def read_bundle(app: Path) -> tuple[dict, list[str]]:
|
|
132
|
+
"""(TOC-shaped entries for every packed file plus the executable's own
|
|
133
|
+
archive entries, module names in the embedded PYZ) for a one-folder
|
|
134
|
+
helper app. Symlinks are aliases of a file listed once; the app's own
|
|
135
|
+
icon is bpp's and is skipped. PyInstaller renames a dotted folder in
|
|
136
|
+
Contents/Frameworks (``python3.11``, ``cv2/.dylibs``) to ``__dot__``
|
|
137
|
+
and links the original name to it; entries keep the original name,
|
|
138
|
+
the one the running server sees and the distributions record (see
|
|
139
|
+
``_original_rel``)."""
|
|
140
|
+
import plistlib
|
|
141
|
+
|
|
142
|
+
info = plistlib.loads((app / "Contents" / "Info.plist").read_bytes())
|
|
143
|
+
exe = app / "Contents" / "MacOS" / info["CFBundleExecutable"]
|
|
144
|
+
toc, modules = read_archive(exe)
|
|
145
|
+
toc = dict(toc)
|
|
146
|
+
icon = info.get("CFBundleIconFile")
|
|
147
|
+
for root in bundle_roots(app):
|
|
148
|
+
for path in _walk(root):
|
|
149
|
+
if path.is_symlink() or not path.is_file():
|
|
150
|
+
continue
|
|
151
|
+
rel = _original_rel(root, path)
|
|
152
|
+
if root.name == "Resources" and icon and rel == icon:
|
|
153
|
+
continue
|
|
154
|
+
toc.setdefault(rel, ("b" if _is_binary(path) else "x",))
|
|
155
|
+
return toc, modules
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
def _original_rel(root: Path, path: Path) -> str:
|
|
159
|
+
"""*path* relative to *root*, with each Frameworks folder PyInstaller
|
|
160
|
+
renamed (``.`` → ``__dot__``) given back its original name. A folder
|
|
161
|
+
counts as renamed only when its parent holds PyInstaller's link from
|
|
162
|
+
the original name to it; file names, Resources paths and a literal
|
|
163
|
+
``__dot__`` without that link are kept as they are."""
|
|
164
|
+
parts = list(path.relative_to(root).parts)
|
|
165
|
+
if root.name != "Frameworks":
|
|
166
|
+
return "/".join(parts)
|
|
167
|
+
base = root
|
|
168
|
+
for i, part in enumerate(parts[:-1]):
|
|
169
|
+
here = base / part
|
|
170
|
+
if "__dot__" in part:
|
|
171
|
+
alias = base / part.replace("__dot__", ".")
|
|
172
|
+
if alias.is_symlink() and Path(os.readlink(alias)) == Path(part):
|
|
173
|
+
parts[i] = alias.name
|
|
174
|
+
base = here
|
|
175
|
+
return "/".join(parts)
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
def _walk(root: Path) -> list[Path]:
|
|
179
|
+
"""Every entry under *root*, sorted, without following symlinks (a
|
|
180
|
+
linked folder is listed as the link, not walked twice)."""
|
|
181
|
+
out: list[Path] = []
|
|
182
|
+
for dirpath, dirnames, filenames in os.walk(root, followlinks=False):
|
|
183
|
+
base = Path(dirpath)
|
|
184
|
+
out.extend(base / n for n in dirnames + filenames)
|
|
185
|
+
return sorted(out)
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
def tree_sha256(app: Path) -> str:
|
|
189
|
+
"""One digest over every file and link of the helper app (path +
|
|
190
|
+
content or target), so the inventory names exactly the build it
|
|
191
|
+
describes."""
|
|
192
|
+
h = hashlib.sha256()
|
|
193
|
+
for path in _walk(app):
|
|
194
|
+
rel = path.relative_to(app).as_posix()
|
|
195
|
+
if path.is_symlink():
|
|
196
|
+
h.update(f"L {rel} -> {path.readlink()}\n".encode())
|
|
197
|
+
elif path.is_file():
|
|
198
|
+
h.update(f"F {rel} {_sha256(path)}\n".encode())
|
|
199
|
+
return h.hexdigest()
|
|
200
|
+
|
|
201
|
+
|
|
109
202
|
def attribute(toc: Mapping[str, tuple], modules: Iterable[str], attributor: Attributor) -> dict:
|
|
110
203
|
owners: dict[str, dict] = {}
|
|
111
204
|
unattributed: list[str] = []
|
|
@@ -153,7 +246,8 @@ def _sha256(path: Path) -> str:
|
|
|
153
246
|
def record_bundled(inv: dict, binary: Path, dists: Mapping[str, md.Distribution]) -> None:
|
|
154
247
|
from third_party_inventory import canon, dist_record
|
|
155
248
|
|
|
156
|
-
|
|
249
|
+
is_bundle = binary.is_dir()
|
|
250
|
+
toc, modules = read_bundle(binary) if is_bundle else read_archive(binary)
|
|
157
251
|
result = attribute(toc, modules, Attributor(dists, inv["root"]["name"]))
|
|
158
252
|
listed = {canon(d["name"]) for d in inv["distributions"]}
|
|
159
253
|
special = {CPYTHON, PYINSTALLER, inv["root"]["name"]}
|
|
@@ -173,7 +267,8 @@ def record_bundled(inv: dict, binary: Path, dists: Mapping[str, md.Distribution]
|
|
|
173
267
|
inv["distributions"].sort(key=lambda r: r["name"].lower())
|
|
174
268
|
inv["sidecar"] = {
|
|
175
269
|
"binary": binary.name,
|
|
176
|
-
"
|
|
270
|
+
"layout": "one-folder helper app" if is_bundle else "one-file binary",
|
|
271
|
+
"sha256": tree_sha256(binary) if is_bundle else _sha256(binary),
|
|
177
272
|
"archive_entries": len(toc),
|
|
178
273
|
"pyz_modules": len(modules),
|
|
179
274
|
"added_by_pyinstaller": sorted(added),
|