Skip to main content

PyEncode

PyEncode protects CPython applications on Windows, Linux, and macOS. It compiles Python modules to code objects, serializes them with marshal for the portable runtime or a tagged primitive codec for the native runtime, compresses them, and authenticated-encrypts them with AES-256-GCM. The generated runtime decrypts and executes code in memory; neither plaintext source nor plaintext bytecode is written to a temporary file.

Version 0.6 retains the PYE2/manifest-format-3 compatibility contract and extends the per-build native runtime to standard CPython on Windows x64 and macOS arm64/x86_64. The independent hardening controls are:

  • --obf-code 0 decrypts each module once when it is imported. --obf-code 1 additionally puts the original code of module-level functions, methods, and lambdas in build-time authenticated capsules. The visible functions expose signature-preserving dispatch stubs while idle and restore their real CodeType only for a call. Nested definitions remain protected inside their encrypted parent and are sealed when that parent creates them.
  • --runtime-backend python emits the portable Python runtime. On Windows x64 or macOS arm64/x86_64, --runtime-backend native instead builds one per-build pyencode_runtime._runtime extension and embeds the masked master-key material in that binary. Application modules still remain encrypted .pye artifacts.
  • --native-module is a separate application AOT option. Use it only when selected application modules themselves should become Cython/Zig .pyd extensions; it is not implied by a native runtime.

The existing protection contract also includes:

  • Every artifact receives a random 128-bit filename, for example myapp/7b82a40e9aa14e60db7094f2de3fbc33.pye.
  • PYE2 has no plaintext JSON header; an artifact contains only its magic value, nonce, and ciphertext/authentication tag.
  • Module names, the entry point, and package flags are stored in an encrypted module index.
  • Manifest format 3 is signed with Ed25519 and contains the SHA-256 digest of every artifact.
  • The runtime, launcher, support trees, and resources copied by default are signed, key-bound, and verified again during install(). Explicit --unsigned-data resources are isolated from that trusted inventory for host-managed mutable data.
  • The loader exposes only a small trampoline to runpy, rather than returning the application's real code object. Module keys are derived on demand and are not retained by the finder.
  • Application modules explicitly selected with --native-module are removed from the encrypted index, emitted as signed ABI-tagged .pyd files, and recorded in signed .pyencode-native.json coverage.
  • A dedicated finder rejects preloaded/shadowed native modules and rechecks the exact extension hash immediately before CPython loads it.

The goal is to make static analysis substantially more expensive than it is for .pyc files. PyEncode does not claim to make reverse engineering impossible.

Supported Python versions

PyEncode 0.6 requires standard CPython 3.10 or later. The production release gate currently targets CPython 3.14 on Windows, Linux, and macOS, matching the embedded interpreter used by the Fusion add-in integration. CI also monitors Python 3.10 through 3.13 and 3.15 as compatibility lanes, but those versions are not release-blocking until their compiler-specific capsule mappings are fully validated. PyPy and other Python implementations are not currently supported.

The portable runtime source is Python-only. The default cryptography backend uses that package's native extension; --runtime-crypto pure-python removes the runtime dependency and is intended for restricted embedded hosts such as Fusion on macOS. However, a built artifact is tied to the exact CPython major/minor version used to build it:

  • an artifact built with CPython 3.11 runs on CPython 3.11;
  • that artifact does not run on CPython 3.10, 3.12, or 3.14;
  • to support several minor versions, build a separate output with each interpreter.

If a bundle includes .pyd, .so, .dll, or other native dependencies through --support, the whole bundle is also constrained by the operating system, architecture, and ABI of those files. Current testing targets the standard GIL build of CPython; free-threaded and debug ABIs require separate builds and testing.

The per-build native runtime supports standard 64-bit Windows CPython and macOS CPython on arm64 or x86_64. It emits .cpXY-win_amd64.pyd on Windows and .cpython-XY-darwin.so on macOS. Application modules selected with --native-module remain Windows-only. Native builds fail instead of silently falling back when their compiler, ABI, binary format, imports, export, architecture, or signature cannot be validated. Build a separate native output for every OS, architecture, and CPython major/minor ABI used by a target host. The per-build native runtime's direct CodeType codec requires CPython 3.11 or later; CPython 3.10 remains supported by the portable runtime.

