{"id":16790287,"url":"https://github.com/cdgriffith/puremagic","last_synced_at":"2026-03-09T21:24:04.639Z","repository":{"id":6831385,"uuid":"8079700","full_name":"cdgriffith/puremagic","owner":"cdgriffith","description":"Pure python implementation of identifying files based off their magic numbers","archived":false,"fork":false,"pushed_at":"2026-03-09T03:23:53.000Z","size":956,"stargazers_count":225,"open_issues_count":9,"forks_count":40,"subscribers_count":7,"default_branch":"master","last_synced_at":"2026-03-09T07:28:46.111Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/cdgriffith.png","metadata":{"files":{"readme":"README.rst","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":"AUTHORS.rst","dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2013-02-07T19:18:54.000Z","updated_at":"2026-02-20T13:18:10.000Z","dependencies_parsed_at":"2024-03-06T16:55:32.548Z","dependency_job_id":"8368743c-cacc-4b35-a95b-26459493c25c","html_url":"https://github.com/cdgriffith/puremagic","commit_stats":{"total_commits":36,"total_committers":4,"mean_commits":9.0,"dds":"0.36111111111111116","last_synced_commit":"763349ec4d02ba930fb1142c6eb684afdf06c6ab"},"previous_names":[],"tags_count":31,"template":false,"template_full_name":null,"purl":"pkg:github/cdgriffith/puremagic","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cdgriffith%2Fpuremagic","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cdgriffith%2Fpuremagic/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cdgriffith%2Fpuremagic/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cdgriffith%2Fpuremagic/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cdgriffith","download_url":"https://codeload.github.com/cdgriffith/puremagic/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cdgriffith%2Fpuremagic/sbom","scorecard":{"id":269742,"data":{"date":"2025-08-11","repo":{"name":"github.com/cdgriffith/puremagic","commit":"47b0a5bebf394b0aa9d55c2d4935454202cdbc79"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3.3,"checks":[{"name":"Maintained","score":1,"reason":"2 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 1","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Code-Review","score":0,"reason":"Found 1/30 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/pythonpublish.yml:1","Warn: no topLevel permission defined: .github/workflows/tests.yml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Binary-Artifacts","score":8,"reason":"binaries present in source code","details":["Warn: binary detected: test/resources/media/test.iso:1","Warn: binary detected: test/resources/system/test.exe:1"],"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/pythonpublish.yml:16: update your workflow using https://app.stepsecurity.io/secureworkflow/cdgriffith/puremagic/pythonpublish.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/pythonpublish.yml:19: update your workflow using https://app.stepsecurity.io/secureworkflow/cdgriffith/puremagic/pythonpublish.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/pythonpublish.yml:24: update your workflow using https://app.stepsecurity.io/secureworkflow/cdgriffith/puremagic/pythonpublish.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/tests.yml:27: update your workflow using https://app.stepsecurity.io/secureworkflow/cdgriffith/puremagic/tests.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/tests.yml:30: update your workflow using https://app.stepsecurity.io/secureworkflow/cdgriffith/puremagic/tests.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/tests.yml:36: update your workflow using https://app.stepsecurity.io/secureworkflow/cdgriffith/puremagic/tests.yml/master?enable=pin","Info:   0 out of   4 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   2 third-party GitHubAction dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'","Warn: branch protection not enabled for branch '1.x-bugfix'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 29 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-17T13:02:35.330Z","repository_id":6831385,"created_at":"2025-08-17T13:02:35.331Z","updated_at":"2025-08-17T13:02:35.331Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30312174,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-09T20:05:46.299Z","status":"ssl_error","status_checked_at":"2026-03-09T19:57:04.425Z","response_time":61,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-13T08:29:23.796Z","updated_at":"2026-03-09T21:24:04.631Z","avatar_url":"https://github.com/cdgriffith.png","language":"Python","funding_links":[],"categories":["others"],"sub_categories":[],"readme":"=========\npuremagic\n=========\n\npuremagic is a pure python module that will identify a file based off\nits magic numbers. It has zero runtime dependencies and serves as a\nlightweight, cross-platform alternative to python-magic/libmagic.\n\nIt is designed to be minimalistic and inherently cross platform\ncompatible. It is also designed to be a stand in for python-magic. It\nimplements the functions :code:`from_file(filename[, mime])` and\n:code:`from_string(string[, mime])` however the :code:`magic_file()` and\n:code:`magic_string()` are more powerful and will also display confidence and\nduplicate matches.\n\nStarting with version 2.0, puremagic includes a **deep scan** system\nthat performs content-aware analysis beyond simple magic number matching.\nThis improves accuracy for formats like Office documents, text files,\nCSV, MP3, Python source, JSON, HDF5, email, and many scientific formats.\nDeep scan is enabled by default and can be disabled by setting the\nenvironment variable :code:`PUREMAGIC_DEEPSCAN=0`.\n\nAdvantages over using a wrapper for 'file' or 'libmagic':\n\n-  Faster\n-  Lightweight\n-  Cross platform compatible\n-  No dependencies\n\nDisadvantages:\n\n-  Does not have as many file types\n-  No multilingual comments\n-  Duplications due to small or reused magic numbers\n\n(Help fix the first two disadvantages by contributing!)\n\nCompatibility\n~~~~~~~~~~~~~\n\n-  Python 3.12+\n\nFor use with Python 3.7–3.11, use the 1.x release chain.\n\nUsing github ci to run continuous integration tests on listed platforms.\n\nInstall from PyPI\n-----------------\n\n.. code:: bash\n\n        $ pip install puremagic\n\nOn linux environments, you may want to be clear you are using python3\n\n.. code:: bash\n\n        $ python3 -m pip install puremagic\n\nUsage\n-----\n\n\"from_file\" will return the most likely file extension. \"magic_file\"\nwill give you every possible result it finds, as well as the confidence.\n\n.. code:: python\n\n        import puremagic\n\n        filename = \"test/resources/images/test.gif\"\n\n        ext = puremagic.from_file(filename)\n        # '.gif'\n\n        puremagic.magic_file(filename)\n        # [['.gif', 'image/gif', 'Graphics interchange format file (GIF87a)', 0.7],\n        #  ['.gif', '', 'GIF file', 0.5]]\n\nWith \"magic_file\" it gives each match, highest confidence first:\n\n-  possible extension(s)\n-  mime type\n-  description\n-  confidence (All headers have to perfectly match to make the list,\n   however this orders it by longest header, therefore most precise,\n   first)\n\nIf you already have a file open, or raw byte string, you could also use:\n\n* from_string\n* from_stream\n* magic_string\n* magic_stream\n\n.. code:: python\n\n        with open(r\"test\\resources\\video\\test.mp4\", \"rb\") as file:\n            print(puremagic.magic_stream(file))\n\n        # [PureMagicWithConfidence(byte_match=b'ftypisom', offset=4, extension='.mp4', mime_type='video/mp4', name='MPEG-4 video', confidence=0.8),\n        #  PureMagicWithConfidence(byte_match=b'iso2avc1mp4', offset=20, extension='.mp4', mime_type='video/mp4', name='MP4 Video', confidence=0.8)]\n\nDeep Scan\n---------\n\nDeep scan performs content-aware analysis when magic number matching\nalone is not enough. It is enabled by default and runs automatically\nas part of the normal identification pipeline.\n\nThe following format-specific scanners are included:\n\n-  **ZIP** — Distinguishes Office formats (xlsx/docx/pptx), OpenDocument\n   (odt/ods/odp), and their macro-enabled variants by inspecting ZIP internals\n-  **MPEG Audio** — Parses MP3/MPEG audio frames to validate and identify audio files\n-  **Text** — Detects text encodings, line endings (CRLF/LF/CR), CSV files\n   with automatic delimiter detection, and email messages (.eml)\n-  **Python** — Validates Python source via :code:`ast.parse()` and keyword analysis\n-  **PDF** — Format-specific PDF validation\n-  **JSON** — JSON format validation\n-  **HDF5** — Identifies HDF5 subtypes used in scientific computing (AnnData,\n   Loom, Cooler, BIOM v2, mz5, and more)\n-  **Audio** — Identifies HCOM and SNDR audio formats\n-  **Dynamic text checks** — Recognizes many scientific and bioinformatics text\n   formats including VCF, SAM, GFF, PLY, VTK, and others\n\nTo disable deep scan, set the environment variable:\n\n.. code:: bash\n\n        $ export PUREMAGIC_DEEPSCAN=0\n\nScript\n------\n\n*Usage*\n\n.. code:: bash\n\n        $ python -m puremagic [options] filename \u003cfilename2\u003e...\n\n*Options*\n\n-  :code:`-m, --mime` — Return the MIME type instead of file extension\n-  :code:`-v, --verbose` — Print verbose output with all possible matches\n-  :code:`--version` — Show program version\n\nDirectories can be passed as arguments; all files within will be scanned.\n\n*Examples*\n\n.. code:: bash\n\n        $ python -m puremagic test/resources/images/test.gif\n        'test/resources/images/test.gif' : .gif\n\n        $ python -m puremagic -m test/resources/images/test.gif test/resources/audio/test.mp3\n        'test/resources/images/test.gif' : image/gif\n        'test/resources/audio/test.mp3' : audio/mpeg\n\nUpgrading from 1.x\n-------------------\n\nVersion 2.0 includes the following breaking changes:\n\n-  **Python 3.12+ required** — Python 3.7–3.11 are no longer supported.\n   Use the 1.x release chain for older Python versions.\n-  **Removed** :code:`puremagic.what()` — The :code:`imghdr` drop-in replacement\n   has been removed. Use :code:`puremagic.from_file()` instead.\n-  **Removed** :code:`magic_header_array`, :code:`magic_footer_array`, and\n   :code:`multi_part_dict` from the public API.\n-  **Removed** :code:`setup.py` — The project now uses :code:`pyproject.toml`\n   exclusively.\n-  Internal functions have been renamed from private (e.g. :code:`_magic_data`)\n   to public (e.g. :code:`magic_data`).\n\nFAQ\n---\n\n*The file type is actually X but it's showing up as Y with higher\nconfidence?*\n\nThis can happen when the file's signature happens to match a subset of a\nfile standard. The subset signature will be longer, therefore report\nwith greater confidence, because it will have both the base file type\nsignature plus the additional subset one.\n\n\nAcknowledgements\n----------------\n\nGary C. Kessler\n\nFor use of his File Signature Tables, available at:\nhttps://filesig.search.org/\n\nFreedesktop.org\n\nFor use of their shared-mime-info file, available at:\nhttps://cgit.freedesktop.org/xdg/shared-mime-info/\n\nLicense\n-------\n\nMIT Licenced, see LICENSE, Copyright (c) 2013-2026 Chris Griffith\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcdgriffith%2Fpuremagic","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcdgriffith%2Fpuremagic","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcdgriffith%2Fpuremagic/lists"}