Skip to content

Commit 7e15d13

Browse files
committed
Initial commit - python-magic-bin
0 parents  commit 7e15d13

46 files changed

Lines changed: 2331 additions & 0 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.dockerignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
.gitignore

.github/dependabot.yml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
version: 2
2+
updates:
3+
- package-ecosystem: "github-actions"
4+
directory: "/"
5+
schedule:
6+
interval: "monthly"
7+
groups:
8+
github-actions:
9+
patterns:
10+
- "*"

.github/workflows/ci.yml

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
name: ci
2+
on: [push, pull_request]
3+
jobs:
4+
ci:
5+
strategy:
6+
fail-fast: false
7+
matrix:
8+
os: ["ubuntu-latest"]
9+
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13"]
10+
include:
11+
- os: macos-latest
12+
python-version: "3.13"
13+
# - os: windows-latest # TODO: Fix the Windows test that runs in an infinite loop
14+
# python-version: '3.13'
15+
runs-on: ${{ matrix.os }}
16+
steps:
17+
- uses: actions/checkout@v4
18+
- uses: actions/setup-python@v5
19+
with:
20+
python-version: ${{ matrix.python-version }}
21+
allow-prereleases: true
22+
- name: Copy libmagic into magic dir
23+
run: ${{ (runner.os == 'Windows' && 'bash add_libmagic.sh') || 'sudo -E bash add_libmagic.sh' }}
24+
- run: pip install --upgrade pip
25+
- run: pip install --upgrade pytest
26+
- run: pip install --editable .
27+
- run: LC_ALL=en_US.UTF-8 pytest
28+
shell: bash
29+
timeout-minutes: 15 # Limit Windows infinite loop.

.github/workflows/wheels.yml

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
name: wheels
2+
3+
on:
4+
pull_request:
5+
push:
6+
branches: master
7+
release:
8+
types: [released, prereleased]
9+
workflow_dispatch: # allows running workflow manually from the Actions tab
10+
11+
jobs:
12+
13+
build-sdist:
14+
runs-on: ubuntu-latest
15+
16+
env:
17+
PIP_DISABLE_PIP_VERSION_CHECK: 1
18+
19+
steps:
20+
- uses: actions/checkout@v4
21+
with:
22+
fetch-depth: 0
23+
24+
- name: Set up Python
25+
uses: actions/setup-python@v5
26+
with:
27+
python-version: '3.x'
28+
29+
- run: sudo apt-get install -y libmagic1
30+
31+
- name: Build source distribution
32+
run: |
33+
pip install --upgrade setuptools wheel pip build
34+
python -m build --sdist
35+
36+
- uses: actions/upload-artifact@v4
37+
with:
38+
name: dist
39+
path: dist/*.tar.*
40+
41+
42+
build-wheels-matrix:
43+
runs-on: ubuntu-latest
44+
outputs:
45+
include: ${{ steps.set-matrix.outputs.include }}
46+
steps:
47+
- uses: actions/checkout@v4
48+
- uses: actions/setup-python@v5
49+
with:
50+
python-version: '3.x'
51+
- run: pip install cibuildwheel==2.17.0 # sync version with pypa/cibuildwheel below
52+
- id: set-matrix
53+
env:
54+
# only mention one (trivial) python version, as py2.py3 wheels only need to be build once per arch
55+
CIBW_PROJECT_REQUIRES_PYTHON: '==3.12.*'
56+
# skip PyPy wheels for now, and skip i686 wheels because pytest is failing
57+
CIBW_SKIP: pp* *i686
58+
run: |
59+
MATRIX_INCLUDE=$(
60+
{
61+
cibuildwheel --print-build-identifiers --platform linux --arch all | jq -nRc '{"only": inputs, "os": "ubuntu-latest"}' \
62+
&& cibuildwheel --print-build-identifiers --platform macos --arch x86_64 | jq -nRc '{"only": inputs, "os": "macos-13"}' \
63+
&& cibuildwheel --print-build-identifiers --platform macos --arch arm64 | jq -nRc '{"only": inputs, "os": "macos-14"}' \
64+
&& cibuildwheel --print-build-identifiers --platform windows --arch x86,AMD64 | jq -nRc '{"only": inputs, "os": "windows-latest"}'
65+
} | jq -sc
66+
)
67+
echo "include=$MATRIX_INCLUDE" >> $GITHUB_OUTPUT
68+
69+
70+
build-wheels:
71+
name: build ${{ matrix.only }}
72+
needs: build-wheels-matrix
73+
runs-on: ${{ matrix.os }}
74+
75+
strategy:
76+
fail-fast: false
77+
matrix:
78+
include: ${{ fromJson(needs.build-wheels-matrix.outputs.include) }}
79+
80+
steps:
81+
- uses: actions/checkout@v4
82+
with:
83+
fetch-depth: 0
84+
85+
- name: Set up QEMU
86+
if: runner.os == 'Linux'
87+
uses: docker/setup-qemu-action@v3
88+
89+
- uses: pypa/cibuildwheel@v2.17.0 # sync version with pip install cibuildwheel above
90+
timeout-minutes: 10
91+
with:
92+
only: ${{ matrix.only }}
93+
env:
94+
CIBW_BUILD_VERBOSITY: 1
95+
# add compiled libmagic to the build directory (to include in the wheel)
96+
CIBW_BEFORE_BUILD: ${{ ( startsWith( matrix.os, 'macos' ) && 'sudo -E bash add_libmagic.sh' ) || 'bash add_libmagic.sh' }}
97+
# build macos wheels with maximum backwards compatibility (gcc -mmacosx-version-min flag)
98+
MACOSX_DEPLOYMENT_TARGET: ${{ ( endsWith( matrix.only, 'arm64' ) && '11.0' ) || '10.9' }}
99+
# simple smoke test run on each wheel: this is an HLS MP4 video, only recognised in recent versions of libmagic
100+
CIBW_TEST_COMMAND: python -c "import magic; assert magic.Magic(mime=True).from_buffer(b'\x00\x00\x00\x1cftypiso5\x00\x00\x00\x01isomiso5hlsf\x00\x00') == 'video/mp4'"
101+
102+
- uses: actions/upload-artifact@v4
103+
with:
104+
name: dist-${{ matrix.only }}
105+
path: wheelhouse/*.whl
106+
107+
108+
publish:
109+
if: github.event_name == 'release'
110+
needs: [build-sdist, build-wheels]
111+
runs-on: ubuntu-latest
112+
113+
permissions:
114+
contents: write # softprops/action-gh-release
115+
id-token: write # pypa/gh-action-pypi-publish
116+
117+
steps:
118+
- uses: actions/setup-python@v5
119+
with:
120+
python-version: 3.x
121+
122+
- uses: actions/download-artifact@v4
123+
with:
124+
path: dist/
125+
pattern: dist-*
126+
merge-multiple: true
127+
128+
- run: ls -ltra dist/
129+
130+
- run: pip install --upgrade python-magic --find-links ./dist
131+
132+
- name: Smoketest
133+
run: python -c "import magic; magic.Magic()"
134+
135+
- name: Upload release assets
136+
uses: softprops/action-gh-release@v0.1.15
137+
with:
138+
files: dist/*
139+
140+
- name: Publish package distributions to PyPI
141+
uses: pypa/gh-action-pypi-publish@v1.8.14

.gitignore

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
.coverage*
2+
.tox/
3+
bin/
4+
deb_dist
5+
htmlcov/
6+
lib/
7+
**/__pycache__
8+
python_magic.egg-info
9+
pip-selfcheck.json
10+
pyvenv.cfg
11+
*.pyc
12+
*~
13+
dist/
14+
.vscode/
15+
.venv/
16+
.idea/

