eyeD3 0.9.8a1__tar.gz → 0.9.8a5__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 (128) hide show
  1. eyed3-0.9.8a5/.readthedocs.yaml +17 -0
  2. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/AUTHORS.rst +6 -0
  3. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/MANIFEST.in +2 -3
  4. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/Makefile +46 -52
  5. {eyed3-0.9.8a1/eyeD3.egg-info → eyed3-0.9.8a5}/PKG-INFO +6 -11
  6. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/README.rst +5 -10
  7. {eyed3-0.9.8a1 → eyed3-0.9.8a5/eyeD3.egg-info}/PKG-INFO +6 -11
  8. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/eyeD3.egg-info/SOURCES.txt +4 -1
  9. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/eyed3/__regarding__.py +3 -3
  10. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/eyed3/core.py +42 -15
  11. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/eyed3/id3/__init__.py +2 -2
  12. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/eyed3/id3/apple.py +16 -0
  13. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/eyed3/id3/frames.py +11 -2
  14. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/eyed3/id3/tag.py +2 -2
  15. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/eyed3/plugins/mimetype.py +2 -37
  16. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/pyproject.toml +3 -6
  17. eyed3-0.9.8a5/requirements/dev-requirements.txt +97 -0
  18. eyed3-0.9.8a5/requirements/plugin-requirements.txt +21 -0
  19. eyed3-0.9.8a5/requirements/requirements.txt +7 -0
  20. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/tests/conftest.py +7 -0
  21. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/tests/id3/test_frames.py +0 -3
  22. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/tests/id3/test_id3.py +1 -1
  23. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/tests/id3/test_tag.py +19 -1
  24. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/tests/test_core.py +4 -6
  25. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/tox.ini +1 -1
  26. eyed3-0.9.8a1/pdm.lock +0 -1900
  27. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/CONTRIBUTING.rst +0 -0
  28. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/HISTORY.rst +0 -0
  29. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/LICENSE +0 -0
  30. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/docs/Makefile +0 -0
  31. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/docs/_config.yml +0 -0
  32. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/docs/_static/.keep +0 -0
  33. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/docs/_static/rtd.css +0 -0
  34. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/docs/_templates/.keepme +0 -0
  35. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/docs/authors.rst +0 -0
  36. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/docs/cli.rst +0 -0
  37. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/docs/compliance.rst +0 -0
  38. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/docs/conf.py +0 -0
  39. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/docs/contributing.rst +0 -0
  40. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/docs/eyeD3.1 +0 -0
  41. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/docs/eyed3.id3.rst +5 -5
  42. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/docs/eyed3.mp3.rst +2 -2
  43. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/docs/eyed3.plugins.rst +16 -16
  44. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/docs/eyed3.rst +4 -4
  45. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/docs/eyed3.utils.rst +6 -6
  46. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/docs/history.rst +0 -0
  47. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/docs/index.rst +0 -0
  48. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/docs/installation.rst +0 -0
  49. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/docs/make.bat +0 -0
  50. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/docs/modules.rst +0 -0
  51. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/docs/plugins/art_plugin.rst +0 -0
  52. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/docs/plugins/classic_plugin.rst +0 -0
  53. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/docs/plugins/extract_plugin.rst +0 -0
  54. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/docs/plugins/fixup_plugin.rst +0 -0
  55. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/docs/plugins/genres_plugin.rst +0 -0
  56. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/docs/plugins/itunes_plugin.rst +0 -0
  57. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/docs/plugins/json_plugin.rst +0 -0
  58. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/docs/plugins/lameinfo_plugin.rst +0 -0
  59. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/docs/plugins/mimetypes_plugin.rst +0 -0
  60. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/docs/plugins/nfo_plugin.rst +0 -0
  61. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/docs/plugins/pymod_plugin.rst +0 -0
  62. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/docs/plugins/stats_plugin.rst +0 -0
  63. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/docs/plugins/xep118_plugin.rst +0 -0
  64. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/docs/plugins/yaml_plugin.rst +0 -0
  65. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/docs/plugins.rst +0 -0
  66. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/docs/readme.rst +0 -0
  67. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/docs/usage.rst +0 -0
  68. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/examples/chapters.py +0 -0
  69. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/examples/cli_examples.sh +0 -0
  70. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/examples/config.ini +0 -0
  71. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/examples/plugins/echo.py +0 -0
  72. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/examples/plugins/echo2.py +0 -0
  73. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/examples/tag_example.py +0 -0
  74. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/eyeD3.egg-info/dependency_links.txt +0 -0
  75. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/eyeD3.egg-info/entry_points.txt +0 -0
  76. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/eyeD3.egg-info/requires.txt +0 -0
  77. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/eyeD3.egg-info/top_level.txt +0 -0
  78. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/eyed3/__about__.py +0 -0
  79. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/eyed3/__init__.py +0 -0
  80. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/eyed3/id3/headers.py +0 -0
  81. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/eyed3/main.py +0 -0
  82. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/eyed3/mimetype.py +0 -0
  83. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/eyed3/mp3/__init__.py +0 -0
  84. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/eyed3/mp3/headers.py +0 -0
  85. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/eyed3/plugins/__init__.py +0 -0
  86. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/eyed3/plugins/art.py +0 -0
  87. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/eyed3/plugins/classic.py +0 -0
  88. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/eyed3/plugins/extract.py +0 -0
  89. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/eyed3/plugins/fixup.py +0 -0
  90. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/eyed3/plugins/genres.py +0 -0
  91. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/eyed3/plugins/itunes.py +0 -0
  92. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/eyed3/plugins/jsontag.py +0 -0
  93. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/eyed3/plugins/lameinfo.py +0 -0
  94. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/eyed3/plugins/lastfm.py +0 -0
  95. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/eyed3/plugins/nfo.py +0 -0
  96. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/eyed3/plugins/pymod.py +0 -0
  97. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/eyed3/plugins/stats.py +0 -0
  98. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/eyed3/plugins/xep_118.py +0 -0
  99. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/eyed3/plugins/yamltag.py +0 -0
  100. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/eyed3/utils/__init__.py +0 -0
  101. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/eyed3/utils/art.py +0 -0
  102. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/eyed3/utils/binfuncs.py +0 -0
  103. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/eyed3/utils/console.py +0 -0
  104. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/eyed3/utils/log.py +0 -0
  105. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/eyed3/utils/prompt.py +0 -0
  106. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/setup.cfg +0 -0
  107. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/setup.py +0 -0
  108. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/tests/__init__.py +0 -0
  109. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/tests/id3/__init__.py +0 -0
  110. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/tests/id3/test_headers.py +0 -0
  111. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/tests/id3/test_rva.py +0 -0
  112. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/tests/mp3/__init__.py +0 -0
  113. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/tests/mp3/test_infos.py +0 -0
  114. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/tests/mp3/test_mp3.py +0 -0
  115. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/tests/pytest.ini +0 -0
  116. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/tests/test__init__.py +0 -0
  117. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/tests/test_binfuncs.py +0 -0
  118. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/tests/test_classic_plugin.py +0 -0
  119. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/tests/test_console.py +0 -0
  120. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/tests/test_factory.py +0 -0
  121. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/tests/test_issues.py +0 -0
  122. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/tests/test_jsonyaml_plugin.py +0 -0
  123. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/tests/test_lameinfo_plugin.py +0 -0
  124. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/tests/test_main.py +0 -0
  125. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/tests/test_mimetype.py +0 -0
  126. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/tests/test_plugins.py +0 -0
  127. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/tests/test_stats_plugins.py +0 -0
  128. {eyed3-0.9.8a1 → eyed3-0.9.8a5}/tests/test_utils.py +0 -0
