{"id":32176457,"url":"https://github.com/adamchainz/treepoem","last_synced_at":"2025-10-21T20:00:12.540Z","repository":{"id":37601597,"uuid":"54045707","full_name":"adamchainz/treepoem","owner":"adamchainz","description":"Barcode rendering for Python supporting QRcode, Aztec, PDF417, I25, Code128, Code39 and many more types.","archived":false,"fork":false,"pushed_at":"2025-10-07T10:23:25.000Z","size":2500,"stargazers_count":153,"open_issues_count":4,"forks_count":29,"subscribers_count":8,"default_branch":"main","last_synced_at":"2025-10-21T20:00:06.046Z","etag":null,"topics":["barcod","bwipp","python"],"latest_commit_sha":null,"homepage":"","language":"PostScript","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/adamchainz.png","metadata":{"files":{"readme":"README.rst","changelog":"CHANGELOG.rst","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":".github/CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":".github/SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"github":"adamchainz","custom":["https://adamj.eu/books/"]}},"created_at":"2016-03-16T15:53:06.000Z","updated_at":"2025-10-21T09:55:30.000Z","dependencies_parsed_at":"2024-01-26T23:28:06.761Z","dependency_job_id":"2aa7db51-a866-48a3-bffd-beb76fe997be","html_url":"https://github.com/adamchainz/treepoem","commit_stats":{"total_commits":529,"total_committers":12,"mean_commits":"44.083333333333336","dds":0.275992438563327,"last_synced_commit":"6eaf32726147c430d5a76ecd5c96fe2acb86e2dc"},"previous_names":[],"tags_count":39,"template":false,"template_full_name":null,"purl":"pkg:github/adamchainz/treepoem","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/adamchainz%2Ftreepoem","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/adamchainz%2Ftreepoem/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/adamchainz%2Ftreepoem/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/adamchainz%2Ftreepoem/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/adamchainz","download_url":"https://codeload.github.com/adamchainz/treepoem/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/adamchainz%2Ftreepoem/sbom","scorecard":{"id":164933,"data":{"date":"2025-08-11","repo":{"name":"github.com/adamchainz/treepoem","commit":"152f4e0ac11f55151dc79d8261ed3a73a8f541e3"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":5.5,"checks":[{"name":"Code-Review","score":0,"reason":"Found 1/22 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":"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":"Security-Policy","score":9,"reason":"security policy file detected","details":["Info: security policy file detected: .github/SECURITY.md:1","Info: Found linked content: .github/SECURITY.md:1","Warn: One or no descriptive hints of disclosure, vulnerability, and/or timelines in security policy","Info: Found text in security policy: .github/SECURITY.md:1"],"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":"Maintained","score":7,"reason":"9 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 7","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Info: jobLevel 'contents' permission set to 'read': .github/workflows/main.yml:62","Warn: no topLevel permission defined: .github/workflows/main.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":10,"reason":"no binaries found in the repo","details":null,"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":"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/main.yml:30: update your workflow using https://app.stepsecurity.io/secureworkflow/adamchainz/treepoem/main.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/main.yml:32: update your workflow using https://app.stepsecurity.io/secureworkflow/adamchainz/treepoem/main.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/main.yml:38: update your workflow using https://app.stepsecurity.io/secureworkflow/adamchainz/treepoem/main.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/main.yml:66: update your workflow using https://app.stepsecurity.io/secureworkflow/adamchainz/treepoem/main.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/main.yml:68: update your workflow using https://app.stepsecurity.io/secureworkflow/adamchainz/treepoem/main.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/main.yml:73: update your workflow using https://app.stepsecurity.io/secureworkflow/adamchainz/treepoem/main.yml/main?enable=pin","Info:   0 out of   3 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   3 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":"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":"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":"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":"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":-1,"reason":"internal error: error during branchesHandler.setup: internal error: githubv4.Query: Resource not accessible by integration","details":null,"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":"Packaging","score":10,"reason":"packaging workflow detected","details":["Info: Project packages its releases by way of GitHub Actions.: .github/workflows/main.yml:55"],"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":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 22 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-16T14:33:30.862Z","repository_id":37601597,"created_at":"2025-08-16T14:33:30.862Z","updated_at":"2025-08-16T14:33:30.862Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":280325299,"owners_count":26311419,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-21T02:00:06.614Z","response_time":58,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":["barcod","bwipp","python"],"created_at":"2025-10-21T20:00:11.081Z","updated_at":"2025-10-21T20:00:12.527Z","avatar_url":"https://github.com/adamchainz.png","language":"PostScript","funding_links":["https://github.com/sponsors/adamchainz","https://adamj.eu/books/"],"categories":[],"sub_categories":[],"readme":"========\nTreepoem\n========\n\n.. image:: https://img.shields.io/github/actions/workflow/status/adamchainz/treepoem/main.yml.svg?branch=main\u0026style=for-the-badge\n   :target: https://github.com/adamchainz/treepoem/actions?workflow=CI\n\n.. image:: https://img.shields.io/pypi/v/treepoem.svg?style=for-the-badge\n   :target: https://pypi.org/project/treepoem/\n\n.. image:: https://img.shields.io/badge/code%20style-black-000000.svg?style=for-the-badge\n   :target: https://github.com/psf/black\n\n.. image:: https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit\u0026logoColor=white\u0026style=for-the-badge\n   :target: https://github.com/pre-commit/pre-commit\n   :alt: pre-commit\n\nA cleverly named, but very simple python barcode renderer wrapping the\nBWIPP_ library and ``ghostscript`` command line tool.\n\n----\n\n**Improve your Django and Git skills** with `one of my books \u003chttps://adamj.eu/books/\u003e`__.\n\n----\n\nInstallation\n============\n\nInstall from **pip**:\n\n.. code-block:: sh\n\n    python -m pip install treepoem\n\nPython 3.9 to 3.14 supported.\n\nYou'll also need Ghostscript installed. On Ubuntu/Debian this can be installed\nwith:\n\n.. code-block:: sh\n\n    apt-get install ghostscript\n\nOn Mac OS X use:\n\n.. code-block:: sh\n\n    brew install ghostscript\n\nOtherwise refer to your distribution's package manager, though it's likely to\nbe called ``ghostscript`` too.\n\nThere's a known issue with rendering on Ghostscript 9.22+ where images are\nsmeared. See\n`GitHub Issue #124 \u003chttps://github.com/adamchainz/treepoem/issues/124\u003e`_ and\nits associated links for more details. Ghostscript merged a fix in version\n9.26 and common barcodes seem to work from then on, though still with some\nsmearing.\n\nYou can check your Ghostscript version with:\n\n.. code-block:: sh\n\n    gs --version\n\nAPI\n===\n\n``generate_barcode(barcode_type: str, data: str | bytes, options: dict[str, str | bool] | None=None, *, scale: int = 2) -\u003e Image``\n----------------------------------------------------------------------------------------------------------------------------------\n\nGenerates a barcode and returns it as a `PIL Image object \u003chttps://pillow.readthedocs.io/en/stable/reference/Image.html#the-image-class\u003e`__\n\n``barcode_type`` is the name of the barcode type to generate from BWIPP’s `list of supported types \u003chttps://github.com/bwipp/postscriptbarcode/wiki/Symbologies-Reference\u003e`__.\nThe ``barcode_types`` dictionary, described below, contains the names of the supported types.\n\n``data`` is a ``str`` or ``bytes`` of data to embed in the barcode.\nThe amount of data that can be embedded varies by type.\n\n``options`` is a dictionary of strings-to-strings of BWIPP options, per `its documentation \u003chttps://github.com/bwipp/postscriptbarcode/wiki/Options-Reference\u003e`__.\n\n``scale`` controls the output image size.\nUse ``1`` for the smallest image and larger values for larger images.\n\nFor example, this generates a QR code image, adds a border with |ImageOps.expand()|__, and saves it to a file using |Image.save()|__:\n\n.. |ImageOps.expand()| replace:: ``ImageOps.expand()``\n__ https://pillow.readthedocs.io/en/stable/reference/ImageOps.html#PIL.ImageOps.expand\n\n.. |Image.save()| replace:: ``Image.save()``\n__ https://pillow.readthedocs.io/en/stable/reference/Image.html#PIL.Image.Image.save\n\n.. code-block:: python\n\n    import treepoem\n    from PIL import ImageOps\n\n    image = treepoem.generate_barcode(\n        barcode_type=\"qrcode\",\n        data=\"https://example.com\",\n    )\n    image = ImageOps.expand(image, border=10, fill=\"white\")\n    image.convert(\"1\").save(\"barcode.png\")\n\nFor greyscale barcodes, the conversion to monochrome (``image.convert(\"1\")``) will likely reduce its file size.\n\n``barcode_types: dict[str, BarcodeType]``\n-----------------------------------------\n\nThis is a ``dict`` of the ~100 names of the barcode types that the vendored\nversion of BWIPP_ supports: its keys are ``str``\\s of the barcode type encoder\nnames, and the values are instances of ``BarcodeType``.\n\n``BarcodeType``\n---------------\n\nA class representing meta information on the types. It has two attributes:\n\n* ``type_code`` - the value needed for the ``barcode_type`` argument of\n  ``generate_barcode()`` to use this type.\n\n* ``description`` - the human level description of the type\n  which has two ``str``.\n\nOnly these common types are used in the test suite:\n\n* ``qrcode`` - `QR Code`_\n\n* ``azteccode`` - `Aztec Code`_\n\n* ``pdf417`` - PDF417_\n\n* ``interleaved2of5`` - `Interleaved 2 of 5`_\n\n* ``code128`` - `Code 128`_\n\n* ``code39`` - `Code 39`_\n\nCommand-line interface\n======================\n\nTreepoem also includes a simple command-line interface to the\nfunctionality of ``generate_barcode``. For example, these commands\nwill generate two QR codes with identical contents, but different levels\nof error correction (see `QR Code Options`_):\n\n.. code-block:: sh\n\n   $ treepoem -o barcode1.png -t qrcode \"This is a test\" eclevel=H\n   $ treepoem -o barcode2.png -t qrcode \"^084his is a test\" eclevel=L parse\n\nComplete usage instructions are shown with ``treepoem --help``.\n\nWhat's so clever about the name?\n================================\n\nBarcode.\n\nBark ode.\n\nTree poem.\n\nUpdating BWIPP\n==============\n\nFor development of treepoem, when there's a new BWIPP release:\n\n1. Run ``./download_bwipp.py`` with the `version of BWIPP \u003chttps://github.com/bwipp/postscriptbarcode/tags\u003e`__ to download.\n2. Run ``./make_data.py`` to update the barcode types that treepoem knows about.\n3. Add a note in ``CHANGELOG.rst`` about the upgrade, adapting from the previous one.\n4. Commit and make a pull request, `adapting from previous examples \u003chttps://github.com/adamchainz/treepoem/pulls?utf8=%E2%9C%93\u0026q=is%3Apr+is%3Aclosed+upgrade+bwipp\u003e`__.\n\n.. _BWIPP: https://github.com/bwipp/postscriptbarcode\n.. _QR Code: https://github.com/bwipp/postscriptbarcode/wiki/QR-Code\n.. _Aztec Code: https://github.com/bwipp/postscriptbarcode/wiki/Aztec-Code\n.. _PDF417: https://github.com/bwipp/postscriptbarcode/wiki/PDF417\n.. _Interleaved 2 of 5: https://github.com/bwipp/postscriptbarcode/wiki/Interleaved-2-of-5\n.. _Code 128: https://github.com/bwipp/postscriptbarcode/wiki/Code-128\n.. _Code 39: https://github.com/bwipp/postscriptbarcode/wiki/Code-39\n.. _QR Code Options: https://github.com/bwipp/postscriptbarcode/wiki/QR-Code\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fadamchainz%2Ftreepoem","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fadamchainz%2Ftreepoem","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fadamchainz%2Ftreepoem/lists"}