puremagic 2.0.0b4__tar.gz → 2.0.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 (140) hide show
  1. {puremagic-2.0.0b4 → puremagic-2.0.2}/.coveragerc +1 -1
  2. {puremagic-2.0.0b4 → puremagic-2.0.2}/.github/workflows/pythonpublish.yml +1 -1
  3. {puremagic-2.0.0b4 → puremagic-2.0.2}/.github/workflows/tests.yml +6 -3
  4. {puremagic-2.0.0b4 → puremagic-2.0.2}/.gitignore +6 -4
  5. {puremagic-2.0.0b4 → puremagic-2.0.2}/.pre-commit-config.yaml +11 -7
  6. {puremagic-2.0.0b4 → puremagic-2.0.2}/CHANGELOG.md +13 -1
  7. {puremagic-2.0.0b4 → puremagic-2.0.2}/PKG-INFO +67 -33
  8. {puremagic-2.0.0b4 → puremagic-2.0.2}/README.rst +65 -32
  9. {puremagic-2.0.0b4 → puremagic-2.0.2}/puremagic/magic_data.json +424 -247
  10. {puremagic-2.0.0b4 → puremagic-2.0.2}/puremagic/main.py +139 -134
  11. puremagic-2.0.2/puremagic/scanners/hdf5_scanner.py +61 -0
  12. {puremagic-2.0.0b4 → puremagic-2.0.2}/puremagic/scanners/json_scanner.py +3 -1
  13. puremagic-2.0.2/puremagic/scanners/mpeg_audio_scanner.py +1178 -0
  14. puremagic-2.0.2/puremagic/scanners/python_scanner.py +65 -0
  15. puremagic-2.0.2/puremagic/scanners/sndhdr_scanner.py +46 -0
  16. puremagic-2.0.2/puremagic/scanners/text_scanner.py +226 -0
  17. {puremagic-2.0.0b4 → puremagic-2.0.2}/puremagic.egg-info/PKG-INFO +67 -33
  18. {puremagic-2.0.0b4 → puremagic-2.0.2}/puremagic.egg-info/SOURCES.txt +23 -1
  19. {puremagic-2.0.0b4 → puremagic-2.0.2}/pyproject.toml +29 -29
  20. {puremagic-2.0.0b4 → puremagic-2.0.2}/scripts/parse_ftk_kessler_sigs.py +2 -2
  21. puremagic-2.0.2/test/resources/audio/test.flac +0 -0
  22. puremagic-2.0.2/test/resources/audio/test.opus +0 -0
  23. puremagic-2.0.2/test/resources/audio/test.sndr +0 -0
  24. puremagic-2.0.2/test/resources/audio/test_mp3_vbr_info_128k_notags.mp3 +0 -0
  25. puremagic-2.0.2/test/resources/audio/test_mp3_vbr_xing_128k_3di_id3v1.mp3 +0 -0
  26. puremagic-2.0.2/test/resources/audio/test_mp3_vbr_xing_128k_apev1.mp3 +0 -0
  27. puremagic-2.0.2/test/resources/audio/test_mp3_vbr_xing_128k_apev1_id3v1.mp3 +0 -0
  28. puremagic-2.0.2/test/resources/audio/test_mp3_vbr_xing_128k_apev2_tagplus_id3v1.mp3 +0 -0
  29. puremagic-2.0.2/test/resources/audio/test_mp3_vbr_xing_128k_ext_id3v1.mp3 +0 -0
  30. puremagic-2.0.2/test/resources/audio/test_mp3_vbr_xing_128k_lyrics3v2_id3v1.mp3 +0 -0
  31. puremagic-2.0.2/test/resources/audio/test_mp3_vbr_xing_128k_notags.mp3 +0 -0
  32. puremagic-2.0.2/test/resources/audio/test_mp3_vbr_xing_128k_tagplus_apev2_id3v1.mp3 +0 -0
  33. puremagic-2.0.2/test/resources/audio/test_mp3_vbr_xing_128k_tagplus_id3v1.mp3 +0 -0
  34. puremagic-2.0.2/test/resources/audio/test_mpeg2_mp3_VBR_128k_id3v2_24.mp3 +0 -0
  35. puremagic-2.0.2/test/resources/office/test.eml +9 -0
  36. puremagic-2.0.2/test/resources/office/test_utf16le.csv +0 -0
  37. puremagic-2.0.2/test/resources/office/text_cr.txt +1 -0
  38. puremagic-2.0.2/test/resources/office/text_crlf.txt +6 -0
  39. puremagic-2.0.2/test/resources/office/text_lf.txt +6 -0
  40. puremagic-2.0.2/test/resources/system/test_list.json +1 -0
  41. {puremagic-2.0.0b4 → puremagic-2.0.2}/test/test_common_extensions.py +3 -2
  42. puremagic-2.0.2/test/test_scanners.py +118 -0
  43. puremagic-2.0.2/uv.lock +816 -0
  44. puremagic-2.0.0b4/puremagic/scanners/python_scanner.py +0 -25
  45. puremagic-2.0.0b4/puremagic/scanners/text_scanner.py +0 -32
  46. puremagic-2.0.0b4/test/test_main.py +0 -158
  47. puremagic-2.0.0b4/test/test_scanners.py +0 -61
  48. puremagic-2.0.0b4/uv.lock +0 -698
  49. {puremagic-2.0.0b4 → puremagic-2.0.2}/AUTHORS.rst +0 -0
  50. {puremagic-2.0.0b4 → puremagic-2.0.2}/LICENSE +0 -0
  51. {puremagic-2.0.0b4 → puremagic-2.0.2}/MANIFEST.in +0 -0
  52. {puremagic-2.0.0b4 → puremagic-2.0.2}/puremagic/__init__.py +0 -0
  53. {puremagic-2.0.0b4 → puremagic-2.0.2}/puremagic/__main__.py +0 -0
  54. {puremagic-2.0.0b4 → puremagic-2.0.2}/puremagic/py.typed +0 -0
  55. {puremagic-2.0.0b4 → puremagic-2.0.2}/puremagic/scanners/__init__.py +0 -0
  56. {puremagic-2.0.0b4 → puremagic-2.0.2}/puremagic/scanners/helpers.py +0 -0
  57. {puremagic-2.0.0b4 → puremagic-2.0.2}/puremagic/scanners/pdf_scanner.py +0 -0
  58. {puremagic-2.0.0b4 → puremagic-2.0.2}/puremagic/scanners/zip_scanner.py +0 -0
  59. {puremagic-2.0.0b4 → puremagic-2.0.2}/puremagic.egg-info/dependency_links.txt +0 -0
  60. {puremagic-2.0.0b4 → puremagic-2.0.2}/puremagic.egg-info/entry_points.txt +0 -0
  61. {puremagic-2.0.0b4 → puremagic-2.0.2}/puremagic.egg-info/top_level.txt +0 -0
  62. {puremagic-2.0.0b4 → puremagic-2.0.2}/requirements-test.txt +0 -0
  63. {puremagic-2.0.0b4 → puremagic-2.0.2}/setup.cfg +0 -0
  64. {puremagic-2.0.0b4 → puremagic-2.0.2}/test/__init__.py +0 -0
  65. {puremagic-2.0.0b4 → puremagic-2.0.2}/test/common.py +0 -0
  66. {puremagic-2.0.0b4 → puremagic-2.0.2}/test/resources/archive/test.7z +0 -0
  67. {puremagic-2.0.0b4 → puremagic-2.0.2}/test/resources/archive/test.big_endian.pcapng +0 -0
  68. {puremagic-2.0.0b4 → puremagic-2.0.2}/test/resources/archive/test.bz2 +0 -0
  69. {puremagic-2.0.0b4 → puremagic-2.0.2}/test/resources/archive/test.cb7 +0 -0
  70. {puremagic-2.0.0b4 → puremagic-2.0.2}/test/resources/archive/test.cbt +0 -0
  71. {puremagic-2.0.0b4 → puremagic-2.0.2}/test/resources/archive/test.cbz +0 -0
  72. {puremagic-2.0.0b4 → puremagic-2.0.2}/test/resources/archive/test.fb2.zip +0 -0
  73. {puremagic-2.0.0b4 → puremagic-2.0.2}/test/resources/archive/test.fbz +0 -0
  74. {puremagic-2.0.0b4 → puremagic-2.0.2}/test/resources/archive/test.gz +0 -0
  75. {puremagic-2.0.0b4 → puremagic-2.0.2}/test/resources/archive/test.little_endian.pcapng +0 -0
  76. {puremagic-2.0.0b4 → puremagic-2.0.2}/test/resources/archive/test.pcapng +0 -0
  77. {puremagic-2.0.0b4 → puremagic-2.0.2}/test/resources/archive/test.rar +0 -0
  78. {puremagic-2.0.0b4 → puremagic-2.0.2}/test/resources/archive/test.tar +0 -0
  79. {puremagic-2.0.0b4 → puremagic-2.0.2}/test/resources/archive/test.txt.lz4 +0 -0
  80. {puremagic-2.0.0b4 → puremagic-2.0.2}/test/resources/archive/test.txt.zst +0 -0
  81. {puremagic-2.0.0b4 → puremagic-2.0.2}/test/resources/archive/test.xz +0 -0
  82. {puremagic-2.0.0b4 → puremagic-2.0.2}/test/resources/archive/test.zip +0 -0
  83. {puremagic-2.0.0b4 → puremagic-2.0.2}/test/resources/audio/test.aac +0 -0
  84. {puremagic-2.0.0b4 → puremagic-2.0.2}/test/resources/audio/test.aif +0 -0
  85. {puremagic-2.0.0b4 → puremagic-2.0.2}/test/resources/audio/test.mp3 +0 -0
  86. {puremagic-2.0.0b4 → puremagic-2.0.2}/test/resources/audio/test.wav +0 -0
  87. {puremagic-2.0.0b4 → puremagic-2.0.2}/test/resources/fake_file +0 -0
  88. {puremagic-2.0.0b4 → puremagic-2.0.2}/test/resources/images/test.avif +0 -0
  89. {puremagic-2.0.0b4 → puremagic-2.0.2}/test/resources/images/test.bmp +0 -0
  90. {puremagic-2.0.0b4 → puremagic-2.0.2}/test/resources/images/test.gif +0 -0
  91. {puremagic-2.0.0b4 → puremagic-2.0.2}/test/resources/images/test.ico +0 -0
  92. {puremagic-2.0.0b4 → puremagic-2.0.2}/test/resources/images/test.jpg +0 -0
  93. {puremagic-2.0.0b4 → puremagic-2.0.2}/test/resources/images/test.png +0 -0
  94. {puremagic-2.0.0b4 → puremagic-2.0.2}/test/resources/images/test.psd +0 -0
  95. {puremagic-2.0.0b4 → puremagic-2.0.2}/test/resources/images/test.svg +0 -0
  96. {puremagic-2.0.0b4 → puremagic-2.0.2}/test/resources/images/test.tga +0 -0
  97. {puremagic-2.0.0b4 → puremagic-2.0.2}/test/resources/images/test.tif +0 -0
  98. {puremagic-2.0.0b4 → puremagic-2.0.2}/test/resources/images/test.webp +0 -0
  99. {puremagic-2.0.0b4 → puremagic-2.0.2}/test/resources/images/test.xcf +0 -0
  100. {puremagic-2.0.0b4 → puremagic-2.0.2}/test/resources/images/test_varriant.svg +0 -0
  101. {puremagic-2.0.0b4 → puremagic-2.0.2}/test/resources/images/test_varriant_2.svg +0 -0
  102. {puremagic-2.0.0b4 → puremagic-2.0.2}/test/resources/media/test (single).vmdk +0 -0
  103. {puremagic-2.0.0b4 → puremagic-2.0.2}/test/resources/media/test (split).vmdk +0 -0
  104. {puremagic-2.0.0b4 → puremagic-2.0.2}/test/resources/media/test.iso +0 -0
  105. {puremagic-2.0.0b4 → puremagic-2.0.2}/test/resources/media/test.mdf +0 -0
  106. {puremagic-2.0.0b4 → puremagic-2.0.2}/test/resources/media/test.swf +0 -0
  107. {puremagic-2.0.0b4 → puremagic-2.0.2}/test/resources/office/test.doc +0 -0
  108. {puremagic-2.0.0b4 → puremagic-2.0.2}/test/resources/office/test.docm +0 -0
  109. {puremagic-2.0.0b4 → puremagic-2.0.2}/test/resources/office/test.docx +0 -0
  110. {puremagic-2.0.0b4 → puremagic-2.0.2}/test/resources/office/test.dotm +0 -0
  111. {puremagic-2.0.0b4 → puremagic-2.0.2}/test/resources/office/test.dotx +0 -0
  112. {puremagic-2.0.0b4 → puremagic-2.0.2}/test/resources/office/test.fb2 +0 -0
  113. {puremagic-2.0.0b4 → puremagic-2.0.2}/test/resources/office/test.odp +0 -0
  114. {puremagic-2.0.0b4 → puremagic-2.0.2}/test/resources/office/test.ods +0 -0
  115. {puremagic-2.0.0b4 → puremagic-2.0.2}/test/resources/office/test.odt +0 -0
  116. {puremagic-2.0.0b4 → puremagic-2.0.2}/test/resources/office/test.pdf +0 -0
  117. {puremagic-2.0.0b4 → puremagic-2.0.2}/test/resources/office/test.potm +0 -0
  118. {puremagic-2.0.0b4 → puremagic-2.0.2}/test/resources/office/test.potx +0 -0
  119. {puremagic-2.0.0b4 → puremagic-2.0.2}/test/resources/office/test.ppt +0 -0
  120. {puremagic-2.0.0b4 → puremagic-2.0.2}/test/resources/office/test.pptm +0 -0
  121. {puremagic-2.0.0b4 → puremagic-2.0.2}/test/resources/office/test.pptx +0 -0
  122. {puremagic-2.0.0b4 → puremagic-2.0.2}/test/resources/office/test.txt +0 -0
  123. {puremagic-2.0.0b4 → puremagic-2.0.2}/test/resources/office/test.xls +0 -0
  124. {puremagic-2.0.0b4 → puremagic-2.0.2}/test/resources/office/test.xlsb +0 -0
  125. {puremagic-2.0.0b4 → puremagic-2.0.2}/test/resources/office/test.xlsm +0 -0
  126. {puremagic-2.0.0b4 → puremagic-2.0.2}/test/resources/office/test.xlsx +0 -0
  127. {puremagic-2.0.0b4 → puremagic-2.0.2}/test/resources/office/test.xltm +0 -0
  128. {puremagic-2.0.0b4 → puremagic-2.0.2}/test/resources/office/test.xltx +0 -0
  129. {puremagic-2.0.0b4 → puremagic-2.0.2}/test/resources/system/test.exe +0 -0
  130. {puremagic-2.0.0b4 → puremagic-2.0.2}/test/resources/system/test.json +0 -0
  131. {puremagic-2.0.0b4 → puremagic-2.0.2}/test/resources/system/test.puremagic_multi_footer +0 -0
  132. {puremagic-2.0.0b4 → puremagic-2.0.2}/test/resources/system/test.py +0 -0
  133. {puremagic-2.0.0b4 → puremagic-2.0.2}/test/resources/video/test.3g2 +0 -0
  134. {puremagic-2.0.0b4 → puremagic-2.0.2}/test/resources/video/test.avi +0 -0
  135. {puremagic-2.0.0b4 → puremagic-2.0.2}/test/resources/video/test.flv +0 -0
  136. {puremagic-2.0.0b4 → puremagic-2.0.2}/test/resources/video/test.jxsv +0 -0
  137. {puremagic-2.0.0b4 → puremagic-2.0.2}/test/resources/video/test.mkv +0 -0
  138. {puremagic-2.0.0b4 → puremagic-2.0.2}/test/resources/video/test.mp4 +0 -0
  139. {puremagic-2.0.0b4 → puremagic-2.0.2}/test/resources/video/test.mpg +0 -0
  140. {puremagic-2.0.0b4 → puremagic-2.0.2}/test/resources/video/test.wmv +0 -0