CHANGELOG

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
Changes to 0.4.28:
2+
3+
- libmagic and magic.mgc now come bundled in the wheels on PyPI, and will be copied
4+
into site-packages/magic along with the Python files of this library
5+
- magic.loader.load_lib now first searches for libmagic in the same directory as the
6+
Python files, then in the current working directory, and only then in standard paths
7+
- magic.Magic(magic_file=...) and magic.compat.Magic.load(magic_file=...) will now
8+
prefer "magic.mgc" in the same directory as the Python files, only if left
9+
unspecified by the user (and the MAGIC env var is empty or not set)
10+
- support MAGIC_SYMLINK (via follow_symlink flag on Magic constructor)
11+
- correctly throw FileNotFoundException depending on flag
12+
- support "magic-1.dll" on Windows, which is produced by vcpkg
13+
- add python 3.10 to tox config
14+
- update test for upstream gzip extensions
15+
16+
Changes to 0.4.27:
17+
18+
- remove spurious pyproject.toml that breaks source builds
19+
20+
Changes to 0.4.26:
21+
22+
- Use tox for all multi-version testing
23+
- Fix use of pytest, use it via tox
24+
25+
Changes to 0.4.25:
26+
27+
- Support os.PathLike values in Magic.from_file and magic.from_file
28+
- Handle some versions of libmagic that return mime string without charset
29+
- Fix tests for file 5.41
30+
- Include typing stub in package
31+
32+
Changes to 0.4.24:
33+
34+
- Fix regression in library loading on some Alpine docker images.
35+
36+
Changes to 0.4.23
37+
38+
- Include a `py.typed` sentinel to enable type checking
39+
- Improve fix for attribute error during destruction
40+
- Cleanup library loading logic
41+
- Add new homebrew library dir for OSX
42+
43+
Changes to 0.4.21, 0.4.22
44+
45+
- Unify dll loader between the standard and compat library, fixing load
46+
failures on some previously supported platforms.
47+
48+
Changes to 0.4.20
49+
50+
- merge in a compatibility layer for the upstream libmagic python binding.
51+
Since both this package and that one are called 'magic', this compat layer
52+
removes a very common source of runtime errors. Use of that libmagic API will
53+
produce a deprecation warning.
54+
55+
- support python 3.9 in tests and pypi metadata
56+
57+
- add support for magic_descriptor functions, which take a file descriptor
58+
rather than a filename.
59+
60+
- sometimes the returned description includes snippets of the file, e.g a title
61+
for MS Word docs. Since this is in an unknown encoding, we would throw a
62+
unicode decode error trying to decode. Now, it decodes with
63+
'backslashreplace' to handle this more gracefully. The undecodable characters
64+
are replaced with hex escapes.
65+
66+
- add support for MAGIC_EXTENSION, to return possible file extensions.
67+
68+
- add mypy typing stubs file, for type checking
69+
70+
Changes in 0.4.18
71+
72+
- Make bindings for magic\_[set|get]param optional, and throw NotImplementedError
73+
if they are used but not supported. Only call setparam() in the constructor if
74+
it's supported. This prevents breakage on CentOS7 which uses an old version of
75+
libmagic.
76+
77+
- Add tests for CentOS 7 & 8
78+
79+
Changes in 0.4.16 and 0.4.17
80+
81+
- add MAGIC_MIME_TYPE constant, use that in preference to MAGIC_MIME internally.
82+
This sets up for a breaking change in a future major version bump where
83+
MAGIC_MIME will change to match magic.h.
84+
- add magic.version() function to return library version
85+
- add setparam/getparam to control internal behavior
86+
- increase internal limits with setparam to prevent spurious error on some jpeg files
87+
- various setup.py improvements to declare modern python support
88+
- support MSYS2 magic dlls
89+
- fix warning about using 'is' on an int in python 3.8
90+
- include tests in source distribution
91+
92+
- many test improvements:
93+
-- tox runner support
94+
-- remove deprecated test_suite field from setup.py
95+
-- docker tests that cover all LTS ubuntu versions
96+
-- add test for snapp file identification
97+
98+
- doc improvements
99+
-- document dependency install process for debian
100+
-- various typos
101+
-- document test running process