On Linux, use --runtime-backend python. On macOS, native-runtime compilation uses a full external CPython plus Xcode Command Line Tools; an embedded host's stripped Python does not need Cython, headers, or a compiler. The resulting runtime has no generated-application dependency on cryptography: it uses system CommonCrypto and is code-signed before PyEncode computes its hashes. Whether a hardened embedding host accepts an ad-hoc or third-party signature is still controlled by that host's macOS library-validation entitlements and signing policy.

Installation

Install the published package from PyPI in a virtual environment:

py -3.11 -m venv .venv
.venv\Scripts\Activate.ps1
python -m pip install --upgrade pip
python -m pip install pyencode-protector

The CLI command and import namespace are both named pyencode.

For source development, use an editable installation in a virtual environment.

Windows PowerShell:

py -3.11 -m venv .venv
.venv\Scripts\Activate.ps1
python -m pip install --upgrade pip
python -m pip install -e .

Linux:

python3.11 -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip
python -m pip install -e .

The builder depends on cryptography>=42. Portable generated applications use it at runtime by default. Pass --runtime-crypto pure-python to emit a dependency-free portable runtime that verifies Ed25519 signatures and opens the existing AES-256-GCM PYE2 format using signed Python code. This compatibility backend is slower and is not constant-time; it is intended for small protected bundles in embedded hosts, not as a general-purpose cryptography library. The native runtime has no generated-application dependency on cryptography or _pure_crypto.py.

The native convenience extra installs the Cython version used by the current Windows/macOS runtime contract and Zig on Windows:

python -m pip install "pyencode-protector[native]==0.6.0"

Production builds should place those tools in an isolated directory and create the hash-pinned descriptor shown below.

Usage

Built-in command-line help is available without opening the documentation:

pyencode --help
pyencode build --help
python -m pyencode --help

Protect a single file:

pyencode build hello.py -o dist/hello
python dist/hello/run.py

Protect a package containing __main__.py:

pyencode build src/myapp -o dist/myapp
python dist/myapp/run.py

Specify the entry module explicitly:

pyencode build src -o dist/app --entry myapp.__main__

Create and verify a Windows native toolchain descriptor with the target CPython interpreter (the interpreter embedded by Fusion in an add-in build):

pyencode native-toolchain create -o build/native-toolchain.json `
  --builder-python C:\Python311\python.exe `
  --tool-root build\native-tools `
  --python-include build\python-dev\include `
  --python-library build\python-dev\libs\python314.lib `
  --target-python-dll C:\path\to\Fusion\python314.dll `
  --cython-version 3.3.0 --zig-version 0.16.0

pyencode native-toolchain verify build/native-toolchain.json

Use the descriptor to build only the generated runtime as a per-build native extension while leaving every application module encrypted as .pye:

pyencode build src -o dist/app --entry myapp.main `
  --obf-code 1 `
  --runtime-backend native `
  --runtime-crypto pure-python `
  --native-toolchain build/native-toolchain.json

For a native runtime, --runtime-crypto is retained as compatibility metadata but does not select a Python crypto implementation. The generated .pyd performs AES-256-GCM through Windows CNG. The generated macOS .so uses CommonCrypto's AES primitive with compiled CTR/GHASH code and system randomness. Both keep HKDF/Ed25519 helpers inside compiled cdef code, ship no _pure_crypto.py, and do not import an installed or vendored cryptography package. bcrypt.dll on Windows and the macOS system libraries are operating-system dependencies, not bundled libraries.

Build the macOS runtime with a complete external CPython of the same major/minor version as the target host. PyEncode auto-probes the Xcode SDK and current architecture, so no Windows toolchain descriptor is accepted or needed:

/opt/homebrew/bin/python3 -m pip install "pyencode-protector[native]==0.6.0"
/opt/homebrew/bin/python3 -m pyencode build src -o dist/app \
  --entry myapp.main \
  --obf-code 1 \
  --runtime-backend native \
  --runtime-crypto pure-python \
  --native-macos-deployment-target 11.0

