media-optimization-engine 1.4.1__tar.gz → 1.4.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (94) hide show
  1. {media_optimization_engine-1.4.1/media_optimization_engine.egg-info → media_optimization_engine-1.4.2}/PKG-INFO +11 -1
  2. {media_optimization_engine-1.4.1 → media_optimization_engine-1.4.2}/README.md +10 -0
  3. media_optimization_engine-1.4.2/media_engine/management/commands/backfill_registered_media.py +72 -0
  4. {media_optimization_engine-1.4.1 → media_optimization_engine-1.4.2}/media_engine/storage_paths.py +1 -1
  5. media_optimization_engine-1.4.2/media_engine/tests/test_backfill_registered_media.py +51 -0
  6. media_optimization_engine-1.4.2/media_engine/tests/test_validators.py +30 -0
  7. {media_optimization_engine-1.4.1 → media_optimization_engine-1.4.2}/media_engine/validators.py +7 -1
  8. {media_optimization_engine-1.4.1 → media_optimization_engine-1.4.2/media_optimization_engine.egg-info}/PKG-INFO +11 -1
  9. {media_optimization_engine-1.4.1 → media_optimization_engine-1.4.2}/media_optimization_engine.egg-info/SOURCES.txt +2 -0
  10. {media_optimization_engine-1.4.1 → media_optimization_engine-1.4.2}/pyproject.toml +1 -1
  11. media_optimization_engine-1.4.1/media_engine/management/commands/backfill_registered_media.py +0 -21
  12. {media_optimization_engine-1.4.1 → media_optimization_engine-1.4.2}/LICENSE +0 -0
  13. {media_optimization_engine-1.4.1 → media_optimization_engine-1.4.2}/media_engine/__init__.py +0 -0
  14. {media_optimization_engine-1.4.1 → media_optimization_engine-1.4.2}/media_engine/adapters/__init__.py +0 -0
  15. {media_optimization_engine-1.4.1 → media_optimization_engine-1.4.2}/media_engine/adapters/flutter/README.md +0 -0
  16. {media_optimization_engine-1.4.1 → media_optimization_engine-1.4.2}/media_engine/adapters/flutter/__init__.py +0 -0
  17. {media_optimization_engine-1.4.1 → media_optimization_engine-1.4.2}/media_engine/adapters/flutter/models.dart +0 -0
  18. {media_optimization_engine-1.4.1 → media_optimization_engine-1.4.2}/media_engine/adapters/flutter/standard_images.dart +0 -0
  19. {media_optimization_engine-1.4.1 → media_optimization_engine-1.4.2}/media_engine/adapters/marzipano/__init__.py +0 -0
  20. {media_optimization_engine-1.4.1 → media_optimization_engine-1.4.2}/media_engine/adapters/marzipano/manifest.py +0 -0
  21. {media_optimization_engine-1.4.1 → media_optimization_engine-1.4.2}/media_engine/adapters/pannellum/__init__.py +0 -0
  22. {media_optimization_engine-1.4.1 → media_optimization_engine-1.4.2}/media_engine/adapters/pannellum/manifest.py +0 -0
  23. {media_optimization_engine-1.4.1 → media_optimization_engine-1.4.2}/media_engine/adapters/threejs/__init__.py +0 -0
  24. {media_optimization_engine-1.4.1 → media_optimization_engine-1.4.2}/media_engine/adapters/threejs/manifest.py +0 -0
  25. {media_optimization_engine-1.4.1 → media_optimization_engine-1.4.2}/media_engine/admin.py +0 -0
  26. {media_optimization_engine-1.4.1 → media_optimization_engine-1.4.2}/media_engine/apps.py +0 -0
  27. {media_optimization_engine-1.4.1 → media_optimization_engine-1.4.2}/media_engine/auth.py +0 -0
  28. {media_optimization_engine-1.4.1 → media_optimization_engine-1.4.2}/media_engine/autoregister.py +0 -0
  29. {media_optimization_engine-1.4.1 → media_optimization_engine-1.4.2}/media_engine/control_plane.py +0 -0
  30. {media_optimization_engine-1.4.1 → media_optimization_engine-1.4.2}/media_engine/doctor.py +0 -0
  31. {media_optimization_engine-1.4.1 → media_optimization_engine-1.4.2}/media_engine/focal_detectors.py +0 -0
  32. {media_optimization_engine-1.4.1 → media_optimization_engine-1.4.2}/media_engine/health.py +0 -0
  33. {media_optimization_engine-1.4.1 → media_optimization_engine-1.4.2}/media_engine/image_ops.py +0 -0
  34. {media_optimization_engine-1.4.1 → media_optimization_engine-1.4.2}/media_engine/integration.py +0 -0
  35. {media_optimization_engine-1.4.1 → media_optimization_engine-1.4.2}/media_engine/locks.py +0 -0
  36. {media_optimization_engine-1.4.1 → media_optimization_engine-1.4.2}/media_engine/management/__init__.py +0 -0
  37. {media_optimization_engine-1.4.1 → media_optimization_engine-1.4.2}/media_engine/management/commands/__init__.py +0 -0
  38. {media_optimization_engine-1.4.1 → media_optimization_engine-1.4.2}/media_engine/management/commands/audit_media_engine.py +0 -0
  39. {media_optimization_engine-1.4.1 → media_optimization_engine-1.4.2}/media_engine/management/commands/audit_panorama_media.py +0 -0
  40. {media_optimization_engine-1.4.1 → media_optimization_engine-1.4.2}/media_engine/management/commands/backfill_panorama_media.py +0 -0
  41. {media_optimization_engine-1.4.1 → media_optimization_engine-1.4.2}/media_engine/management/commands/backfill_responsive_images.py +0 -0
  42. {media_optimization_engine-1.4.1 → media_optimization_engine-1.4.2}/media_engine/management/commands/cleanup_image_derivatives.py +0 -0
  43. {media_optimization_engine-1.4.1 → media_optimization_engine-1.4.2}/media_engine/management/commands/media_engine_doctor.py +0 -0
  44. {media_optimization_engine-1.4.1 → media_optimization_engine-1.4.2}/media_engine/management/commands/media_engine_node_report.py +0 -0
  45. {media_optimization_engine-1.4.1 → media_optimization_engine-1.4.2}/media_engine/management/commands/rollback_media_engine_config.py +0 -0
  46. {media_optimization_engine-1.4.1 → media_optimization_engine-1.4.2}/media_engine/management/commands/sync_media_engine_hub.py +0 -0
  47. {media_optimization_engine-1.4.1 → media_optimization_engine-1.4.2}/media_engine/manifest.py +0 -0
  48. {media_optimization_engine-1.4.1 → media_optimization_engine-1.4.2}/media_engine/metrics.py +0 -0
  49. {media_optimization_engine-1.4.1 → media_optimization_engine-1.4.2}/media_engine/migrations/0001_initial.py +0 -0
  50. {media_optimization_engine-1.4.1 → media_optimization_engine-1.4.2}/media_engine/migrations/0002_panorama_multires.py +0 -0
  51. {media_optimization_engine-1.4.1 → media_optimization_engine-1.4.2}/media_engine/migrations/0003_panorama_cube_tiles.py +0 -0
  52. {media_optimization_engine-1.4.1 → media_optimization_engine-1.4.2}/media_engine/migrations/__init__.py +0 -0
  53. {media_optimization_engine-1.4.1 → media_optimization_engine-1.4.2}/media_engine/models.py +0 -0
  54. {media_optimization_engine-1.4.1 → media_optimization_engine-1.4.2}/media_engine/node.py +0 -0
  55. {media_optimization_engine-1.4.1 → media_optimization_engine-1.4.2}/media_engine/processors/__init__.py +0 -0
  56. {media_optimization_engine-1.4.1 → media_optimization_engine-1.4.2}/media_engine/processors/base.py +0 -0
  57. {media_optimization_engine-1.4.1 → media_optimization_engine-1.4.2}/media_engine/processors/image/__init__.py +0 -0
  58. {media_optimization_engine-1.4.1 → media_optimization_engine-1.4.2}/media_engine/processors/image/standard.py +0 -0
  59. {media_optimization_engine-1.4.1 → media_optimization_engine-1.4.2}/media_engine/processors/panorama/__init__.py +0 -0
  60. {media_optimization_engine-1.4.1 → media_optimization_engine-1.4.2}/media_engine/processors/panorama/cube_tiles.py +0 -0
  61. {media_optimization_engine-1.4.1 → media_optimization_engine-1.4.2}/media_engine/processors/panorama/cubemap.py +0 -0
  62. {media_optimization_engine-1.4.1 → media_optimization_engine-1.4.2}/media_engine/processors/panorama/detect.py +0 -0
  63. {media_optimization_engine-1.4.1 → media_optimization_engine-1.4.2}/media_engine/processors/panorama/equirectangular.py +0 -0
  64. {media_optimization_engine-1.4.1 → media_optimization_engine-1.4.2}/media_engine/processors/panorama/manifest.py +0 -0
  65. {media_optimization_engine-1.4.1 → media_optimization_engine-1.4.2}/media_engine/processors/panorama/tiles.py +0 -0
  66. {media_optimization_engine-1.4.1 → media_optimization_engine-1.4.2}/media_engine/processors/registry.py +0 -0
  67. {media_optimization_engine-1.4.1 → media_optimization_engine-1.4.2}/media_engine/profiles.py +0 -0
  68. {media_optimization_engine-1.4.1 → media_optimization_engine-1.4.2}/media_engine/queueing.py +0 -0
  69. {media_optimization_engine-1.4.1 → media_optimization_engine-1.4.2}/media_engine/registry.py +0 -0
  70. {media_optimization_engine-1.4.1 → media_optimization_engine-1.4.2}/media_engine/runtime_config.py +0 -0
  71. {media_optimization_engine-1.4.1 → media_optimization_engine-1.4.2}/media_engine/serializers.py +0 -0
  72. {media_optimization_engine-1.4.1 → media_optimization_engine-1.4.2}/media_engine/services.py +0 -0
  73. {media_optimization_engine-1.4.1 → media_optimization_engine-1.4.2}/media_engine/signals.py +0 -0
  74. {media_optimization_engine-1.4.1 → media_optimization_engine-1.4.2}/media_engine/spec/openapi.yaml +0 -0
  75. {media_optimization_engine-1.4.1 → media_optimization_engine-1.4.2}/media_engine/static/media_engine/adaptive-media.js +0 -0
  76. {media_optimization_engine-1.4.1 → media_optimization_engine-1.4.2}/media_engine/static/media_engine/media-cache-sw.js +0 -0
  77. {media_optimization_engine-1.4.1 → media_optimization_engine-1.4.2}/media_engine/system_views.py +0 -0
  78. {media_optimization_engine-1.4.1 → media_optimization_engine-1.4.2}/media_engine/tasks.py +0 -0
  79. {media_optimization_engine-1.4.1 → media_optimization_engine-1.4.2}/media_engine/templatetags/__init__.py +0 -0
  80. {media_optimization_engine-1.4.1 → media_optimization_engine-1.4.2}/media_engine/templatetags/responsive_media.py +0 -0
  81. {media_optimization_engine-1.4.1 → media_optimization_engine-1.4.2}/media_engine/tests/__init__.py +0 -0
  82. {media_optimization_engine-1.4.1 → media_optimization_engine-1.4.2}/media_engine/tests/test_distributed_node.py +0 -0
  83. {media_optimization_engine-1.4.1 → media_optimization_engine-1.4.2}/media_engine/tests/test_image_ops.py +0 -0
  84. {media_optimization_engine-1.4.1 → media_optimization_engine-1.4.2}/media_engine/tests/test_panorama.py +0 -0
  85. {media_optimization_engine-1.4.1 → media_optimization_engine-1.4.2}/media_engine/tests/test_paths.py +0 -0
  86. {media_optimization_engine-1.4.1 → media_optimization_engine-1.4.2}/media_engine/tests/test_profiles.py +0 -0
  87. {media_optimization_engine-1.4.1 → media_optimization_engine-1.4.2}/media_engine/tests/test_responsive_media.py +0 -0
  88. {media_optimization_engine-1.4.1 → media_optimization_engine-1.4.2}/media_engine/urls.py +0 -0
  89. {media_optimization_engine-1.4.1 → media_optimization_engine-1.4.2}/media_engine/views.py +0 -0
  90. {media_optimization_engine-1.4.1 → media_optimization_engine-1.4.2}/media_optimization_engine.egg-info/dependency_links.txt +0 -0
  91. {media_optimization_engine-1.4.1 → media_optimization_engine-1.4.2}/media_optimization_engine.egg-info/entry_points.txt +0 -0
  92. {media_optimization_engine-1.4.1 → media_optimization_engine-1.4.2}/media_optimization_engine.egg-info/requires.txt +0 -0
  93. {media_optimization_engine-1.4.1 → media_optimization_engine-1.4.2}/media_optimization_engine.egg-info/top_level.txt +0 -0
  94. {media_optimization_engine-1.4.1 → media_optimization_engine-1.4.2}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: media-optimization-engine