COMPAT.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
There are two python modules named 'magic' that do the same thing, but
2+
with incompatible APIs. One of these ships with libmagic, and (this one) is
3+
distributed through pypi. Both have been around for many years and have
4+
substantial user bases. This incompatibility is a major source of pain for
5+
users, and bug reports for me.
6+
7+
To mitigate this pain, python-magic has added a compatibility layer to export
8+
the libmagic python API parallel to the existing one.
9+
10+
The mapping between the libmagic and python-magic functions is:
11+
12+
detect_from_filename => from_file
13+
detect_from_content => from_buffer
14+
detect_from_fobj => from_descriptor(f.fileno())
15+
open => Magic()
16+
17+

LICENSE

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
The MIT License (MIT)
2+
3+
Copyright (c) 2001-2014 Adam Hupp
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.
22+
23+
24+
====
25+
26+
Portions of this package (magic/compat.py and test/libmagic_test.py)
27+
are distributed under the following copyright notice:
28+
29+
30+
$File: LEGAL.NOTICE,v 1.15 2006/05/03 18:48:33 christos Exp $
31+
Copyright (c) Ian F. Darwin 1986, 1987, 1989, 1990, 1991, 1992, 1994, 1995.
32+
Software written by Ian F. Darwin and others;
33+
maintained 1994- Christos Zoulas.
34+
35+
This software is not subject to any export provision of the United States
36+
Department of Commerce, and may be exported to any country or planet.
37+
38+
Redistribution and use in source and binary forms, with or without
39+
modification, are permitted provided that the following conditions
40+
are met:
41+
1. Redistributions of source code must retain the above copyright
42+
notice immediately at the beginning of the file, without modification,
43+
this list of conditions, and the following disclaimer.
44+
2. Redistributions in binary form must reproduce the above copyright
45+
notice, this list of conditions and the following disclaimer in the
46+
documentation and/or other materials provided with the distribution.
47+
48+
THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
49+
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
50+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
51+
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
52+
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
53+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
54+
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
55+
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
56+
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
57+
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
58+
SUCH DAMAGE.

MANIFEST.in

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
include *.py
2+
include LICENSE
3+
graft tests
4+
global-exclude __pycache__
5+
global-exclude *.py[co]

0 commit comments

Comments
 (0)