@@ -0,0 +1,17 @@
1
+ # Read the Docs configuration file for Sphinx projects
2
+ # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
3
+
4
+ version: 2
5
+
6
+ build:
7
+ os: ubuntu-22.04
8
+ tools:
9
+ python: "3.12"
10
+
11
+ sphinx:
12
+ configuration: docs/conf.py
13
+
14
+ python:
15
+ install:
16
+ - method: pip
17
+ path: .[dev]
@@ -37,3 +37,9 @@ and has been contributed to by (ordered by date of first contribution):
37
37
  * grun <grunseid@gmail.com>
38
38
  * guiweber <guillaume.web@gmail.com>
39
39
  * zhu <zhumumu@gmail.com>
40
+ * Michał Górny <mgorny@gentoo.org>
41
+ * Jonathan Herlin <Jonte@jherlin.se>
42
+ * Ramiro Gómez <code@ramiro.org>
43
+ * Steve Kowalik <steven@wedontsleep.org>
44
+ * gersonkurz <gerson.kurz@gmail.com>
45
+ * obskyr <powpowd@gmail.com>
@@ -7,6 +7,7 @@ include Makefile
7
7
  include tox.ini
8
8
  include setup.py
9
9
  include pdm.lock
10
+ include .readthedocs.yaml
10
11
 
11
12
  graft docs
12
13
  prune docs/_build
@@ -25,8 +26,6 @@ recursive-include requirements *.txt
25
26
  recursive-include eyed3 *.py
26
27
  recursive-include examples *
27
28
 
28
- exclude fabfile.py
29
- exclude mkenv.sh
30
- exclude pavement.py
29
+ exclude pdm.lock
31
30
  prune etc
32
31
 