@@ -7,7 +7,7 @@ omit =
7
7
  */venv/*
8
8
  */.*/*
9
9
  */*.egg-info/*
10
- */.mypy_cache/*
10
+ */.ty/*
11
11
  */.pytest_cache/*
12
12
  exclude_lines =
13
13
  command_line_entry
@@ -18,7 +18,7 @@ jobs:
18
18
  - name: Set up Python
19
19
  uses: actions/setup-python@v5
20
20
  with:
21
- python-version: '3.12'
21
+ python-version: '3.14'
22
22
 
23
23
  - name: Install the latest version of uv and activate the environment
24
24
  uses: astral-sh/setup-uv@v6
@@ -16,12 +16,12 @@ jobs:
16
16
  fail-fast: false
17
17
  matrix:
18
18
  os: [ubuntu-latest]
19
- python-version: ["3.12", "3.13", "3.14-dev"]
19
+ python-version: ["3.12", "3.13", "3.14"]
20
20
  include:
21
21
  - os: macos-latest
22
- python-version: '3.13'
22
+ python-version: '3.14'
23
23
  - os: windows-latest
24
- python-version: '3.13'
24
+ python-version: '3.14'
25
25
  runs-on: ${{ matrix.os }}
26
26
  steps:
27
27
  - uses: actions/checkout@v4
@@ -41,6 +41,9 @@ jobs:
41
41
  - name: Verify Code with Ruff
42
42
  run: uv run ruff check
43
43
 
44
+ - name: Type check with ty
45
+ run: uv run ty check
46
+
44
47
  - name: Test with pytest
45
48
  run: uv run pytest --cov=puremagic test/
46
49
 
@@ -124,10 +124,8 @@ venv.bak/
124
124
  # mkdocs documentation
125
125
  /site
126
126
 
127
- # mypy
128
- .mypy_cache/
129
- .dmypy.json
130
- dmypy.json
127
+ # ty
128
+ .ty/
131
129
 
132
130
  # Pyre type checker
133
131
  .pyre/
@@ -143,3 +141,7 @@ media
143
141
  static
144
142
 
145
143
  .idea/
144
+
145
+ # Ignore VS Code related files and folders
146
+ .vscode
147
+ *.code-workspace
@@ -1,6 +1,6 @@
1
1
  repos:
2
2
  - repo: https://github.com/pre-commit/pre-commit-hooks
3
- rev: v5.0.0
3
+ rev: v6.0.0
4
4
  hooks:
5
5
  # Identify invalid files
6
6
  - id: check-ast
@@ -35,7 +35,7 @@ repos:
35
35
 
36
36
  - repo: https://github.com/astral-sh/ruff-pre-commit
37
37
  # Ruff version.
38
- rev: v0.12.2
38
+ rev: v0.15.5
39
39
  hooks:
40
40
  # Run the linter.
41
41
  - id: ruff-check
@@ -43,17 +43,21 @@ repos:
43
43
  # Run the formatter.
44
44
  - id: ruff-format
45
45
 
46
- - repo: https://github.com/pre-commit/mirrors-mypy
47
- rev: 'v1.16.1'
46
+ - repo: local
48
47
  hooks:
49
- - id: mypy
48
+ - id: ty
49
+ name: ty
50
+ entry: uv run ty check
51
+ language: system
52
+ types: [python]
53
+ pass_filenames: false
50
54
 
51
55
  - repo: https://github.com/tox-dev/pyproject-fmt
52
- rev: v2.6.0
56
+ rev: v2.16.2
53
57
  hooks:
54
58
  - id: pyproject-fmt
55
59
 
56
60
  - repo: https://github.com/abravalheri/validate-pyproject
57
- rev: v0.24.1
61
+ rev: v0.25
58
62
  hooks:
59
63
  - id: validate-pyproject
@@ -1,10 +1,22 @@
1
1
  Changelog
2
2
  =========
3
3
 
4
+ Version 2.0.2
5
+ -------------
6
+
7
+ - Fixing #137 passing non-existent filename to from_string()/from_stream() no longer raises FileNotFoundError (thanks to denisw)
8
+
9
+ Version 2.0.1
10
+ -------------
11
+
12
+ - Fixing #126 Python scanner false positives — now uses AST node walking instead of regex to verify real Python constructs (thanks to ahobson)
13
+ - Fixing #134 UTF-16 LE BOM (FF FE) no longer misidentified as .mp1 audio, added UTF-16 BOM detection to text scanner (thanks to tomazfs)
14
+ - Fixing #135 from_string(), from_stream(), magic_string(), and magic_stream() now perform deep scan when filename is provided (thanks to denisw)
15
+
4
16
  Version 2.0.0
5
17
  -------------
6
18
 
7
- - Adding deep scan for improved accuracy #102 #94 #70 #69 #12 #3
19
+ - Adding deep scan for improved accuracy #102 #94 #85 #70 #69 #12 #3
8
20
  - Changing to full semantic versioning to be able to denote bugfixes vs minor features
9
21
  - Changing to use uv instead of requirements
10
22
  - Removing support for python 3.7, 3.8, 3.9, 3.10 and 3.11 please stick to 1.x release chain to support older versions
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: puremagic
3
- Version: 2.0.0b4
3
+ Version: 2.0.2
4
4
  Summary: Pure python implementation of magic file detection
5
5
  Author-email: Chris Griffith <chris@cdgriffith.com>
6
6
  License-Expression: MIT
@@ -13,6 +13,7 @@ Classifier: Programming Language :: Python
13
13
  Classifier: Programming Language :: Python :: 3 :: Only
14
14
  Classifier: Programming Language :: Python :: 3.12
15
15
  Classifier: Programming Language :: Python :: 3.13
16
+ Classifier: Programming Language :: Python :: 3.14
16
17
  Classifier: Programming Language :: Python :: Implementation :: PyPy
17
18
  Classifier: Topic :: Utilities
18
19
  Requires-Python: >=3.12
@@ -25,18 +26,22 @@ puremagic
25
26
  =========
26
27
 
27
28
  puremagic is a pure python module that will identify a file based off
28
- it's magic numbers.
29
+ its magic numbers. It has zero runtime dependencies and serves as a
30
+ lightweight, cross-platform alternative to python-magic/libmagic.
29
31
 
30
32
  It is designed to be minimalistic and inherently cross platform
31
- compatible. It is also designed to be a stand in for python-magic, it
32
- incorporates the functions from\_file(filename[, mime]) and
33
- from\_string(string[, mime]) however the magic\_file() and
34
- magic\_string() are more powerful and will also display confidence and
33
+ compatible. It is also designed to be a stand in for python-magic. It
34
+ implements the functions :code:`from_file(filename[, mime])` and
35
+ :code:`from_string(string[, mime])` however the :code:`magic_file()` and
36
+ :code:`magic_string()` are more powerful and will also display confidence and
35
37
  duplicate matches.
36
38
 
37
- It does NOT try to match files off non-magic string. In other words it
38
- will not search for a string within a certain window of bytes like
39
- others might.
39
+ Starting with version 2.0, puremagic includes a **deep scan** system
40
+ that performs content-aware analysis beyond simple magic number matching.
41
+ This improves accuracy for formats like Office documents, text files,
42
+ CSV, MP3, Python source, JSON, HDF5, email, and many scientific formats.
43
+ Deep scan is enabled by default and can be disabled by setting the
44
+ environment variable :code:`PUREMAGIC_DEEPSCAN=0`.
40
45
 
41
46
  Advantages over using a wrapper for 'file' or 'libmagic':
42
47
 
@@ -58,11 +63,11 @@ Compatibility
58
63
 
59
64
  - Python 3.12+
60
65
 
61
- For use with with 3.7 use the 1.x branch.
66
+ For use with Python 3.7–3.11, use the 1.x release chain.
62
67
 
63
68
  Using github ci to run continuous integration tests on listed platforms.
64
69
 
65
- Install from pypy
70
+ Install from PyPI
66
71
  -----------------
67
72
 
68
73
  .. code:: bash
@@ -75,16 +80,6 @@ On linux environments, you may want to be clear you are using python3
75
80
 
76
81
  $ python3 -m pip install puremagic
77
82
 
78
-
79
- Install from source
80
- -------------------
81
-
82
- In either a virtualenv or globally, simply run:
83
-
84
- .. code:: bash
85
-
86
- $ python setup.py install
87
-
88
83
  Usage
89
84
  -----
90
85
 
@@ -128,6 +123,35 @@ If you already have a file open, or raw byte string, you could also use:
128
123
  # [PureMagicWithConfidence(byte_match=b'ftypisom', offset=4, extension='.mp4', mime_type='video/mp4', name='MPEG-4 video', confidence=0.8),
129
124
  # PureMagicWithConfidence(byte_match=b'iso2avc1mp4', offset=20, extension='.mp4', mime_type='video/mp4', name='MP4 Video', confidence=0.8)]
130
125
 
126
+ Deep Scan
127
+ ---------
128
+
129
+ Deep scan performs content-aware analysis when magic number matching
130
+ alone is not enough. It is enabled by default and runs automatically
131
+ as part of the normal identification pipeline.
132
+
133
+ The following format-specific scanners are included:
134
+
135
+ - **ZIP** — Distinguishes Office formats (xlsx/docx/pptx), OpenDocument
136
+ (odt/ods/odp), and their macro-enabled variants by inspecting ZIP internals
137
+ - **MPEG Audio** — Parses MP3/MPEG audio frames to validate and identify audio files
138
+ - **Text** — Detects text encodings, line endings (CRLF/LF/CR), CSV files
139
+ with automatic delimiter detection, and email messages (.eml)
140
+ - **Python** — Validates Python source via :code:`ast.parse()` and keyword analysis
141
+ - **PDF** — Format-specific PDF validation
142
+ - **JSON** — JSON format validation
143
+ - **HDF5** — Identifies HDF5 subtypes used in scientific computing (AnnData,
144
+ Loom, Cooler, BIOM v2, mz5, and more)
145
+ - **Audio** — Identifies HCOM and SNDR audio formats
146
+ - **Dynamic text checks** — Recognizes many scientific and bioinformatics text
147
+ formats including VCF, SAM, GFF, PLY, VTK, and others
148
+
149
+ To disable deep scan, set the environment variable:
150
+
151
+ .. code:: bash
152
+
153
+ $ export PUREMAGIC_DEEPSCAN=0
154
+
131
155
  Script
132
156
  ------
133
157
 
@@ -137,6 +161,14 @@ Script
137
161
 
138
162
  $ python -m puremagic [options] filename <filename2>...
139
163
 
164
+ *Options*
165
+
166
+ - :code:`-m, --mime` — Return the MIME type instead of file extension
167
+ - :code:`-v, --verbose` — Print verbose output with all possible matches
168
+ - :code:`--version` — Show program version
169
+
170
+ Directories can be passed as arguments; all files within will be scanned.
171
+
140
172
  *Examples*
141
173
 
142
174
  .. code:: bash
@@ -148,19 +180,21 @@ Script
148
180
  'test/resources/images/test.gif' : image/gif
149
181
  'test/resources/audio/test.mp3' : audio/mpeg
150
182
 
151
- imghdr replacement
152
- ------------------
153
-
154
- If you are looking for a replacement for the standard library's depreciated imghdr, you can use `puremagic.what()`
155
-
156
- .. code:: python
157
-
158
- import puremagic
183
+ Upgrading from 1.x
184
+ -------------------
159
185
 
160
- filename = "test/resources/images/test.gif"
186
+ Version 2.0 includes the following breaking changes:
161
187
 
162
- ext = puremagic.what(filename)
163
- # 'gif'
188
+ - **Python 3.12+ required** — Python 3.7–3.11 are no longer supported.
189
+ Use the 1.x release chain for older Python versions.
190
+ - **Removed** :code:`puremagic.what()` — The :code:`imghdr` drop-in replacement
191
+ has been removed. Use :code:`puremagic.from_file()` instead.
192
+ - **Removed** :code:`magic_header_array`, :code:`magic_footer_array`, and
193
+ :code:`multi_part_dict` from the public API.
194
+ - **Removed** :code:`setup.py` — The project now uses :code:`pyproject.toml`
195
+ exclusively.
196
+ - Internal functions have been renamed from private (e.g. :code:`_magic_data`)
197
+ to public (e.g. :code:`magic_data`).
164
198
 
165
199
  FAQ
166
200
  ---
@@ -190,4 +224,4 @@ https://cgit.freedesktop.org/xdg/shared-mime-info/
190
224
  License
191
225
  -------
192
226
 
193
- MIT Licenced, see LICENSE, Copyright (c) 2013-2025 Chris Griffith
227
+ MIT Licenced, see LICENSE, Copyright (c) 2013-2026 Chris Griffith
@@ -3,18 +3,22 @@ puremagic
3
3
  =========
4
4
 
5
5
  puremagic is a pure python module that will identify a file based off
6
- it's magic numbers.
6
+ its magic numbers. It has zero runtime dependencies and serves as a
7
+ lightweight, cross-platform alternative to python-magic/libmagic.
7
8
 
8
9
  It is designed to be minimalistic and inherently cross platform
9
- compatible. It is also designed to be a stand in for python-magic, it
10
- incorporates the functions from\_file(filename[, mime]) and
11
- from\_string(string[, mime]) however the magic\_file() and
12
- magic\_string() are more powerful and will also display confidence and
10
+ compatible. It is also designed to be a stand in for python-magic. It
11
+ implements the functions :code:`from_file(filename[, mime])` and
12
+ :code:`from_string(string[, mime])` however the :code:`magic_file()` and
13
+ :code:`magic_string()` are more powerful and will also display confidence and
13
14
  duplicate matches.
14
15
 
15
- It does NOT try to match files off non-magic string. In other words it
16
- will not search for a string within a certain window of bytes like
17
- others might.
16
+ Starting with version 2.0, puremagic includes a **deep scan** system
17
+ that performs content-aware analysis beyond simple magic number matching.
18
+ This improves accuracy for formats like Office documents, text files,
19
+ CSV, MP3, Python source, JSON, HDF5, email, and many scientific formats.
20
+ Deep scan is enabled by default and can be disabled by setting the
21
+ environment variable :code:`PUREMAGIC_DEEPSCAN=0`.
18
22
 
19
23
  Advantages over using a wrapper for 'file' or 'libmagic':
20
24
 
@@ -36,11 +40,11 @@ Compatibility
36
40
 
37
41
  - Python 3.12+
38
42
 
39
- For use with with 3.7 use the 1.x branch.
43
+ For use with Python 3.7–3.11, use the 1.x release chain.
40
44
 
41
45
  Using github ci to run continuous integration tests on listed platforms.
42
46
 
43
- Install from pypy
47
+ Install from PyPI
44
48
  -----------------
45
49
 
46
50
  .. code:: bash
@@ -53,16 +57,6 @@ On linux environments, you may want to be clear you are using python3
53
57
 
54
58
  $ python3 -m pip install puremagic
55
59
 
56
-
57
- Install from source
58
- -------------------
59
-
60
- In either a virtualenv or globally, simply run:
61
-
62
- .. code:: bash
63
-
64
- $ python setup.py install
65
-
66
60
  Usage
67
61
  -----
68
62
 
@@ -106,6 +100,35 @@ If you already have a file open, or raw byte string, you could also use:
106
100
  # [PureMagicWithConfidence(byte_match=b'ftypisom', offset=4, extension='.mp4', mime_type='video/mp4', name='MPEG-4 video', confidence=0.8),
107
101
  # PureMagicWithConfidence(byte_match=b'iso2avc1mp4', offset=20, extension='.mp4', mime_type='video/mp4', name='MP4 Video', confidence=0.8)]
108
102
 
103
+ Deep Scan
104
+ ---------
105
+
106
+ Deep scan performs content-aware analysis when magic number matching
107
+ alone is not enough. It is enabled by default and runs automatically
108
+ as part of the normal identification pipeline.
109
+
110
+ The following format-specific scanners are included:
111
+
112
+ - **ZIP** — Distinguishes Office formats (xlsx/docx/pptx), OpenDocument
113
+ (odt/ods/odp), and their macro-enabled variants by inspecting ZIP internals
114
+ - **MPEG Audio** — Parses MP3/MPEG audio frames to validate and identify audio files
115
+ - **Text** — Detects text encodings, line endings (CRLF/LF/CR), CSV files
116
+ with automatic delimiter detection, and email messages (.eml)
117
+ - **Python** — Validates Python source via :code:`ast.parse()` and keyword analysis
118
+ - **PDF** — Format-specific PDF validation
119
+ - **JSON** — JSON format validation
120
+ - **HDF5** — Identifies HDF5 subtypes used in scientific computing (AnnData,
121
+ Loom, Cooler, BIOM v2, mz5, and more)
122
+ - **Audio** — Identifies HCOM and SNDR audio formats
123
+ - **Dynamic text checks** — Recognizes many scientific and bioinformatics text
124
+ formats including VCF, SAM, GFF, PLY, VTK, and others
125
+
126
+ To disable deep scan, set the environment variable:
127
+
128
+ .. code:: bash
129
+
130
+ $ export PUREMAGIC_DEEPSCAN=0
131
+
109
132
  Script
110
133
  ------
111
134
 
@@ -115,6 +138,14 @@ Script
115
138
 
116
139
  $ python -m puremagic [options] filename <filename2>...
117
140
 
141
+ *Options*
142
+
143
+ - :code:`-m, --mime` — Return the MIME type instead of file extension
144
+ - :code:`-v, --verbose` — Print verbose output with all possible matches
145
+ - :code:`--version` — Show program version
146
+
147
+ Directories can be passed as arguments; all files within will be scanned.
148
+
118
149
  *Examples*
119
150
 
120
151
  .. code:: bash
@@ -126,19 +157,21 @@ Script
126
157
  'test/resources/images/test.gif' : image/gif
127
158
  'test/resources/audio/test.mp3' : audio/mpeg
128
159
 
129
- imghdr replacement
130
- ------------------
131
-
132
- If you are looking for a replacement for the standard library's depreciated imghdr, you can use `puremagic.what()`
133
-
134
- .. code:: python
135
-
136
- import puremagic
160
+ Upgrading from 1.x
161
+ -------------------
137
162
 
138
- filename = "test/resources/images/test.gif"
163
+ Version 2.0 includes the following breaking changes:
139
164
 
140
- ext = puremagic.what(filename)
141
- # 'gif'
165
+ - **Python 3.12+ required** — Python 3.7–3.11 are no longer supported.
166
+ Use the 1.x release chain for older Python versions.
167
+ - **Removed** :code:`puremagic.what()` — The :code:`imghdr` drop-in replacement
168
+ has been removed. Use :code:`puremagic.from_file()` instead.
169
+ - **Removed** :code:`magic_header_array`, :code:`magic_footer_array`, and
170
+ :code:`multi_part_dict` from the public API.
171
+ - **Removed** :code:`setup.py` — The project now uses :code:`pyproject.toml`
172
+ exclusively.
173
+ - Internal functions have been renamed from private (e.g. :code:`_magic_data`)
174
+ to public (e.g. :code:`magic_data`).
142
175
 
143
176
  FAQ
144
177
  ---
@@ -168,4 +201,4 @@ https://cgit.freedesktop.org/xdg/shared-mime-info/
168
201
  License
169
202
  -------
170
203
 
171
- MIT Licenced, see LICENSE, Copyright (c) 2013-2025 Chris Griffith
204
+ MIT Licenced, see LICENSE, Copyright (c) 2013-2026 Chris Griffith