3
- Version: 1.4.1
3
+ Version: 1.4.2
4
4
  Summary: Media Optimization Engineer for Django/Python: automatic model-field optimization, responsive picture/srcset rendering, AVIF/WebP derivatives, 360 media, autonomous nodes, and CDN-ready storage.
5
5
  Author-email: Achille Kabasele <pepexykabasele@gmail.com>
6
6
  Maintainer-email: Achille Kabasele <pepexykabasele@gmail.com>
@@ -233,6 +233,16 @@ JavaScript is not required for normal responsive images.
233
233
 
234
234
  Runtime measurement is appropriate only for highly dynamic components whose rendered width cannot be described reliably with sizes, such as resizable editors, canvas-like builders, or asynchronously mounted panels.
235
235
 
236
+ ## Docker image
237
+
238
+ The standalone service is also published as a multi-architecture GHCR image:
239
+
240
+ ~~~bash
241
+ docker pull ghcr.io/kabasele754/media-optimization-engine:1.4.1
242
+ ~~~
243
+
244
+ For Compose deployment, see `docs/DOCKER.md` and `docker-compose.ghcr.yml`.
245
+
236
246
  ## Flutter / native clients
237
247
 
238
248
  MOE also ships reference Dart adapters for native applications.
@@ -177,6 +177,16 @@ JavaScript is not required for normal responsive images.
177
177
 