@@ -88,10 +88,13 @@ clean-local:
88
88
  ### Test
89
89
  .PHONY: test
90
90
  test: ## Run tests with default python
91
- tox -e py
91
+ tox -e py,lint
92
92
 
93
+ SKIP_TEST_ALL ?= no
93
94
  test-all: ## Run tests with all supported versions of Python
94
- tox --parallel=all
95
+ @if [ "$(SKIP_TEST_ALL)" != yes ]; then \
96
+ tox --parallel=all ;\
97
+ fi
95
98
 
96
99
  test-data:
97
100
  # Move these to eyed3.nicfit.net
@@ -146,10 +149,9 @@ docs: ## Generate project documentation with Sphinx
146
149
  $(MAKE) -C docs html
147
150
  -rm example.id3
148
151
 
152
+ DOCS_DIST := $(PROJECT_NAME)-$(VERSION)-docs.tar.gz
149
153
  docs-dist: docs
150
- test -d dist || mkdir dist
151
- cd docs/_build && \
152
- tar czvf ../../dist/$(PROJECT_NAME)-$(VERSION)-docs.tar.gz html
154
+ cd docs/_build && tar czvf ./$(DOCS_DIST) html
153
155
 
154
156
  docs-view: docs
155
157
  $(BROWSER) docs/_build/html/index.html
@@ -164,12 +166,13 @@ clean-docs:
164
166
  dist: clean-dist lint all docs-dist ## Create source and binary distribution files
165
167
 
166
168
  _dist-md5:
167
- @# The cd dist keeps the dist/ prefix out of the md5sum files
169
+ @# The cd dist/docs keeps the dist/ prefix out of the md5sum files
170
+ cd docs/_build/ && md5sum $(DOCS_DIST) >| $(DOCS_DIST).md5
168
171
  @cd dist && \
169
172
  for f in $$(ls -I '*.md5'); do \
170
173
  md5sum $${f} >| $${f}.md5; \
171
174
  done
172
- @ls -l dist
175
+ @ls -l docs/_build/$(DOCS_DIST)* dist
173
176
 
174
177
 
175
178
  clean-dist: ## Clean distribution artifacts (included in `clean`)
@@ -185,17 +188,18 @@ release-tag: _check-clean-repo _check-version-tag _check-main-branch
185
188
  fi
186
189
  git push origin $(RELEASE_TAG)
187
190
 
188
- #authors:
189
- # @git authors --list | while read auth ; do \
190
- # email=`echo "$$auth" | awk 'match($$0, /.*<(.*)>/, m) {print m[1]}'`;\
191
- # echo "Checking $$email...";\
192
- # if echo "$$email" | grep -v 'users.noreply.github.com'\
193
- # | grep -v 'github-bot@pyup.io' \
194
- # > /dev/null ; then \
195
- # grep "$$email" AUTHORS.rst > /dev/null || echo " * $$auth" >> AUTHORS.rst;\
196
- # fi;\
197
- # done
198
- #
191
+ authors:
192
+ @# requires git-extras
193
+ @git authors --list | while read auth ; do \
194
+ email=`echo "$$auth" | awk 'match($$0, /.*<(.*)>/, m) {print m[1]}'`;\
195
+ echo "Checking $$email...";\
196
+ if echo "$$email" | grep -v 'users.noreply.github.com'\
197
+ | grep -v 'github-bot@pyup.io' \
198
+ > /dev/null ; then \
199
+ grep "$$email" AUTHORS.rst > /dev/null || echo " * $$auth" >> AUTHORS.rst;\
200
+ fi;\
201
+ done
202
+
199
203
 
200
204
  ## Install
201
205
  install: ## Install project and dependencies
@@ -211,36 +215,34 @@ install-all: install install-extra install-dev
211
215
 
212
216
 
213
217
  ## Release
214
- release: _check-on-release-tag _check-clean-repo _check-gh _check-pypi pre-release upload-release
218
+ .PHONY: release
219
+ release: _check-on-release-tag _check-clean-repo _check-gh _check-pypi dist publish-release
215
220
 
216
- pre-release: dist check-manifest test-all _check-clean-repo
217
- #pre-release: # authors changelog
221
+ pre-release: _check-version-tag dist check-manifest test-all requirements authors _check-clean-repo
222
+ #pre-release: # changelog
218
223
 
219
- upload-release: _pypi-release _web-release _github-release
224
+ # Order is import here
225
+ publish-release: _pypi-publish _web-publish _github-publish _docs-publish
226
+
227
+ _pypi-publish:
228
+ pdm publish --no-build -r $(PYPI_REPO) --skip-existing --dest ./dist
229
+
230
+ _web-publish: _dist-md5
231
+ for f in `find ./dist -type f`; do \
232
+ scp $$f eyed3.nicfit.net:./data1/eyeD3-releases/`basename $$f`; \
233
+ done
220
234
 