By default, the Mach-O runtime receives an ad-hoc signature. Pass --native-codesign-identity 'Developer ID Application: Name (TEAMID)' to use an installed identity, and optionally pass --native-codesign-identifier to override the per-build identifier. PyEncode signs before hashing, then verifies the signature, thin architecture, MH_BUNDLE file type, exact PyInit__runtime export, and system-only dependencies. Use a full external Python to build; do not try to install Cython into Fusion's stripped embedded interpreter.

Application AOT is an independent option. Select exact, non-entry package implementation modules with --native-module; it may be repeated:

pyencode build src -o dist/app --entry myapp.main `
  --runtime-backend native `
  --native-toolchain build/native-toolchain.json `
  --native-module myapp.license_client `
  --native-module myapp.structural.geometry

The example above uses both native axes, but either can be used without the other. On Windows, --native-toolchain is required whenever --runtime-backend native or at least one --native-module is requested. A macOS runtime auto-probes Xcode and rejects this Windows descriptor; application AOT remains unavailable there.

The descriptor pins the target executable/runtime DLL/ABI, builder Python, full isolated tool tree, Zig executable, CPython headers, and import library by SHA-256 before any compiler process is launched. For an embedded host, pass the actual pythonXY.dll loaded by that host with --target-python-dll; otherwise PyEncode uses the DLL associated with the target interpreter. Creating a descriptor establishes repeatability; it does not independently prove that the initially provisioned tools were trustworthy.

The DLL hash is build-provenance metadata: descriptor verification re-hashes it before compilation. Generated applications enforce the exact Windows/64-bit/ EXT_SUFFIX ABI, but do not re-hash the host's loaded Python DLL at runtime.

Sign and key-bind additional dependencies or support trees:

pyencode build src -o dist/app \
  --entry myapp.main \
  --support build/vendor _vendor \
  --support public/config.json config.json

--support SOURCE DEST may be repeated. If SOURCE is a directory, its tree is copied below DEST; if it is a file, DEST is the output file path. Symlinks, reparse points, paths that escape the root, and case-insensitive path collisions are rejected.

The exact destination _vendor is treated as a bootstrap dependency path for hosts that do not already have cryptography installed, such as Fusion. Only the exact _vendor entry remains on sys.path while the verifier loads; every other bundle subdirectory is isolated. Because the vendored cryptography library must run before Ed25519 can verify the bundle itself, _vendor is a trusted bootstrap component by design in the default cryptography runtime. Vendor only wheels obtained from trusted sources.

For an embedded host that disallows the native extension in cryptography, do not vendor it. Build instead with the wire-compatible dependency-free backend:

pyencode build src -o dist/app --entry myapp.main \
  --runtime-crypto pure-python

This writes an empty generated requirements.txt. Both cryptographic implementations consume the same signed manifest and PYE2 AES-256-GCM artifacts, so the choice does not change the authentication algorithms or container format. Pure-Python AES and big-integer Ed25519 operations are not constant-time and decrypt more slowly.

For Fusion on macOS, prefer the native runtime when Fusion accepts the resulting signed Mach-O. The portable combination remains an explicit fallback:

pyencode build src -o dist/app --entry myapp.main \
  --obf-code 1 \
  --runtime-backend python \
  --runtime-crypto pure-python

Main options:

  • -o, --output: output directory; it must not exist or must be completely empty.
  • -e, --entry: dotted name of the entry module or package.
  • --exclude GLOB: exclude paths matching a glob; may be repeated.
  • --no-resources: do not copy non-Python files from the source tree.
  • --keep-docstrings: preserve docstrings.
  • --optimize {0,1,2}: CPython optimization level.
  • --expires YYYY-MM-DD: refuse to run after the specified UTC date.
  • --launcher PATH: use a custom .py launcher.
  • --support SOURCE DEST: copy, sign, and key-bind a support file or tree.
  • --rename-locals: rename metadata for local variables that are not parameters.
  • --obf-code {0,1}: choose module-only decryption (0, the default) or add authenticated per-function capsules and dispatch stubs (1).
  • --allow-extra-data: allow the host to create additional unsigned data files and directories; signed files and recognized Python/native artifact types remain protected. The application must not execute or trust the added data.
  • --unsigned-data PATTERN: copy matching discovered source resources only after the signed/key-bound inventory is sealed; repeat for additional globs. This requires --allow-extra-data.
  • --runtime-crypto {cryptography,pure-python}: select the portable Python runtime's cryptographic implementation. The default is cryptography; the native runtime always uses its compiled platform boundary.
  • --runtime-backend {python,native}: emit the portable Python runtime (the default), or one per-build Windows x64/macOS arm64 or x86_64 runtime extension containing the masked master-key material.
  • --native-toolchain FILE: use a canonical, hash-pinned Windows toolchain descriptor for the Windows native runtime, application AOT, or both. Do not pass it for a macOS native runtime.
  • --native-codesign-identity IDENTITY: sign a macOS runtime with this identity; the default - requests an ad-hoc signature.
  • --native-codesign-identifier IDENTIFIER: override the generated macOS code-sign identifier.
  • --native-macos-deployment-target VERSION: set the minimum macOS target; arm64 defaults to 11.0 and cannot target an older release.
  • --native-module MODULE: compile this exact dotted implementation module as a native extension; repeat for additional modules. Package __init__, entry, __main__, top-level, duplicate, missing, globbed, and non-ASCII names fail.