178
178
  Runtime measurement is appropriate only for highly dynamic components whose rendered width cannot be described reliably with sizes, such as resizable editors, canvas-like builders, or asynchronously mounted panels.
179
179
 
180
+ ## Docker image
181
+
182
+ The standalone service is also published as a multi-architecture GHCR image:
183
+
184
+ ~~~bash
185
+ docker pull ghcr.io/kabasele754/media-optimization-engine:1.4.1
186
+ ~~~
187
+
188
+ For Compose deployment, see `docs/DOCKER.md` and `docker-compose.ghcr.yml`.
189
+
180
190
  ## Flutter / native clients
181
191
 
182
192
  MOE also ships reference Dart adapters for native applications.
@@ -0,0 +1,72 @@
1
+ from django.core.exceptions import ValidationError
2
+ from django.core.management.base import BaseCommand
3
+ from media_engine.integration import ingest_model_field
4
+ from media_engine.registry import entries
5
+
6
+
7
+ class Command(BaseCommand):
8
+ help = 'Ingest image fields declared through register_model_image().'
9
+
10
+ def add_arguments(self, parser):
11
+ parser.add_argument('--limit', type=int)
12
+ parser.add_argument(
13
+ '--fail-fast',
14
+ action='store_true',
15
+ help='Stop immediately on the first invalid/unreadable image.',
16
+ )
17
+
18
+ def handle(self, *args, **options):
19
+ processed = 0
20
+ skipped = 0
21
+ failed = 0
22
+ failures = []
23
+
24
+ for entry in entries():
25
+ qs = entry.model._default_manager.all()
26
+ if options['limit']:
27
+ qs = qs[:options['limit']]
28
+
29
+ for obj in qs.iterator():
30
+ try:
31
+ asset = ingest_model_field(
32
+ obj,
33
+ field_name=entry.field_name,
34
+ profile=entry.profile,
35
+ role=entry.role,
36
+ )
37
+ if asset is None:
38
+ skipped += 1
39
+ else:
40
+ processed += 1
41
+ except ValidationError as exc:
42
+ failed += 1
43
+ message = (
44
+ f'{entry.model._meta.label}.{entry.field_name} '
45
+ f'pk={obj.pk}: {exc}'
46
+ )
47
+ failures.append(message)
48
+ self.stderr.write(self.style.WARNING(f'SKIP {message}'))
49
+ if options['fail_fast']:
50
+ raise
51
+ except (FileNotFoundError, OSError, ValueError) as exc:
52
+ failed += 1
53
+ message = (
54
+ f'{entry.model._meta.label}.{entry.field_name} '
55
+ f'pk={obj.pk}: {exc}'
56
+ )
57
+ failures.append(message)
58
+ self.stderr.write(self.style.WARNING(f'SKIP {message}'))
59
+ if options['fail_fast']:
60
+ raise
61
+
62
+ summary = (
63
+ f'Processed {processed} registered model images; '
64
+ f'skipped {skipped}; failures {failed}.'
65
+ )
66
+ if failed:
67
+ self.stdout.write(self.style.WARNING(summary))
68
+ self.stdout.write('Last failures:')
69
+ for message in failures[-20:]:
70
+ self.stdout.write(f' - {message}')
71
+ else:
72
+ self.stdout.write(self.style.SUCCESS(summary))
@@ -2,7 +2,7 @@ from pathlib import Path
2
2
 