221
- _pypi-release:
222
- pdm publish -r ${PYPI_REPO}
235
+ _docs-publish:
236
+ # TODO: READTHEDOCS
223
237
 
224
- _github-release:
238
+ _github-publish:
225
239
  @# TODO: --prerelease if appropriate
226
240
  @# TODO: --notes-file when release notes are available
227
241
  @# TODO: --latest=false when prerelease is used
228
242
  gh release --repo nicfit/eyeD3 create $(RELEASE_TAG) --verify-tag \
229
243
  --title "$(RELEASE_TAG) ($(RELEASE_NAME))" \
230
- --draft --prerelease \
231
- --generate-notes ./dist/*.tar.gz
232
-
233
- # prerelease=""; \
234
- # if echo "${RELEASE_TAG}" | grep '[^v0-9\.]'; then \
235
- # prerelease="--pre-release"; \
236
- # fi; \
237
- # echo "NAME: $$name"; \
238
- # echo "PRERELEASE: $$prerelease"; \
239
-
240
- _web-release:
241
- for f in `find ./dist -type f`; do \
242
- scp $$f eyed3.nicfit.net:./data1/eyeD3-releases/`basename $$f`; \
243
- done
244
+ --draft \
245
+ --generate-notes ./dist/*.tar.gz ./dist/*.whl
244
246
 
245
247
  #changelog:
246
248
  # @last=`git tag -l --sort=version:refname | grep '^v[0-9]' | tail -n1`;\
@@ -331,21 +333,13 @@ _check-pypi:
331
333
  @(test -n "${PDM_PUBLISH_USERNAME}" && test -n "${PDM_PUBLISH_PASSWORD}") || \
332
334
  (echo "PDM_BUBLISH_* not set, needed for PyPI publish" && false)
333
335
 
334
- #bump-release: requirements
336
+ #bump-release:
335
337
  # @# TODO: is not a pre-release, clear release_name
336
338
  # poetry version $(BUMP)
337
339
 
338
340
  .PHONY: requirements
339
341
  requirements:
340
- pdm outdated
341
- pdm update --unconstrained --update-all -d
342
- # poetry update --lock
343
- # poetry export -f requirements.txt --without-hashes\
344
- # --output requirements/requirements.txt
345
- # poetry export -f requirements.txt --without-hashes\
346
- # --output requirements/test-requirements.txt -E test
347
- # poetry export -f requirements.txt --without-hashes --output requirements/dev-requirements.txt --with dev
348
- # poetry export -f requirements.txt --without-hashes\
349
- # --output requirements/extra-requirements.txt \
350
- # -E art-plugin -E yaml-plugin
351
- # $(MAKE) build
342
+ pdm lock -G:all
343
+ pdm export --prod --no-hashes >| requirements/requirements.txt
344
+ pdm export -G test,dev --no-hashes >| requirements/dev-requirements.txt
345
+ pdm export -G yaml-plugim,art-plugin --no-hashes >| requirements/plugin-requirements.txt
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: eyeD3
3
- Version: 0.9.8a1
3
+ Version: 0.9.8a5
4
4
  Summary: Python audio data toolkit (ID3 and MP3)
5
5
  Author-email: Travis Shirk <travis@pobox.com>
6
6
  Project-URL: homepage, https://eyeD3.nicfit.net/
@@ -56,21 +56,16 @@ Status
56
56
  .. image:: https://img.shields.io/pypi/v/eyeD3.svg
57
57
  :target: https://pypi.python.org/pypi/eyeD3/
58
58
  :alt: Latest Version
59
- .. image:: https://img.shields.io/pypi/status/eyeD3.svg
60
- :target: https://pypi.python.org/pypi/eyeD3/
61
- :alt: Project Status
62
- .. image:: https://travis-ci.org/nicfit/eyeD3.svg?branch=master
63
- :target: https://travis-ci.org/nicfit/eyeD3
64
- :alt: Build Status
65
59
  .. image:: https://img.shields.io/pypi/l/eyeD3.svg
66
60
  :target: https://pypi.python.org/pypi/eyeD3/
67
61
  :alt: License
68
62
  .. image:: https://img.shields.io/pypi/pyversions/eyeD3.svg
69
63
  :target: https://pypi.python.org/pypi/eyeD3/
70
64
  :alt: Supported Python versions
71
- .. image:: https://coveralls.io/repos/nicfit/eyeD3/badge.svg
72
- :target: https://coveralls.io/r/nicfit/eyeD3
73
- :alt: Coverage Status
65
+ .. image:: https://img.shields.io/pypi/dm/eyeD3
66
+ :alt: PyPI - Downloads
67
+ .. image:: https://img.shields.io/github/stars/nicfit/eyeD3
68
+ :alt: GitHub Repo stars
74
69
 
75
70
 
76
71
  About
@@ -145,7 +140,7 @@ Features
145
140
  Get Started
146
141
  -----------
147
142
 
148
- Python >= 3.7 is required.
143
+ Python >= 3.9 is required.
149
144
 
150
145
  For `installation instructions`_ or more complete `documentation`_ see
151
146
  http://eyeD3.nicfit.net/
@@ -3,21 +3,16 @@ Status
3
3
  .. image:: https://img.shields.io/pypi/v/eyeD3.svg
4
4
  :target: https://pypi.python.org/pypi/eyeD3/
5
5
  :alt: Latest Version
6
- .. image:: https://img.shields.io/pypi/status/eyeD3.svg
7
- :target: https://pypi.python.org/pypi/eyeD3/
8
- :alt: Project Status
9
- .. image:: https://travis-ci.org/nicfit/eyeD3.svg?branch=master
10
- :target: https://travis-ci.org/nicfit/eyeD3
11
- :alt: Build Status
12
6
  .. image:: https://img.shields.io/pypi/l/eyeD3.svg
13
7
  :target: https://pypi.python.org/pypi/eyeD3/
14
8
  :alt: License
15
9
  .. image:: https://img.shields.io/pypi/pyversions/eyeD3.svg
16
10
  :target: https://pypi.python.org/pypi/eyeD3/
17
11
  :alt: Supported Python versions
18
- .. image:: https://coveralls.io/repos/nicfit/eyeD3/badge.svg
19
- :target: https://coveralls.io/r/nicfit/eyeD3
20
- :alt: Coverage Status
12
+ .. image:: https://img.shields.io/pypi/dm/eyeD3
13
+ :alt: PyPI - Downloads
14
+ .. image:: https://img.shields.io/github/stars/nicfit/eyeD3
15
+ :alt: GitHub Repo stars
21
16
 
22
17
 
23
18
  About
@@ -92,7 +87,7 @@ Features
92
87
  Get Started
93
88
  -----------
94
89
 
95
- Python >= 3.7 is required.
90
+ Python >= 3.9 is required.
96
91
 
97
92
  For `installation instructions`_ or more complete `documentation`_ see
98
93
  http://eyeD3.nicfit.net/
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: eyeD3
3
- Version: 0.9.8a1
3
+ Version: 0.9.8a5
4
4
  Summary: Python audio data toolkit (ID3 and MP3)
5
5
  Author-email: Travis Shirk <travis@pobox.com>
6
6
  Project-URL: homepage, https://eyeD3.nicfit.net/
@@ -56,21 +56,16 @@ Status
56
56
  .. image:: https://img.shields.io/pypi/v/eyeD3.svg
57
57
  :target: https://pypi.python.org/pypi/eyeD3/
58
58
  :alt: Latest Version
59
- .. image:: https://img.shields.io/pypi/status/eyeD3.svg
60
- :target: https://pypi.python.org/pypi/eyeD3/
61
- :alt: Project Status
62
- .. image:: https://travis-ci.org/nicfit/eyeD3.svg?branch=master
63
- :target: https://travis-ci.org/nicfit/eyeD3
64
- :alt: Build Status
65
59
  .. image:: https://img.shields.io/pypi/l/eyeD3.svg
66
60
  :target: https://pypi.python.org/pypi/eyeD3/
67
61
  :alt: License
68
62
  .. image:: https://img.shields.io/pypi/pyversions/eyeD3.svg
69
63
  :target: https://pypi.python.org/pypi/eyeD3/
70
64
  :alt: Supported Python versions
71
- .. image:: https://coveralls.io/repos/nicfit/eyeD3/badge.svg
72
- :target: https://coveralls.io/r/nicfit/eyeD3
73
- :alt: Coverage Status
65
+ .. image:: https://img.shields.io/pypi/dm/eyeD3
66
+ :alt: PyPI - Downloads
67
+ .. image:: https://img.shields.io/github/stars/nicfit/eyeD3
68
+ :alt: GitHub Repo stars
74
69
 
75
70
 
76
71
  About
@@ -145,7 +140,7 @@ Features
145
140
  Get Started
146
141
  -----------
147
142
 
148
- Python >= 3.7 is required.
143
+ Python >= 3.9 is required.
149
144
 
150
145
  For `installation instructions`_ or more complete `documentation`_ see
151
146
  http://eyeD3.nicfit.net/
@@ -1,3 +1,4 @@
1
+ .readthedocs.yaml
1
2
  AUTHORS.rst
2
3
  CONTRIBUTING.rst
3
4
  HISTORY.rst
@@ -5,7 +6,6 @@ LICENSE
5
6
  MANIFEST.in
6
7
  Makefile
7
8
  README.rst
8
- pdm.lock
9
9
  pyproject.toml
10
10
  setup.py
11
11
  tox.ini
@@ -94,6 +94,9 @@ eyed3/utils/binfuncs.py
94
94
  eyed3/utils/console.py
95
95
  eyed3/utils/log.py
96
96
  eyed3/utils/prompt.py
97
+ requirements/dev-requirements.txt
98
+ requirements/plugin-requirements.txt
99
+ requirements/requirements.txt
97
100
  tests/__init__.py
98
101
  tests/conftest.py
99
102
  tests/pytest.ini
@@ -22,13 +22,13 @@ class Version:
22
22
 
23
23
 
24
24
  project_name = "eyeD3"
25
- version = "0.9.8a1"
25
+ version = "0.9.8a5"
26
26
  version_info = Version(
27
27
  0, 9, 8,
28
28
  None,
29
- ('a', 1),
29
+ ('a', 5),
30
30
  None,
31
- "Refuse/Resist",
31
+ "With Fear I Kiss the Burning Darkness",
32
32
  )
33
33
 
34
34
  author = "Travis Shirk"
@@ -268,14 +268,27 @@ class Date:
268
268
  "%Y-%m-%d %H:%M:%S",
269
269
  "%Y-00-00",
270
270
  "%Y%m%d",
271
+ # Special formats to support ID3v2.3 TDAT and TIME frames.
272
+ # See https://github.com/nicfit/eyeD3/pull/623 and frames.Date.date setter
273
+ "D%d-%m",
274
+ "T%H:%M",
271
275
  ]
272
276
  """Valid time stamp formats per ISO 8601 and used by `strptime`."""
273
277
 
274
- def __init__(self, year, month=None, day=None,
278
+ @classmethod
279
+ def __new__(cls, *args, **kwargs):
280
+ if ([arg for arg in args[1:] if arg is not None] or
281
+ [kwarg for kwarg in kwargs.values() if kwarg is not None]):
282
+ return super().__new__(cls)
283
+ else:
284
+ return
285
+
286
+ def __init__(self, year=None, month=None, day=None,
275
287
  hour=None, minute=None, second=None):
276
288
  # Validate with datetime
277
289
  from datetime import datetime
278
- _ = datetime(year, month if month is not None else 1,
290
+ _ = datetime(year if year is not None else 1899,
291
+ month if month is not None else 1,
279
292
  day if day is not None else 1,
280
293
  hour if hour is not None else 0,
281
294
  minute if minute is not None else 0,
@@ -383,6 +396,8 @@ class Date:
383
396
  # Here is the difference with Python date/datetime objects, some
384
397
  # of the members can be None
385
398
  kwargs = {}
399
+ if "%Y" in fmt:
400
+ kwargs["year"] = pdate.tm_year
386
401
  if "%m" in fmt:
387
402
  kwargs["month"] = pdate.tm_mon
388
403
  if "%d" in fmt:
@@ -394,23 +409,35 @@ class Date:
394
409
  if "%S" in fmt:
395
410
  kwargs["second"] = pdate.tm_sec
396
411
 
397
- return Date(pdate.tm_year, **kwargs)
412
+ return Date(**kwargs)
398
413
 
399
414
  def __str__(self):
400
415
  """Returns date strings that conform to ISO-8601.
401
416
  The returned string will be no larger than 17 characters."""
402
- s = "%d" % self.year
403
- if self.month:
404
- s += "-%s" % str(self.month).rjust(2, '0')
405
- if self.day:
406
- s += "-%s" % str(self.day).rjust(2, '0')
407
- if self.hour is not None:
408
- s += "T%s" % str(self.hour).rjust(2, '0')
409
- if self.minute is not None:
410
- s += ":%s" % str(self.minute).rjust(2, '0')
411
- if self.second is not None:
412
- s += ":%s" % str(self.second).rjust(2, '0')
413
- return s
417
+ s = "" # the string
418
+ c = "" # the separator character
419
+ if self.year is not None: # branch 1, aka "there is a year, maybe more"
420
+ s += "%d" % self.year
421
+ c = "-"
422
+ if self.month is not None: # there is a month
423
+ s += c + "%s" % str(self.month).rjust(2, '0')
424
+ if self.day is not None: # there is a day
425
+ s += c + "%s" % str(self.day).rjust(2, '0')
426
+ else: # branch 2, aka "we start without a year" aka "D%d-%m" format
427
+ c = "D"
428
+ if (self.day is not None) and (self.month is not None): # checking both
429
+ s += c + "%s" % str(self.day).rjust(2, '0')
430
+ c = "-"
431
+ s += c + "%s" % str(self.month).rjust(2, '0')
432
+ return s # We send a "Ddd-mm" string for 'TDAT'
433
+ # Here is the 'TIME' part, which starts or continues the string from branch 1
434
+ c = "T"
435
+ if self.hour is not None:
436
+ s += c + "%s" % str(self.hour).rjust(2, '0')
437
+ c = ":"
438
+ if self.minute is not None:
439
+ s += c + "%s" % str(self.minute).rjust(2, '0')
440
+ return s # We send either a YYYY-mm-ddTHH:MM, or just a THH:MM (for 'TIME')
414
441
 
415
442
 
416
443
  def parseError(ex) -> None:
@@ -130,11 +130,11 @@ class Genre:
130
130
  # valid id will set name
131
131
  if name and name != self.name:
132
132
  log.warning(f"Genre ID takes precedence and remapped '{name}' to '{self.name}'")
133
- except ValueError:
133
+ except ValueError as ex:
134
134
  log.warning(f"Invalid numeric genre ID: {id}")
135
135
  if not name:
136
136
  # Gave an invalid ID and no name to fallback on
137
- raise
137
+ raise GenreException from ex
138
138
  self.name = name
139
139
  self.id = None
140
140
  else:
@@ -10,6 +10,8 @@ TKWD_FID = b"TKWD"
10
10
  TDES_FID = b"TDES"
11
11
  TGID_FID = b"TGID"
12
12
  GRP1_FID = b"GRP1"
13
+ MVNM_FID = b"MVNM"
14
+ MVIN_FID = b"MVIN"
13
15
 
14
16
 
15
17
  class PCST(Frame):
@@ -56,3 +58,17 @@ class GRP1(TextFrame):
56
58
 
57
59
  def __init__(self, _=None, **kwargs):
58
60
  super().__init__(GRP1_FID, **kwargs)
61
+
62
+
63
+ class MVNM(TextFrame):
64
+ """Movement name. An Apple extension for classical music."""
65
+
66
+ def __init__(self, _=None, **kwargs):
67
+ super().__init__(MVNM_FID, **kwargs)
68
+
69
+
70
+ class MVIN(TextFrame):
71
+ """Movement index (e.g. "3/9"). An Apple extension for classical music."""
72
+
73
+ def __init__(self, _=None, **kwargs):
74
+ super().__init__(MVIN_FID, **kwargs)
@@ -319,7 +319,8 @@ class TextFrame(Frame):
319
319
  @staticmethod
320
320
  def isValidFrameId(fid: bytes) -> bool:
321
321
  return (fid[0:1] == b'T' or
322
- fid in [b"XSOA", b"XSOP", b"XSOT", b"XDOR", b"WFED", b"GRP1"])
322
+ fid in [b"XSOA", b"XSOP", b"XSOT", b"XDOR", b"WFED", b"GRP1",
323
+ b"MVNM", b"MVIN"])
323
324
 
324
325
 
325
326
  class UserTextFrame(TextFrame):
@@ -411,7 +412,11 @@ class DateFrame(TextFrame):
411
412
  self.text = ""
412
413
  return
413
414
 
414
- self.text = str(date)
415
+ str_date = str(date)
416
+ if ((DorT := str_date[0]) in ("D", "T")) and (len(str_date) <= 6): # maxlength 6
417
+ str_date = str_date.replace(DorT, "", 1)
418
+ str_date = str_date.replace("-" if DorT == "D" else ":", "")
419
+ self.text = str_date
415
420
 
416
421
  def _initEncoding(self):
417
422
  # Dates are always latin1 since they are always represented in ISO 8601
@@ -2258,4 +2263,8 @@ NONSTANDARD_ID3_FRAMES = {
2258
2263
  ID3_V2, TextFrame),
2259
2264
  b"GRP1": ("iTunes extension; grouping.",
2260
2265
  ID3_V2, apple.GRP1),
2266
+ b"MVNM": ("iTunes extension; movement name.",
2267
+ ID3_V2, apple.MVNM),
2268
+ b"MVIN": ("iTunes extension; movement index.",
2269
+ ID3_V2, apple.MVIN)
2261
2270
  }
@@ -556,11 +556,11 @@ class Tag(core.Tag):
556
556
  date = core.Date.parse(date)
557
557
  self._setDate(b"TYER", str(date.year))
558
558
  if None not in (date.month, date.day):
559
- date_str = "%s%s" % (str(date.day).rjust(2, "0"),
559
+ date_str = "D%s-%s" % (str(date.day).rjust(2, "0"),
560
560
  str(date.month).rjust(2, "0"))
561
561
  self._setDate(b"TDAT", date_str)
562
562
  if None not in (date.hour, date.minute):
563
- date_str = "%s%s" % (str(date.hour).rjust(2, "0"),
563
+ date_str = "T%s:%s" % (str(date.hour).rjust(2, "0"),
564
564
  str(date.minute).rjust(2, "0"))
565
565
  self._setDate(b"TIME", date_str)
566
566
 
@@ -9,32 +9,6 @@ from eyed3.utils.log import getLogger
9
9
 
10
10
  log = getLogger(__name__)
11
11
 
12
- # python-magic
13
- try:
14
- import magic
15
-
16
- class MagicTypes(magic.Magic):
17
- def __init__(self):
18
- magic.Magic.__init__(self, mime=True, mime_encoding=False, keep_going=True)
19
-
20
- def guess_type(self, filename, all_types=False):
21
- try:
22
- types = self.from_file(filename)
23
- except UnicodeEncodeError:
24
- # https://github.com/ahupp/python-magic/pull/144
25
- types = self.from_file(filename.encode("utf-8", 'surrogateescape'))
26
-
27
- delim = r"\012- "
28
- if all_types:
29
- return types.split(delim)
30
- else:
31
- return types.split(delim)[0]
32
-
33
- _python_magic = MagicTypes()
34
-
35
- except ImportError:
36
- _python_magic = None
37
-
38
12
 
39
13
  class MimetypesPlugin(eyed3.plugins.LoaderPlugin):
40
14
  NAMES = ["mimetypes"]
@@ -47,16 +21,12 @@ class MimetypesPlugin(eyed3.plugins.LoaderPlugin):
47
21
  g.add_argument("--status", action="store_true", help="Print dot status.")
48
22
  g.add_argument("--parse-files", action="store_true", help="Parse each file.")
49
23
  g.add_argument("--hide-notfound", action="store_true")
50
- if _python_magic:
51
- g.add_argument("-M", "--use-pymagic", action="store_true",
52
- help="Use python-magic to determine mimetype.")
53
- self.magic = None
24
+
54
25
  self.start_t = None
55
26
  self.mime_types = Counter()
56
27
 
57
28
  def start(self, args, config):
58
29
  super().start(args, config)
59
- self.magic = "pymagic" if self.args.use_pymagic else "filetype"
60
30
  self.start_t = time.time()
61
31
 
62
32
  def handleFile(self, f, *args, **kwargs):
@@ -70,11 +40,7 @@ class MimetypesPlugin(eyed3.plugins.LoaderPlugin):
70
40
  else:
71
41
  self._num_loaded += 1
72
42
 
73
- if self.magic == "pymagic":
74
- mtype = _python_magic.guess_type(f)
75
- else:
76
- mtype = guessMimetype(f)
77
-
43
+ mtype = guessMimetype(f)
78
44
  self.mime_types[mtype] += 1
79
45
  if not self.args.hide_notfound:
80
46
  if mtype is None and Path(f).suffix.lower() in (".mp3",):
@@ -87,7 +53,6 @@ class MimetypesPlugin(eyed3.plugins.LoaderPlugin):
87
53
  t = time.time() - self.start_t
88
54
  print(f"\nVisited {self._num_visited} files")
89
55
  print(f"Processed {self._num_loaded} files")
90
- print(f"magic: {self.magic}")
91
56
  print(f"time: {eyed3.utils.formatTime(t)} seconds")
92
57
  if self.mime_types:
93
58
  pprint.pprint(self.mime_types)
@@ -6,10 +6,10 @@ build-backend = "setuptools.build_meta"
6
6
 
7
7
  [tool.regarding]
8
8
  years = "2002-2025"
9
- release_name = "Refuse/Resist"
9
+ release_name = "With Fear I Kiss the Burning Darkness"
10
10
 
11
11
  [project]
12
- version = "0.9.8a1"
12
+ version = "0.9.8a5"
13
13
  name = "eyeD3"
14
14
  description = "Python audio data toolkit (ID3 and MP3)"
15
15
  readme = "README.rst"
@@ -77,6 +77,7 @@ dev = [
77
77
  "Paver>=1.3.4",
78
78
  "nicfit-py[cookiecutter]>=0.8.7",
79
79
  "regarding>=0.2.0",
80
+ #"git+https://github.com/nicfit/gitchangelog.git@nicfit.py",
80
81
  ]
81
82
 
82
83
  [tool.pdm]
@@ -84,7 +85,3 @@ distribution = true
84
85
 
85
86
  [tool.coverage.html]
86
87
  directory = "build/tests/coverage"
87
-
88
- ######### OLD #################
89
- # FIXME: https://github.com/nicfit/eyeD3/issues/615
90
- #gitchangelog = {git = "https://github.com/nicfit/gitchangelog.git", rev = "nicfit.py"}