--rename-locals is opt-in because code that uses a dynamic alias of locals(), reads frame.f_locals, or depends on debugger/framework introspection may require the original local names. Arguments, closures, line tables, and exception tables are always preserved.

--obf-code, --optimize, --rename-locals, and --keep-docstrings govern encrypted .pye modules. Native-selected application modules use the fixed directives recorded in .pyencode-native.json (binding=False, no embedded signatures/code comments, no tracing/profile hooks, and docstrings disabled) so coverage is auditable.

Custom launchers and embedded hosts

A custom launcher is copied byte-for-byte, signed, and included in key derivation. It must set:

import sys
sys.dont_write_bytecode = True

before any non-bootstrap import. The builder enforces this minimum requirement. A secure production launcher must also verify that pyencode_runtime contains no __pycache__, .pyc, or unexpected files before importing the package. The allowed set must name the selected backend exactly: _runtime.py for the Python backend, or the generated ABI-tagged _runtime.cpXY-win_amd64.pyd/ _runtime.cpython-XY-darwin.so for the native backend. The default launcher and the Weldments pipeline include this complete preflight check.

A host such as Fusion can load an entry point without placing its plaintext module name in the stub:

import sys
sys.dont_write_bytecode = True

# Perform the pyencode_runtime preflight here.
from pyencode_runtime import load_entry

implementation = load_entry()

install() intentionally returns None. load_entry() returns the entry module to an embedding host, while run() executes the entry point with __main__ semantics.

Output layout and runtime behavior

dist/app/
├── .pyencode-manifest.json
├── .pyencode-native.json               # only with application AOT
├── .pyencode-runtime-native.json       # only with a native runtime
├── myapp/
│   ├── 14a0...f91c.pye
│   ├── 7b82...bc33.pye
│   ├── core.cp314-win_amd64.pyd        # only if selected by --native-module
│   └── assets/config.json
├── pyencode_runtime/
│   ├── __init__.py
│   ├── _build.py
│   ├── _mp_main.py
│   ├── _pure_crypto.py                 # Python backend only
│   └── _runtime.py                     # Python backend; native builds contain
│       _runtime.cp314-win_amd64.pyd    # this ABI file on Windows, or
│       _runtime.cpython-314-darwin.so  # this one on macOS (exactly one,
│                                       # with no _pure_crypto.py)
├── requirements.txt
└── run.py

The native runtime report records its pinned toolchain and generated/binary hashes. It is distinct from .pyencode-native.json, which records only application modules compiled through --native-module. Both reports are signed when present.

Resources are not encrypted, but their build-time bytes and paths are signed and key-bound. By default, the entire output tree is immutable: the runtime rejects any file or directory that is added, removed, or modified.

For hosts that create metadata or caches beside an add-in, --allow-extra-data permits additional data files and directories without invalidating the bundle. This mode still rejects modifications or removal of signed files, unexpected .py, .pyc, native libraries, or .pye files, and all symlinks or reparse points. Do not use this extra data as trusted input for licensing or security decisions. The Weldments pipeline enables this compatibility mode so Fusion can create .vscode, logs, or machine-specific caches.

Files that the application itself updates, such as user settings, host metadata, or profile libraries, must not be part of the signed source inventory. Use repeatable --unsigned-data patterns to copy their initial values safely without a separate post-build step:

pyencode build src -o dist/app --entry myapp.main \
  --allow-extra-data \
  --unsigned-data '*.png' \
  --unsigned-data 'myapp/data/settings.json'

Patterns are matched case-sensitively against the POSIX path relative to the output root and, for convenience, against the basename. Thus *.png selects PNG resources at any depth; **/*.png is also accepted and includes root-level matches. Every pattern must match at least one resource discovered in the main source tree. --unsigned-data does not apply to --support inputs, and --no-resources leaves nothing eligible for selection.

Selected files are copied into the atomic temporary output only after the signed manifest and key-bound inventory have been sealed. Their paths and bytes are absent from integrity.files, are not inputs to key derivation, and may be modified or removed by the host. The signed manifest records only the existing allow_extra_data=true compatibility policy; it deliberately does not present the patterns or selected files as trusted inputs.

The builder rejects a pattern if it selects Python source/bytecode, .pye, native libraries, executables or executable scripts, symlinks/reparse points, non-regular entries, the launcher, pyencode_runtime, either generated manifest/report, or requirements.txt. Added unsigned files are still scanned at runtime: recognized code/native artifacts and every link/reparse point remain forbidden. Never execute or use unsigned data for licensing, integrity, or other security decisions.

The __file__ value of a protected module is the real path to its randomly named artifact. Consequently, Path(__file__).parent, pkgutil.get_data(), and importlib.resources, including nested directory resources, continue to work. Code that depends on the basename or stem of __file__ sees the random token.

Integration tests cover imports by full name, relative imports, circular imports, namespace packages, Unicode module names, reloads, runpy.run_module(), and multiprocessing spawn for applications launched through the default launcher. pkgutil.iter_modules() and walk_packages() cannot automatically discover protected child names because those names intentionally reside in the encrypted index; importing a known full name still works.

For an embedding host that calls load_entry(), spawning works if the child process also runs the host bootstrap. A host that places its bootstrap only inside if __name__ == '__main__' and then directly spawns a protected target requires a dedicated launcher. Automatic spawn bootstrapping currently focuses on applications executed through run().

Version 0.6 uses one fixed runtime namespace per process. Do not load two independent PyEncode distributions into the same interpreter; run them in separate processes. Randomized or multi-bundle runtime namespaces are a compatibility item to resolve before declaring a stable 1.0 API.

Security limitations

PyEncode makes static analysis harder, but it cannot guarantee secrecy on a machine fully controlled by an attacker:

  • The default mode is offline, so key material must remain in the bundle. An experienced analyst can inspect the Python runtime and reproduce key derivation. The native runtime removes the readable Python key reconstruction and embeds masked per-build material in a .pyd or .so; its long-lived function key is held in a private C buffer rather than a Python attribute. Binary analysis, native memory inspection, or a debugger can still recover these values.
  • Code objects must exist in memory while they execute. Tracing, debuggers, memory inspection, code-object watchers, or native hooks may still observe code and runtime state. The native codec avoids the ordinary marshal, code.__new__, and function.__new__ audit paths, but this does not make it debugger- or PyCode_AddWatcher-proof.
  • At --obf-code 1, the original code for protected top-level functions is not present in the module code object at rest, and normal function.__code__ inspection sees a generic stub. The real CodeType is nevertheless materialized for execution. A suspended generator/coroutine retains an executing frame, and an attacker who controls the process can inspect or intercept it. This option raises extraction cost; it is not a confidentiality boundary.
  • The integrity interlock prevents straightforward file modification, artifact substitution, code injection, and re-signing. It does not turn a pure-Python runtime into a native trust anchor. A native runtime is a stronger obfuscation boundary, not a hardware-backed trust anchor.
  • Module and entry-point names are hidden at rest, but appear during import in sys.modules, tracebacks, and runtime state. Package and resource directories may still reveal part of the application structure.
  • --expires relies on the system clock and is not a replacement for a licensing system.
  • Native-selected modules no longer expose a marshal-loadable application code object through the PyEncode runtime, but Cython binaries still reveal useful names, strings, metadata, and machine code to a skilled reverse engineer.
  • Native runtime and application extensions remain patchable in a process fully controlled by an attacker. The signed finder raises the cost of preload, path-shadow, and file-tamper attacks; it is not an unpatchable hardware trust anchor or a guarantee of equivalence to PyArmor level 1 or every PyArmor configuration. The products use different runtimes and should be compared with repeatable attacks against the exact builds, not by matching option names.
  • The native runtime is loaded before it can verify its own signed inventory. Its manifest hash detects accidental corruption and inconsistent replacement, but is not an operating-system trust anchor. PyEncode signs the macOS .so before it computes the runtime report and key-bound inventory. Windows Authenticode must likewise be applied before those hashes; changing either binary after a build invalidates that build. A valid ad-hoc signature does not by itself override an embedding host's macOS library-validation policy.
  • The native CodeType record uses CPython's C pickle implementation only after the signed artifact hash and AES-GCM tag have been verified. Its schema checks are for trusted build output; it is not a general-purpose decoder for untrusted pickle data.
  • Native files are re-hashed immediately before CPython loads them, but the hash and operating-system loader open are not one atomic operation. An attacker that already controls the process or filesystem may still exploit that narrow replacement window.

Never store long-lived API keys or private keys in a client. For high-value products, the security upgrade that makes the greatest practical difference is an external or envelope key obtained from a license server or platform key store. A native runtime and --obf-code 1 primarily add reverse-engineering cost.

Testing

python -m unittest discover -v

CI runs on Windows and Ubuntu with CPython 3.10 through 3.15, plus macOS CPython 3.14 portable- and native-runtime jobs. Portable tests cover PYE2, the encrypted module index, KDF vectors, tampering and re-signing, resource/support integrity, opaque filenames, imports, packages, namespaces, Unicode, runpy, multiprocessing spawn, ordinary launchers without -B, expiration policy, and atomic output creation. Level-1 tests cover build-time function capsules, ordinary functions and methods, lambdas, closures, generators, coroutines, call behavior, and the idle dispatch-stub invariant.

The Windows native suite additionally covers the per-build runtime and application AOT independently, exact-module selection, canonical toolchain descriptors and tampering, PE architecture/export/import/hardening checks, signed native reports, extension loading, preload rejection, and runtime tamper.

The macOS native job compiles, signs, inspects, imports, and runs a real Mach-O runtime. It checks the architecture, MH_BUNDLE type, exact export, system-only dependencies, signature, report format, and signed application behavior.

Releasing

The production release process using GitHub OIDC is documented in RELEASING.md. The workflow uploads to PyPI only when a pushed tag exactly matches the project version, for example v0.6.0.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pyencode_protector-0.6.0.tar.gz (197.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pyencode_protector-0.6.0-py3-none-any.whl (144.0 kB view details)

Uploaded Python 3

File details

Details for the file pyencode_protector-0.6.0.tar.gz.

File metadata

  • Download URL: pyencode_protector-0.6.0.tar.gz
  • Upload date:
  • Size: 197.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for pyencode_protector-0.6.0.tar.gz
Algorithm Hash digest
SHA256 49f7b571ba3d4f4527ce64e5c6bcd8ad8924bd93f96ec4aa7504573ebef26acf
MD5 5cae39b6bb5e96d8594c05d6e9662104
BLAKE2b-256 7c2b0629c1c0d0166e8aa508dea2ee10c7d1e86eeff0eeb6134f4a28ac5520c9

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyencode_protector-0.6.0.tar.gz:

Publisher: release.yml on VanThanBK/pyencode

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pyencode_protector-0.6.0-py3-none-any.whl.

File metadata

File hashes

Hashes for pyencode_protector-0.6.0-py3-none-any.whl
Algorithm Hash digest
SHA256 a8edf14b37ef587c0b9730c37e43e6af63fe7d88a08300b9be374ac04a4b7b44
MD5 7122b5935c41ea63ca0695ef9a12c2f8
BLAKE2b-256 ab2c75cce522003ad873cf515bfa64000f282eb383f128ce9b39d1422599994f

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyencode_protector-0.6.0-py3-none-any.whl:

Publisher: release.yml on VanThanBK/pyencode

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

0.7.1

2 files

0.7.0

2 files

0.6.1

2 files

This release

0.6.0 This release

2 files

0.5.0

2 files

0.3.1

2 files

0.3.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page