3
3
 
4
4
  def safe_extension(fmt):
5
- return {'JPEG': 'jpg', 'JPG': 'jpg', 'PNG': 'png', 'WEBP': 'webp', 'AVIF': 'avif'}.get(fmt.upper(), fmt.lower())
5
+ return {'JPEG': 'jpg', 'JPG': 'jpg', 'MPO': 'jpg', 'PNG': 'png', 'WEBP': 'webp', 'AVIF': 'avif'}.get(fmt.upper(), fmt.lower())
6
6
 
7
7
 
8
8
  def original_storage_name(sha256_hex, extension):
@@ -0,0 +1,51 @@
1
+ from types import SimpleNamespace
2
+ from unittest.mock import patch
3
+
4
+ from django.core.exceptions import ValidationError
5
+ from django.core.management import call_command
6
+ from django.test import SimpleTestCase
7
+
8
+
9
+ class _Manager:
10
+ def __init__(self, objects):
11
+ self._objects = list(objects)
12
+
13
+ def all(self):
14
+ return self
15
+
16
+ def __iter__(self):
17
+ return iter(self._objects)
18
+
19
+ def __getitem__(self, item):
20
+ if isinstance(item, slice):
21
+ return _Manager(self._objects[item])
22
+ return self._objects[item]
23
+
24
+ def iterator(self):
25
+ return iter(self._objects)
26
+
27
+
28
+ class BackfillRegisteredMediaTests(SimpleTestCase):
29
+ @patch("media_engine.management.commands.backfill_registered_media.entries")
30
+ @patch("media_engine.management.commands.backfill_registered_media.ingest_model_field")
31
+ def test_invalid_image_does_not_abort_backfill(self, ingest, entries):
32
+ model = SimpleNamespace(
33
+ _default_manager=_Manager([
34
+ SimpleNamespace(pk=1),
35
+ SimpleNamespace(pk=2),
36
+ ]),
37
+ _meta=SimpleNamespace(label="demo.Photo"),
38
+ )
39
+ entries.return_value = [
40
+ SimpleNamespace(
41
+ model=model,
42
+ field_name="image",
43
+ profile="default",
44
+ role="content",
45
+ )
46
+ ]
47
+ ingest.side_effect = [ValidationError("Unsupported image format"), object()]
48
+
49
+ call_command("backfill_registered_media")
50
+
51
+ self.assertEqual(ingest.call_count, 2)
@@ -0,0 +1,30 @@
1
+ from io import BytesIO
2
+ from unittest.mock import MagicMock, patch
3
+
4
+ from django.core.files.uploadedfile import SimpleUploadedFile
5
+ from django.test import SimpleTestCase
6
+
7
+ from media_engine.validators import inspect_upload
8
+
9
+
10
+ class MpoValidationTests(SimpleTestCase):
11
+ @patch("media_engine.validators.Image.open")
12
+ def test_mpo_is_normalized_as_jpeg(self, image_open):
13
+ image = MagicMock()
14
+ image.format = "MPO"
15
+ image.size = (1200, 800)
16
+ image.verify.return_value = None
17
+ image_open.return_value = image
18
+
19
+ upload = SimpleUploadedFile(
20
+ "portrait.jpg",
21
+ b"fake-mpo-container",
22
+ content_type="image/jpeg",
23
+ )
24
+
25
+ raw, fmt, mime, width, height = inspect_upload(upload)
26
+
27
+ self.assertEqual(raw, b"fake-mpo-container")
28
+ self.assertEqual(fmt, "JPEG")
29
+ self.assertEqual(mime, "image/jpeg")
30
+ self.assertEqual((width, height), (1200, 800))
@@ -7,9 +7,10 @@ try:
7
7
  except Exception:
8
8
  pillow_avif = None
9
9
 
10
- ALLOWED_FORMATS = {'JPEG', 'PNG', 'WEBP', 'AVIF'}
10
+ ALLOWED_FORMATS = {'JPEG', 'PNG', 'WEBP', 'AVIF', 'MPO'}
11
11
  MIME_BY_FORMAT = {
12
12
  'JPEG': 'image/jpeg',
13
+ 'MPO': 'image/jpeg',
13
14
  'PNG': 'image/png',
14
15
  'WEBP': 'image/webp',
15
16
  'AVIF': 'image/avif',
@@ -31,6 +32,11 @@ def inspect_upload(uploaded_file):
31
32
  fmt = (image.format or '').upper()
32
33
  if fmt not in ALLOWED_FORMATS:
33
34
  raise ValidationError(f'Unsupported image format: {fmt or "unknown"}')
35
+ # Pillow reports some JPEG containers as MPO. For optimization purposes,
36
+ # the primary frame is a normal JPEG-compatible raster and can safely
37
+ # enter the standard image pipeline.
38
+ if fmt == 'MPO':
39
+ fmt = 'JPEG'
34
40
  width, height = image.size
35
41
  max_pixels = getattr(settings, 'MEDIA_ENGINE_MAX_PIXELS', 50_000_000)
36
42
  if width * height > max_pixels:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: media-optimization-engine
3
- Version: 1.4.1
3
+ Version: 1.4.2
4
4
  Summary: Media Optimization Engineer for Django/Python: automatic model-field optimization, responsive picture/srcset rendering, AVIF/WebP derivatives, 360 media, autonomous nodes, and CDN-ready storage.
5
5
  Author-email: Achille Kabasele <pepexykabasele@gmail.com>
6
6
  Maintainer-email: Achille Kabasele <pepexykabasele@gmail.com>
@@ -233,6 +233,16 @@ JavaScript is not required for normal responsive images.
233
233
 
234
234
  Runtime measurement is appropriate only for highly dynamic components whose rendered width cannot be described reliably with sizes, such as resizable editors, canvas-like builders, or asynchronously mounted panels.
235
235
 
236
+ ## Docker image
237
+
238
+ The standalone service is also published as a multi-architecture GHCR image:
239
+
240
+ ~~~bash
241
+ docker pull ghcr.io/kabasele754/media-optimization-engine:1.4.1
242
+ ~~~
243
+
244
+ For Compose deployment, see `docs/DOCKER.md` and `docker-compose.ghcr.yml`.
245
+
236
246
  ## Flutter / native clients
237
247
 
238
248
  MOE also ships reference Dart adapters for native applications.
@@ -75,12 +75,14 @@ media_engine/static/media_engine/media-cache-sw.js
75
75
  media_engine/templatetags/__init__.py
76
76
  media_engine/templatetags/responsive_media.py
77
77
  media_engine/tests/__init__.py
78
+ media_engine/tests/test_backfill_registered_media.py
78
79
  media_engine/tests/test_distributed_node.py
79
80
  media_engine/tests/test_image_ops.py
80
81
  media_engine/tests/test_panorama.py
81
82
  media_engine/tests/test_paths.py
82
83
  media_engine/tests/test_profiles.py
83
84
  media_engine/tests/test_responsive_media.py
85
+ media_engine/tests/test_validators.py
84
86
  media_optimization_engine.egg-info/PKG-INFO
85
87
  media_optimization_engine.egg-info/SOURCES.txt
86
88
  media_optimization_engine.egg-info/dependency_links.txt
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "media-optimization-engine"
7
- version = "1.4.1"
7
+ version = "1.4.2"
8
8
  description = "Media Optimization Engineer for Django/Python: automatic model-field optimization, responsive picture/srcset rendering, AVIF/WebP derivatives, 360 media, autonomous nodes, and CDN-ready storage."
9
9
  requires-python = ">=3.11"
10
10
  authors = [{ name = "Achille Kabasele", email = "pepexykabasele@gmail.com" }]
@@ -1,21 +0,0 @@
1
- from django.core.management.base import BaseCommand
2
- from media_engine.integration import ingest_model_field
3
- from media_engine.registry import entries
4
-
5
-
6
- class Command(BaseCommand):
7
- help = 'Ingest image fields declared through register_model_image().'
8
-
9
- def add_arguments(self, parser):
10
- parser.add_argument('--limit', type=int)
11
-
12
- def handle(self, *args, **options):
13
- processed = 0
14
- for entry in entries():
15
- qs = entry.model._default_manager.all()
16
- if options['limit']:
17
- qs = qs[:options['limit']]
18
- for obj in qs.iterator():
19
- ingest_model_field(obj, field_name=entry.field_name, profile=entry.profile, role=entry.role)
20
- processed += 1
21
- self.stdout.write(self.style.SUCCESS(f'Processed {processed} registered model images.'))