magic_hour 0.8.2__tar.gz → 0.8.3__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.

Potentially problematic release.


This version of magic_hour might be problematic. Click here for more details.

Files changed (132) hide show
  1. {magic_hour-0.8.2 → magic_hour-0.8.3}/PKG-INFO +23 -22
  2. {magic_hour-0.8.2 → magic_hour-0.8.3}/README.md +22 -21
  3. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/core/api_error.py +15 -7
  4. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/core/base_client.py +48 -30
  5. magic_hour-0.8.3/magic_hour/core/utils.py +55 -0
  6. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/environment.py +1 -1
  7. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/resources/v1/animation/README.md +4 -4
  8. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/resources/v1/animation/client.py +4 -4
  9. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/resources/v1/face_swap/README.md +4 -4
  10. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/resources/v1/face_swap/client.py +4 -4
  11. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/resources/v1/image_projects/README.md +4 -4
  12. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/resources/v1/image_projects/client.py +4 -4
  13. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/resources/v1/image_to_video/README.md +2 -2
  14. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/resources/v1/image_to_video/client.py +2 -2
  15. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/resources/v1/lip_sync/README.md +6 -6
  16. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/resources/v1/lip_sync/client.py +6 -6
  17. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/resources/v1/text_to_video/README.md +2 -2
  18. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/resources/v1/text_to_video/client.py +2 -2
  19. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/resources/v1/video_projects/README.md +4 -4
  20. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/resources/v1/video_projects/client.py +4 -4
  21. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/resources/v1/video_to_video/README.md +4 -4
  22. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/resources/v1/video_to_video/client.py +4 -4
  23. {magic_hour-0.8.2 → magic_hour-0.8.3}/pyproject.toml +1 -1
  24. magic_hour-0.8.2/magic_hour/core/utils.py +0 -38
  25. {magic_hour-0.8.2 → magic_hour-0.8.3}/LICENSE +0 -0
  26. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/__init__.py +0 -0
  27. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/client.py +4 -4
  28. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/core/__init__.py +0 -0
  29. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/core/auth.py +0 -0
  30. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/core/binary_response.py +0 -0
  31. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/core/request.py +0 -0
  32. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/core/response.py +0 -0
  33. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/core/type_utils.py +0 -0
  34. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/resources/v1/__init__.py +0 -0
  35. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/resources/v1/ai_clothes_changer/README.md +0 -0
  36. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/resources/v1/ai_clothes_changer/__init__.py +0 -0
  37. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/resources/v1/ai_clothes_changer/client.py +0 -0
  38. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/resources/v1/ai_headshot_generator/README.md +0 -0
  39. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/resources/v1/ai_headshot_generator/__init__.py +0 -0
  40. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/resources/v1/ai_headshot_generator/client.py +0 -0
  41. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/resources/v1/ai_image_generator/README.md +0 -0
  42. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/resources/v1/ai_image_generator/__init__.py +0 -0
  43. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/resources/v1/ai_image_generator/client.py +0 -0
  44. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/resources/v1/ai_image_upscaler/README.md +0 -0
  45. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/resources/v1/ai_image_upscaler/__init__.py +0 -0
  46. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/resources/v1/ai_image_upscaler/client.py +0 -0
  47. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/resources/v1/ai_photo_editor/README.md +0 -0
  48. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/resources/v1/ai_photo_editor/__init__.py +0 -0
  49. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/resources/v1/ai_photo_editor/client.py +0 -0
  50. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/resources/v1/ai_qr_code_generator/README.md +0 -0
  51. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/resources/v1/ai_qr_code_generator/__init__.py +0 -0
  52. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/resources/v1/ai_qr_code_generator/client.py +0 -0
  53. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/resources/v1/animation/__init__.py +0 -0
  54. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/resources/v1/client.py +0 -0
  55. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/resources/v1/face_swap/__init__.py +0 -0
  56. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/resources/v1/face_swap_photo/README.md +0 -0
  57. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/resources/v1/face_swap_photo/__init__.py +0 -0
  58. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/resources/v1/face_swap_photo/client.py +0 -0
  59. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/resources/v1/files/__init__.py +0 -0
  60. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/resources/v1/files/client.py +0 -0
  61. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/resources/v1/files/upload_urls/README.md +0 -0
  62. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/resources/v1/files/upload_urls/__init__.py +0 -0
  63. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/resources/v1/files/upload_urls/client.py +0 -0
  64. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/resources/v1/image_background_remover/README.md +0 -0
  65. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/resources/v1/image_background_remover/__init__.py +0 -0
  66. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/resources/v1/image_background_remover/client.py +0 -0
  67. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/resources/v1/image_projects/__init__.py +0 -0
  68. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/resources/v1/image_to_video/__init__.py +0 -0
  69. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/resources/v1/lip_sync/__init__.py +0 -0
  70. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/resources/v1/text_to_video/__init__.py +0 -0
  71. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/resources/v1/video_projects/__init__.py +0 -0
  72. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/resources/v1/video_to_video/__init__.py +0 -0
  73. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/types/models/__init__.py +0 -0
  74. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/types/models/get_v1_image_projects_id_response.py +0 -0
  75. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/types/models/get_v1_image_projects_id_response_downloads_item.py +0 -0
  76. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/types/models/get_v1_image_projects_id_response_error.py +0 -0
  77. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/types/models/get_v1_video_projects_id_response.py +0 -0
  78. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/types/models/get_v1_video_projects_id_response_download.py +0 -0
  79. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/types/models/get_v1_video_projects_id_response_downloads_item.py +0 -0
  80. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/types/models/get_v1_video_projects_id_response_error.py +0 -0
  81. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/types/models/post_v1_ai_clothes_changer_response.py +0 -0
  82. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/types/models/post_v1_ai_headshot_generator_response.py +0 -0
  83. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/types/models/post_v1_ai_image_generator_response.py +0 -0
  84. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/types/models/post_v1_ai_image_upscaler_response.py +0 -0
  85. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/types/models/post_v1_ai_photo_editor_response.py +0 -0
  86. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/types/models/post_v1_ai_qr_code_generator_response.py +0 -0
  87. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/types/models/post_v1_animation_response.py +0 -0
  88. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/types/models/post_v1_face_swap_photo_response.py +0 -0
  89. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/types/models/post_v1_face_swap_response.py +0 -0
  90. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/types/models/post_v1_files_upload_urls_response.py +0 -0
  91. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/types/models/post_v1_files_upload_urls_response_items_item.py +0 -0
  92. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/types/models/post_v1_image_background_remover_response.py +0 -0
  93. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/types/models/post_v1_image_to_video_response.py +0 -0
  94. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/types/models/post_v1_lip_sync_response.py +0 -0
  95. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/types/models/post_v1_text_to_video_response.py +0 -0
  96. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/types/models/post_v1_video_to_video_response.py +0 -0
  97. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/types/params/__init__.py +0 -0
  98. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/types/params/post_v1_ai_clothes_changer_body.py +0 -0
  99. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/types/params/post_v1_ai_clothes_changer_body_assets.py +0 -0
  100. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/types/params/post_v1_ai_headshot_generator_body.py +0 -0
  101. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/types/params/post_v1_ai_headshot_generator_body_assets.py +0 -0
  102. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/types/params/post_v1_ai_image_generator_body.py +0 -0
  103. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/types/params/post_v1_ai_image_generator_body_style.py +0 -0
  104. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/types/params/post_v1_ai_image_upscaler_body.py +0 -0
  105. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/types/params/post_v1_ai_image_upscaler_body_assets.py +0 -0
  106. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/types/params/post_v1_ai_image_upscaler_body_style.py +0 -0
  107. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/types/params/post_v1_ai_photo_editor_body.py +0 -0
  108. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/types/params/post_v1_ai_photo_editor_body_assets.py +0 -0
  109. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/types/params/post_v1_ai_photo_editor_body_style.py +0 -0
  110. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/types/params/post_v1_ai_qr_code_generator_body.py +0 -0
  111. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/types/params/post_v1_ai_qr_code_generator_body_style.py +0 -0
  112. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/types/params/post_v1_animation_body.py +0 -0
  113. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/types/params/post_v1_animation_body_assets.py +0 -0
  114. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/types/params/post_v1_animation_body_style.py +0 -0
  115. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/types/params/post_v1_face_swap_body.py +0 -0
  116. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/types/params/post_v1_face_swap_body_assets.py +0 -0
  117. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/types/params/post_v1_face_swap_photo_body.py +0 -0
  118. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/types/params/post_v1_face_swap_photo_body_assets.py +0 -0
  119. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/types/params/post_v1_files_upload_urls_body.py +0 -0
  120. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/types/params/post_v1_files_upload_urls_body_items_item.py +0 -0
  121. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/types/params/post_v1_image_background_remover_body.py +0 -0
  122. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/types/params/post_v1_image_background_remover_body_assets.py +0 -0
  123. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/types/params/post_v1_image_to_video_body.py +0 -0
  124. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/types/params/post_v1_image_to_video_body_assets.py +0 -0
  125. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/types/params/post_v1_image_to_video_body_style.py +0 -0
  126. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/types/params/post_v1_lip_sync_body.py +0 -0
  127. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/types/params/post_v1_lip_sync_body_assets.py +0 -0
  128. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/types/params/post_v1_text_to_video_body.py +0 -0
  129. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/types/params/post_v1_text_to_video_body_style.py +0 -0
  130. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/types/params/post_v1_video_to_video_body.py +0 -0
  131. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/types/params/post_v1_video_to_video_body_assets.py +0 -0
  132. {magic_hour-0.8.2 → magic_hour-0.8.3}/magic_hour/types/params/post_v1_video_to_video_body_style.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: magic_hour
3
- Version: 0.8.2
3
+ Version: 0.8.3
4
4
  Summary: Python SDK for Magic Hour API
5
5
  Requires-Python: >=3.8,<4.0
6
6
  Classifier: Programming Language :: Python :: 3
@@ -18,7 +18,7 @@ Description-Content-Type: text/markdown
18
18
 
19
19
  # Magic Hour Python SDK
20
20
 
21
- ![PyPI - Version](https://img.shields.io/pypi/v/magic_hour)
21
+ [![PyPI - Version](https://img.shields.io/pypi/v/magic_hour)](https://pypi.org/project/magic_hour/)
22
22
 
23
23
  Magic Hour provides an API (beta) that can be integrated into your own application to generate videos and images using AI.
24
24
 
@@ -54,79 +54,80 @@ from magic_hour import AsyncClient
54
54
  client = AsyncClient(token="my api key")
55
55
  ```
56
56
 
57
- > **Warning**: any API call that renders a video will utilize frames in your account.
57
+ > [!WARNING]
58
+ > Any API call that renders a video will utilize frames in your account.
58
59
 
59
60
  ## Module Documentation and Snippets
60
61
 
61
62
  ### [v1.ai_clothes_changer](magic_hour/resources/v1/ai_clothes_changer/README.md)
62
63
 
63
- - [create](magic_hour/resources/v1/ai_clothes_changer/README.md#create) - AI Clothes Changer
64
+ * [create](magic_hour/resources/v1/ai_clothes_changer/README.md#create) - AI Clothes Changer
64
65
 
65
66
  ### [v1.ai_headshot_generator](magic_hour/resources/v1/ai_headshot_generator/README.md)
66
67
 
67
- - [create](magic_hour/resources/v1/ai_headshot_generator/README.md#create) - AI Headshots
68
+ * [create](magic_hour/resources/v1/ai_headshot_generator/README.md#create) - AI Headshots
68
69
 
69
70
  ### [v1.ai_image_generator](magic_hour/resources/v1/ai_image_generator/README.md)
70
71
 
71
- - [create](magic_hour/resources/v1/ai_image_generator/README.md#create) - AI Images
72
+ * [create](magic_hour/resources/v1/ai_image_generator/README.md#create) - AI Images
72
73
 
73
74
  ### [v1.ai_image_upscaler](magic_hour/resources/v1/ai_image_upscaler/README.md)
74
75
 
75
- - [create](magic_hour/resources/v1/ai_image_upscaler/README.md#create) - AI Image Upscaler
76
+ * [create](magic_hour/resources/v1/ai_image_upscaler/README.md#create) - AI Image Upscaler
76
77
 
77
78
  ### [v1.ai_photo_editor](magic_hour/resources/v1/ai_photo_editor/README.md)
78
79
 
79
- - [create](magic_hour/resources/v1/ai_photo_editor/README.md#create) - AI Photo Editor
80
+ * [create](magic_hour/resources/v1/ai_photo_editor/README.md#create) - AI Photo Editor
80
81
 
81
82
  ### [v1.ai_qr_code_generator](magic_hour/resources/v1/ai_qr_code_generator/README.md)
82
83
 
83
- - [create](magic_hour/resources/v1/ai_qr_code_generator/README.md#create) - AI QR Code
84
+ * [create](magic_hour/resources/v1/ai_qr_code_generator/README.md#create) - AI QR Code
84
85
 
85
86
  ### [v1.animation](magic_hour/resources/v1/animation/README.md)
86
87
 
87
- - [create](magic_hour/resources/v1/animation/README.md#create) - Animation
88
+ * [create](magic_hour/resources/v1/animation/README.md#create) - Animation
88
89
 
89
90
  ### [v1.face_swap](magic_hour/resources/v1/face_swap/README.md)
90
91
 
91
- - [create](magic_hour/resources/v1/face_swap/README.md#create) - Face Swap video
92
+ * [create](magic_hour/resources/v1/face_swap/README.md#create) - Face Swap video
92
93
 
93
94
  ### [v1.face_swap_photo](magic_hour/resources/v1/face_swap_photo/README.md)
94
95
 
95
- - [create](magic_hour/resources/v1/face_swap_photo/README.md#create) - Face Swap Photo
96
+ * [create](magic_hour/resources/v1/face_swap_photo/README.md#create) - Face Swap Photo
96
97
 
97
98
  ### [v1.files.upload_urls](magic_hour/resources/v1/files/upload_urls/README.md)
98
99
 
99
- - [create](magic_hour/resources/v1/files/upload_urls/README.md#create) - Generate asset upload urls
100
+ * [create](magic_hour/resources/v1/files/upload_urls/README.md#create) - Generate asset upload urls
100
101
 
101
102
  ### [v1.image_background_remover](magic_hour/resources/v1/image_background_remover/README.md)
102
103
 
103
- - [create](magic_hour/resources/v1/image_background_remover/README.md#create) - Image Background Remover
104
+ * [create](magic_hour/resources/v1/image_background_remover/README.md#create) - Image Background Remover
104
105
 
105
106
  ### [v1.image_projects](magic_hour/resources/v1/image_projects/README.md)
106
107
 
107
- - [delete](magic_hour/resources/v1/image_projects/README.md#delete) - Delete image
108
- - [get](magic_hour/resources/v1/image_projects/README.md#get) - Get image details
108
+ * [delete](magic_hour/resources/v1/image_projects/README.md#delete) - Delete image
109
+ * [get](magic_hour/resources/v1/image_projects/README.md#get) - Get image details
109
110
 
110
111
  ### [v1.image_to_video](magic_hour/resources/v1/image_to_video/README.md)
111
112
 
112
- - [create](magic_hour/resources/v1/image_to_video/README.md#create) - Image-to-Video
113
+ * [create](magic_hour/resources/v1/image_to_video/README.md#create) - Image-to-Video
113
114
 
114
115
  ### [v1.lip_sync](magic_hour/resources/v1/lip_sync/README.md)
115
116
 
116
- - [create](magic_hour/resources/v1/lip_sync/README.md#create) - Lip Sync
117
+ * [create](magic_hour/resources/v1/lip_sync/README.md#create) - Lip Sync
117
118
 
118
119
  ### [v1.text_to_video](magic_hour/resources/v1/text_to_video/README.md)
119
120
 
120
- - [create](magic_hour/resources/v1/text_to_video/README.md#create) - Text-to-Video
121
+ * [create](magic_hour/resources/v1/text_to_video/README.md#create) - Text-to-Video
121
122
 
122
123
  ### [v1.video_projects](magic_hour/resources/v1/video_projects/README.md)
123
124
 
124
- - [delete](magic_hour/resources/v1/video_projects/README.md#delete) - Delete video
125
- - [get](magic_hour/resources/v1/video_projects/README.md#get) - Get video details
125
+ * [delete](magic_hour/resources/v1/video_projects/README.md#delete) - Delete video
126
+ * [get](magic_hour/resources/v1/video_projects/README.md#get) - Get video details
126
127
 
127
128
  ### [v1.video_to_video](magic_hour/resources/v1/video_to_video/README.md)
128
129
 
129
- - [create](magic_hour/resources/v1/video_to_video/README.md#create) - Video-to-Video
130
+ * [create](magic_hour/resources/v1/video_to_video/README.md#create) - Video-to-Video
130
131
 
131
132
  <!-- MODULE DOCS END -->
132
133
 
@@ -1,6 +1,6 @@
1
1
  # Magic Hour Python SDK
2
2
 
3
- ![PyPI - Version](https://img.shields.io/pypi/v/magic_hour)
3
+ [![PyPI - Version](https://img.shields.io/pypi/v/magic_hour)](https://pypi.org/project/magic_hour/)
4
4
 
5
5
  Magic Hour provides an API (beta) that can be integrated into your own application to generate videos and images using AI.
6
6
 
@@ -36,78 +36,79 @@ from magic_hour import AsyncClient
36
36
  client = AsyncClient(token="my api key")
37
37
  ```
38
38
 
39
- > **Warning**: any API call that renders a video will utilize frames in your account.
39
+ > [!WARNING]
40
+ > Any API call that renders a video will utilize frames in your account.
40
41
 
41
42
  ## Module Documentation and Snippets
42
43
 
43
44
  ### [v1.ai_clothes_changer](magic_hour/resources/v1/ai_clothes_changer/README.md)
44
45
 
45
- - [create](magic_hour/resources/v1/ai_clothes_changer/README.md#create) - AI Clothes Changer
46
+ * [create](magic_hour/resources/v1/ai_clothes_changer/README.md#create) - AI Clothes Changer
46
47
 
47
48
  ### [v1.ai_headshot_generator](magic_hour/resources/v1/ai_headshot_generator/README.md)
48
49
 
49
- - [create](magic_hour/resources/v1/ai_headshot_generator/README.md#create) - AI Headshots
50
+ * [create](magic_hour/resources/v1/ai_headshot_generator/README.md#create) - AI Headshots
50
51
 
51
52
  ### [v1.ai_image_generator](magic_hour/resources/v1/ai_image_generator/README.md)
52
53
 
53
- - [create](magic_hour/resources/v1/ai_image_generator/README.md#create) - AI Images
54
+ * [create](magic_hour/resources/v1/ai_image_generator/README.md#create) - AI Images
54
55
 
55
56
  ### [v1.ai_image_upscaler](magic_hour/resources/v1/ai_image_upscaler/README.md)
56
57
 
57
- - [create](magic_hour/resources/v1/ai_image_upscaler/README.md#create) - AI Image Upscaler
58
+ * [create](magic_hour/resources/v1/ai_image_upscaler/README.md#create) - AI Image Upscaler
58
59
 
59
60
  ### [v1.ai_photo_editor](magic_hour/resources/v1/ai_photo_editor/README.md)
60
61
 
61
- - [create](magic_hour/resources/v1/ai_photo_editor/README.md#create) - AI Photo Editor
62
+ * [create](magic_hour/resources/v1/ai_photo_editor/README.md#create) - AI Photo Editor
62
63
 
63
64
  ### [v1.ai_qr_code_generator](magic_hour/resources/v1/ai_qr_code_generator/README.md)
64
65
 
65
- - [create](magic_hour/resources/v1/ai_qr_code_generator/README.md#create) - AI QR Code
66
+ * [create](magic_hour/resources/v1/ai_qr_code_generator/README.md#create) - AI QR Code
66
67
 
67
68
  ### [v1.animation](magic_hour/resources/v1/animation/README.md)
68
69
 
69
- - [create](magic_hour/resources/v1/animation/README.md#create) - Animation
70
+ * [create](magic_hour/resources/v1/animation/README.md#create) - Animation
70
71
 
71
72
  ### [v1.face_swap](magic_hour/resources/v1/face_swap/README.md)
72
73
 
73
- - [create](magic_hour/resources/v1/face_swap/README.md#create) - Face Swap video
74
+ * [create](magic_hour/resources/v1/face_swap/README.md#create) - Face Swap video
74
75
 
75
76
  ### [v1.face_swap_photo](magic_hour/resources/v1/face_swap_photo/README.md)
76
77
 
77
- - [create](magic_hour/resources/v1/face_swap_photo/README.md#create) - Face Swap Photo
78
+ * [create](magic_hour/resources/v1/face_swap_photo/README.md#create) - Face Swap Photo
78
79
 
79
80
  ### [v1.files.upload_urls](magic_hour/resources/v1/files/upload_urls/README.md)
80
81
 
81
- - [create](magic_hour/resources/v1/files/upload_urls/README.md#create) - Generate asset upload urls
82
+ * [create](magic_hour/resources/v1/files/upload_urls/README.md#create) - Generate asset upload urls
82
83
 
83
84
  ### [v1.image_background_remover](magic_hour/resources/v1/image_background_remover/README.md)
84
85
 
85
- - [create](magic_hour/resources/v1/image_background_remover/README.md#create) - Image Background Remover
86
+ * [create](magic_hour/resources/v1/image_background_remover/README.md#create) - Image Background Remover
86
87
 
87
88
  ### [v1.image_projects](magic_hour/resources/v1/image_projects/README.md)
88
89
 
89
- - [delete](magic_hour/resources/v1/image_projects/README.md#delete) - Delete image
90
- - [get](magic_hour/resources/v1/image_projects/README.md#get) - Get image details
90
+ * [delete](magic_hour/resources/v1/image_projects/README.md#delete) - Delete image
91
+ * [get](magic_hour/resources/v1/image_projects/README.md#get) - Get image details
91
92
 
92
93
  ### [v1.image_to_video](magic_hour/resources/v1/image_to_video/README.md)
93
94
 
94
- - [create](magic_hour/resources/v1/image_to_video/README.md#create) - Image-to-Video
95
+ * [create](magic_hour/resources/v1/image_to_video/README.md#create) - Image-to-Video
95
96
 
96
97
  ### [v1.lip_sync](magic_hour/resources/v1/lip_sync/README.md)
97
98
 
98
- - [create](magic_hour/resources/v1/lip_sync/README.md#create) - Lip Sync
99
+ * [create](magic_hour/resources/v1/lip_sync/README.md#create) - Lip Sync
99
100
 
100
101
  ### [v1.text_to_video](magic_hour/resources/v1/text_to_video/README.md)
101
102
 
102
- - [create](magic_hour/resources/v1/text_to_video/README.md#create) - Text-to-Video
103
+ * [create](magic_hour/resources/v1/text_to_video/README.md#create) - Text-to-Video
103
104
 
104
105
  ### [v1.video_projects](magic_hour/resources/v1/video_projects/README.md)
105
106
 
106
- - [delete](magic_hour/resources/v1/video_projects/README.md#delete) - Delete video
107
- - [get](magic_hour/resources/v1/video_projects/README.md#get) - Get video details
107
+ * [delete](magic_hour/resources/v1/video_projects/README.md#delete) - Delete video
108
+ * [get](magic_hour/resources/v1/video_projects/README.md#get) - Get video details
108
109
 
109
110
  ### [v1.video_to_video](magic_hour/resources/v1/video_to_video/README.md)
110
111
 
111
- - [create](magic_hour/resources/v1/video_to_video/README.md#create) - Video-to-Video
112
+ * [create](magic_hour/resources/v1/video_to_video/README.md#create) - Video-to-Video
112
113
 
113
114
  <!-- MODULE DOCS END -->
@@ -1,4 +1,10 @@
1
+ """
2
+ Generated by Sideko (sideko.dev)
3
+ """
4
+
5
+ from json import JSONDecodeError
1
6
  import typing
7
+ import httpx
2
8
 
3
9
 
4
10
  class ApiError(Exception):
@@ -13,29 +19,31 @@ class ApiError(Exception):
13
19
  None if no status code is applicable.
14
20
  body: The response body or error message content.
15
21
  Can be any type depending on the API response format.
22
+ response: The raw httpx response object. See https://www.python-httpx.org/api/#response for object reference
16
23
  """
17
24
 
18
25
  status_code: typing.Optional[int]
19
26
  body: typing.Any
27
+ response: httpx.Response
20
28
 
21
- def __init__(
22
- self, *, status_code: typing.Optional[int] = None, body: typing.Any = None
23
- ) -> None:
29
+ def __init__(self, *, response: httpx.Response) -> None:
24
30
  """
25
31
  Initialize the ApiError with optional status code and body.
26
32
 
27
33
  Args:
28
34
  status_code: The HTTP status code of the error.
29
35
  Defaults to None.
30
- body: The response body or error message content.
31
- Defaults to None.
32
36
 
33
37
  Note:
34
38
  The asterisk (*) in the parameters forces keyword arguments,
35
39
  making the instantiation more explicit.
36
40
  """
37
- self.status_code = status_code
38
- self.body = body
41
+ try:
42
+ self.body = response.json()
43
+ except JSONDecodeError:
44
+ self.body = None
45
+ self.status_code = response.status_code
46
+ self.response = response
39
47
 
40
48
  def __str__(self) -> str:
41
49
  """
@@ -1,4 +1,3 @@
1
- from json import JSONDecodeError
2
1
  from typing import (
3
2
  Any,
4
3
  List,
@@ -9,6 +8,7 @@ from typing import (
9
8
  Union,
10
9
  cast,
11
10
  )
11
+ from typing_extensions import TypeGuard
12
12
 
13
13
  import httpx
14
14
  from pydantic import BaseModel
@@ -17,7 +17,7 @@ from .api_error import ApiError
17
17
  from .auth import AuthProvider
18
18
  from .request import RequestConfig, RequestOptions, default_request_options, QueryParams
19
19
  from .response import from_encodable, AsyncStreamResponse, StreamResponse
20
- from .utils import is_binary_content_type, get_content_type
20
+ from .utils import get_response_type, filter_binary_response
21
21
  from .binary_response import BinaryResponse
22
22
 
23
23
  NoneType = type(None)
@@ -96,6 +96,15 @@ class BaseClient:
96
96
 
97
97
  return f"{base}/{path}"
98
98
 
99
+ def _cast_to_raw_response(
100
+ self, res: httpx.Response, cast_to: Union[Type[T], Any]
101
+ ) -> TypeGuard[T]:
102
+ """Determines if the provided cast_to is an httpx.Response"""
103
+ try:
104
+ return issubclass(cast_to, httpx.Response)
105
+ except TypeError:
106
+ return False
107
+
99
108
  def _apply_auth(
100
109
  self, *, cfg: RequestConfig, auth_names: List[str]
101
110
  ) -> RequestConfig:
@@ -307,35 +316,30 @@ class BaseClient:
307
316
  Raises:
308
317
  ApiError: If the response indicates an error
309
318
  """
310
- if 200 <= response.status_code < 300:
311
- content_type = get_content_type(response.headers)
312
- if response.status_code == 204 or cast_to == NoneType:
313
- return cast(T, None)
314
- elif cast_to == BinaryResponse:
315
- return cast(
316
- T,
317
- BinaryResponse(content=response.content, headers=response.headers),
318
- )
319
- else:
320
- if "json" in content_type or "form" in content_type:
321
- if cast_to is type(Any):
322
- return response.json()
323
- return from_encodable(data=response.json(), load_with=cast_to)
324
- elif is_binary_content_type(content_type):
325
- return cast(
326
- T,
327
- BinaryResponse(
328
- content=response.content, headers=response.headers
329
- ),
330
- )
331
- else:
332
- return from_encodable(data=response.content, load_with=cast_to)
319
+
320
+ if response.status_code == 204 or cast_to == NoneType:
321
+ return cast(T, None)
322
+ elif cast_to == BinaryResponse:
323
+ return cast(
324
+ T,
325
+ BinaryResponse(content=response.content, headers=response.headers),
326
+ )
327
+
328
+ response_type = get_response_type(response.headers)
329
+
330
+ if response_type == "json":
331
+ if cast_to is type(Any):
332
+ return response.json()
333
+ return from_encodable(
334
+ data=response.json(), load_with=filter_binary_response(cast_to=cast_to)
335
+ )
336
+ elif response_type == "text":
337
+ return cast(T, response.text)
333
338
  else:
334
- try:
335
- response_json = response.json()
336
- except JSONDecodeError:
337
- raise ApiError(status_code=response.status_code, body=response.text)
338
- raise ApiError(status_code=response.status_code, body=response_json)
339
+ return cast(
340
+ T,
341
+ BinaryResponse(content=response.content, headers=response.headers),
342
+ )
339
343
 
340
344
 
341
345
  class SyncBaseClient(BaseClient):
@@ -411,6 +415,13 @@ class SyncBaseClient(BaseClient):
411
415
  request_options=request_options,
412
416
  )
413
417
  response = self.httpx_client.request(**req_cfg)
418
+
419
+ if not response.is_success:
420
+ raise ApiError(response=response)
421
+
422
+ if self._cast_to_raw_response(res=response, cast_to=cast_to):
423
+ return response
424
+
414
425
  return self.process_response(response=response, cast_to=cast_to)
415
426
 
416
427
  def stream_request(
@@ -542,6 +553,13 @@ class AsyncBaseClient(BaseClient):
542
553
  request_options=request_options,
543
554
  )
544
555
  response = await self.httpx_client.request(**req_cfg)
556
+
557
+ if not response.is_success:
558
+ raise ApiError(response=response)
559
+
560
+ if self._cast_to_raw_response(res=response, cast_to=cast_to):
561
+ return response
562
+
545
563
  return self.process_response(response=response, cast_to=cast_to)
546
564
 
547
565
  async def stream_request(
@@ -0,0 +1,55 @@
1
+ import typing
2
+ import re
3
+ from typing_extensions import Literal
4
+
5
+ import httpx
6
+
7
+ from .binary_response import BinaryResponse
8
+
9
+
10
+ def remove_none_from_dict(
11
+ original: typing.Dict[str, typing.Optional[typing.Any]],
12
+ ) -> typing.Dict[str, typing.Any]:
13
+ new: typing.Dict[str, typing.Any] = {}
14
+ for key, value in original.items():
15
+ if value is not None:
16
+ new[key] = value
17
+ return new
18
+
19
+
20
+ def get_response_type(headers: httpx.Headers) -> Literal["json", "text", "binary"]:
21
+ """Check response type based on content type"""
22
+ content_type = headers.get("content-type")
23
+
24
+ if re.search("^application/(.+\+)?json", content_type):
25
+ return "json"
26
+ elif re.search("^text/(.+)", content_type):
27
+ return "text"
28
+ else:
29
+ return "binary"
30
+
31
+
32
+ def is_union_type(type_hint: typing.Any) -> bool:
33
+ """Check if a type hint is a Union type."""
34
+ return hasattr(type_hint, "__origin__") and type_hint.__origin__ is typing.Union
35
+
36
+
37
+ def filter_binary_response(cast_to: typing.Type) -> typing.Type:
38
+ """
39
+ Filters out BinaryResponse from a Union type.
40
+ If cast_to is not a Union, returns it unchanged.
41
+ """
42
+ if not is_union_type(cast_to):
43
+ return cast_to
44
+
45
+ types = typing.get_args(cast_to)
46
+ filtered = tuple(t for t in types if t != BinaryResponse)
47
+
48
+ # If everything was filtered out, return original type
49
+ if not filtered:
50
+ return cast_to
51
+ # If only one type remains, return it directly
52
+ if len(filtered) == 1:
53
+ return typing.cast(typing.Type, filtered[0])
54
+ # Otherwise return new Union with filtered types
55
+ return typing.cast(typing.Type, typing.Union[filtered]) # type: ignore
@@ -3,4 +3,4 @@ import enum
3
3
 
4
4
  class Environment(enum.Enum):
5
5
  ENVIRONMENT = "https://api.magichour.ai"
6
- MOCK_SERVER = "https://api.sideko.dev/v1/mock/magichour/magic-hour/0.8.1"
6
+ MOCK_SERVER = "https://api.sideko.dev/v1/mock/magichour/magic-hour/0.8.3"
@@ -19,8 +19,8 @@ res = client.v1.animation.create(
19
19
  "audio_source": "file",
20
20
  "image_file_path": "api-assets/id/1234.png",
21
21
  },
22
- end_seconds=15,
23
- fps=12,
22
+ end_seconds=15.0,
23
+ fps=12.0,
24
24
  height=960,
25
25
  style={
26
26
  "art_style": "Painterly Illustration",
@@ -47,8 +47,8 @@ res = await client.v1.animation.create(
47
47
  "audio_source": "file",
48
48
  "image_file_path": "api-assets/id/1234.png",
49
49
  },
50
- end_seconds=15,
51
- fps=12,
50
+ end_seconds=15.0,
51
+ fps=12.0,
52
52
  height=960,
53
53
  style={
54
54
  "art_style": "Painterly Illustration",
@@ -57,8 +57,8 @@ class AnimationClient:
57
57
  ```py
58
58
  client.v1.animation.create(
59
59
  assets={"audio_source": "file"},
60
- end_seconds=15,
61
- fps=12,
60
+ end_seconds=15.0,
61
+ fps=12.0,
62
62
  height=960,
63
63
  style={
64
64
  "art_style": "Painterly Illustration",
@@ -141,8 +141,8 @@ class AsyncAnimationClient:
141
141
  ```py
142
142
  await client.v1.animation.create(
143
143
  assets={"audio_source": "file"},
144
- end_seconds=15,
145
- fps=12,
144
+ end_seconds=15.0,
145
+ fps=12.0,
146
146
  height=960,
147
147
  style={
148
148
  "art_style": "Painterly Illustration",
@@ -22,9 +22,9 @@ res = client.v1.face_swap.create(
22
22
  "video_file_path": "video/id/1234.mp4",
23
23
  "video_source": "file",
24
24
  },
25
- end_seconds=15,
25
+ end_seconds=15.0,
26
26
  height=960,
27
- start_seconds=0,
27
+ start_seconds=0.0,
28
28
  width=512,
29
29
  name="Face Swap video",
30
30
  )
@@ -43,9 +43,9 @@ res = await client.v1.face_swap.create(
43
43
  "video_file_path": "video/id/1234.mp4",
44
44
  "video_source": "file",
45
45
  },
46
- end_seconds=15,
46
+ end_seconds=15.0,
47
47
  height=960,
48
- start_seconds=0,
48
+ start_seconds=0.0,
49
49
  width=512,
50
50
  name="Face Swap video",
51
51
  )
@@ -58,9 +58,9 @@ class FaceSwapClient:
58
58
  ```py
59
59
  client.v1.face_swap.create(
60
60
  assets={"image_file_path": "image/id/1234.png", "video_source": "file"},
61
- end_seconds=15,
61
+ end_seconds=15.0,
62
62
  height=960,
63
- start_seconds=0,
63
+ start_seconds=0.0,
64
64
  width=512,
65
65
  name="Face Swap video",
66
66
  )
@@ -135,9 +135,9 @@ class AsyncFaceSwapClient:
135
135
  ```py
136
136
  await client.v1.face_swap.create(
137
137
  assets={"image_file_path": "image/id/1234.png", "video_source": "file"},
138
- end_seconds=15,
138
+ end_seconds=15.0,
139
139
  height=960,
140
- start_seconds=0,
140
+ start_seconds=0.0,
141
141
  width=512,
142
142
  name="Face Swap video",
143
143
  )
@@ -13,7 +13,7 @@ from magic_hour import Client
13
13
  from os import getenv
14
14
 
15
15
  client = Client(token=getenv("API_TOKEN"))
16
- res = client.v1.image_projects.delete(id="string")
16
+ res = client.v1.image_projects.delete(id="cm6pvghix03bvyz0zwash6noj")
17
17
  ```
18
18
 
19
19
  #### Asynchronous Client
@@ -23,7 +23,7 @@ from magic_hour import AsyncClient
23
23
  from os import getenv
24
24
 
25
25
  client = AsyncClient(token=getenv("API_TOKEN"))
26
- res = await client.v1.image_projects.delete(id="string")
26
+ res = await client.v1.image_projects.delete(id="cm6pvghix03bvyz0zwash6noj")
27
27
  ```
28
28
 
29
29
  ### get <a name="get"></a>
@@ -49,7 +49,7 @@ from magic_hour import Client
49
49
  from os import getenv
50
50
 
51
51
  client = Client(token=getenv("API_TOKEN"))
52
- res = client.v1.image_projects.get(id="string")
52
+ res = client.v1.image_projects.get(id="cm6pvghix03bvyz0zwash6noj")
53
53
  ```
54
54
 
55
55
  #### Asynchronous Client
@@ -59,5 +59,5 @@ from magic_hour import AsyncClient
59
59
  from os import getenv
60
60
 
61
61
  client = AsyncClient(token=getenv("API_TOKEN"))
62
- res = await client.v1.image_projects.get(id="string")
62
+ res = await client.v1.image_projects.get(id="cm6pvghix03bvyz0zwash6noj")
63
63
  ```
@@ -36,7 +36,7 @@ class ImageProjectsClient:
36
36
 
37
37
  Examples:
38
38
  ```py
39
- client.v1.image_projects.delete(id="string")
39
+ client.v1.image_projects.delete(id="cm6pvghix03bvyz0zwash6noj")
40
40
  ```
41
41
 
42
42
  """
@@ -80,7 +80,7 @@ class ImageProjectsClient:
80
80
 
81
81
  Examples:
82
82
  ```py
83
- client.v1.image_projects.get(id="string")
83
+ client.v1.image_projects.get(id="cm6pvghix03bvyz0zwash6noj")
84
84
  ```
85
85
 
86
86
  """
@@ -120,7 +120,7 @@ class AsyncImageProjectsClient:
120
120
 
121
121
  Examples:
122
122
  ```py
123
- await client.v1.image_projects.delete(id="string")
123
+ await client.v1.image_projects.delete(id="cm6pvghix03bvyz0zwash6noj")
124
124
  ```
125
125
 
126
126
  """
@@ -164,7 +164,7 @@ class AsyncImageProjectsClient:
164
164
 
165
165
  Examples:
166
166
  ```py
167
- await client.v1.image_projects.get(id="string")
167
+ await client.v1.image_projects.get(id="cm6pvghix03bvyz0zwash6noj")
168
168
  ```
169
169
 
170
170
  """
@@ -18,7 +18,7 @@ from os import getenv
18
18
  client = Client(token=getenv("API_TOKEN"))
19
19
  res = client.v1.image_to_video.create(
20
20
  assets={"image_file_path": "image/id/1234.png"},
21
- end_seconds=5,
21
+ end_seconds=5.0,
22
22
  height=960,
23
23
  style={"prompt": None},
24
24
  width=512,
@@ -35,7 +35,7 @@ from os import getenv
35
35
  client = AsyncClient(token=getenv("API_TOKEN"))
36
36
  res = await client.v1.image_to_video.create(
37
37
  assets={"image_file_path": "image/id/1234.png"},
38
- end_seconds=5,
38
+ end_seconds=5.0,
39
39
  height=960,
40
40
  style={"prompt": None},
41
41
  width=512,
@@ -58,7 +58,7 @@ class ImageToVideoClient:
58
58
  ```py
59
59
  client.v1.image_to_video.create(
60
60
  assets={"image_file_path": "image/id/1234.png"},
61
- end_seconds=5,
61
+ end_seconds=5.0,
62
62
  height=960,
63
63
  style={"prompt": "string"},
64
64
  width=512,
@@ -135,7 +135,7 @@ class AsyncImageToVideoClient:
135
135
  ```py
136
136
  await client.v1.image_to_video.create(
137
137
  assets={"image_file_path": "image/id/1234.png"},
138
- end_seconds=5,
138
+ end_seconds=5.0,
139
139
  height=960,
140
140
  style={"prompt": "string"},
141
141
  width=512,