Skip to main content

Tool bao ve source code module Odoo theo huong an toan.

Project description

jProtect

Protect your Odoo module's business logic by extracting method bodies into compiled binaries (.so/.pyd) โ€” the module still installs and runs normally on Odoo.

PyPI version Python License: PolyForm NC


๐Ÿ”’ What It Does

jProtect takes an Odoo module and:

  1. Keeps the public file intact โ€” class definitions, fields, decorators, and _name/_inherit stay in place so Odoo registers the model normally.
  2. Extracts method bodies into a hidden models/_protected/ package as standalone functions.
  3. Replaces each method body with a thin delegation call to _protected.
  4. Compiles _protected/ into .so/.pyd binaries (optional --compile flag).

The result: a module that looks and behaves exactly like the original โ€” but the business logic is gone from the source files.


โœจ Features

  • ๐Ÿ” Dry-run mode โ€” preview what will be protected before writing anything
  • โš™๏ธ Selective protection โ€” include/exclude files with glob patterns
  • ๐Ÿš€ Cython compilation โ€” compile protected code to native binaries
  • ๐Ÿ”„ super() rewriting โ€” zero-arg super() is automatically rewritten to super(cls, self) so inheritance chains keep working
  • ๐Ÿ›ก๏ธ Safe by default โ€” skips dunders, @property, generators, __init__.py, migrations, and any pattern that could break Odoo

๐Ÿ“ฆ Installation

Requires Python 3.10+. Cython is installed automatically.

pip install jprotect

When using --compile, a C compiler is also required:

  • Linux: gcc + python3-dev
  • Windows: MSVC Build Tools

๐Ÿš€ Quick Start

Given a module at ./addons/sale_ext:

# Step 1 โ€” Preview (no files written)
jprotect protect-module \
  --input ./addons/sale_ext \
  --output ./dist/dist/sale_ext \
  --dry-run

# Step 2 โ€” Protect (extract logic, no compile)
jprotect protect-module \
  --input ./addons/sale_ext \
  --output ./dist/dist/sale_ext

# Step 3 โ€” Protect + compile to binary
jprotect protect-module \
  --input ./addons/sale_ext \
  --output ./dist/dist/sale_ext \
  --compile

After running, jProtect generates a protection-manifest.json in the output directory listing every processed file.


๐Ÿ” How It Works

# โ”€โ”€ Original file โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
class SaleOrder(models.Model):
    _inherit = 'sale.order'

    def action_confirm(self):
        # your business logic here...
        return super().action_confirm()


# โ”€โ”€ Public file after jProtect โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
from . import _protected

class SaleOrder(models.Model):
    _inherit = 'sale.order'

    def action_confirm(self):
        return _protected.sale_order.SaleOrder__action_confirm(self, SaleOrder)


# โ”€โ”€ _protected/sale_order.py (or .so after --compile) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
def SaleOrder__action_confirm(self, cls):
    # your business logic here...
    return super(cls, self).action_confirm()

Odoo sees the same class structure and registers the model exactly as before. The logic only lives inside the compiled binary.


โš™๏ธ CLI Reference

jprotect protect-module --input <dir> --output <dir> [options]
Option Description Example
--input Odoo module directory (must contain __manifest__.py) --input ./addons/sale_ext
--output Output directory --output ./dist/dist/sale_ext
--mode dist creates a copy (default); inplace modifies in place --mode inplace
--dry-run Scan and report only, no files written --dry-run
--compile Compile _protected/ to .so/.pyd --compile
--include Glob pattern for files to protect (repeatable, default: models/**/*.py) --include "models/**/*.py" --include "utils/*.py"
--exclude Glob pattern for files to exclude (repeatable) --exclude "models/res_*.py"

๐Ÿณ Docker

Build once, run anywhere โ€” useful for compiling binaries that match your Odoo server environment:

docker build -t jprotect .

docker run --rm \
  -v "$PWD/addons/sale_ext:/work/input:ro" \
  -v "$PWD/dist:/work/output" \
  jprotect protect-module \
    --input /work/input \
    --output /work/output/dist/sale_ext \
    --compile

โš ๏ธ Important Notes

Binaries are environment-specific. A .so/.pyd file only runs on the exact Python version + OS + CPU architecture it was compiled on. You must build on an environment that matches your Odoo server.

Odoo Version Python
16, 17, 18 3.10
14, 15 3.8

Always test on staging first. Install and upgrade the protected module on a staging Odoo database and run through the main flows before going to production.


๐Ÿ›ก๏ธ What Gets Protected

jProtect protects regular instance methods only. The following are intentionally left untouched:

Skipped Reason
@staticmethod, @classmethod, @property Different call semantics, cannot be safely delegated
Property setters/deleters (@x.setter, @x.deleter) Setter return values are ignored by Python; wrapping changes semantics
Dunder methods (__init__, __str__, ...) Called directly by Odoo/Python internals
Generator methods (contain yield) Extracting a generator body breaks the iterator protocol
Methods with super() inside nested functions super() without args relies on the declaring scope's __class__ cell
__init__.py, migrations/, controllers/ Breaking these would prevent Odoo from loading the module

๐Ÿ› ๏ธ Development

Setup

git clone https://github.com/your-org/jprotect.git
cd jprotect

python -m venv .venv
source .venv/bin/activate  # Windows: .venv\Scripts\activate

pip install -e ".[test]"

Run tests

pytest -q                          # all tests
pytest tests/unit/ -q              # unit tests only
pytest tests/integration/ -q       # integration tests only
pytest tests/unit/test_ast_transformer.py -v  # specific file

Project structure

src/jprotect/
โ”œโ”€โ”€ cli/            # CLI entry point (argparse)
โ”œโ”€โ”€ config/         # Config schema and loader
โ”œโ”€โ”€ core/
โ”‚   โ”œโ”€โ”€ compile/    # Cython backend
โ”‚   โ”œโ”€โ”€ transform/  # Core AST transformation logic
โ”‚   โ”‚   โ”œโ”€โ”€ ast_transformer.py   # parse, extract, build delegation
โ”‚   โ”‚   โ””โ”€โ”€ transformer.py       # orchestrate transform over directory tree
โ”‚   โ”œโ”€โ”€ pipeline.py
โ”‚   โ””โ”€โ”€ ...
โ””โ”€โ”€ errors.py

tests/
โ”œโ”€โ”€ unit/           # per-function tests with real source strings
โ””โ”€โ”€ integration/    # full pipeline tests on a fixture Odoo module

See docs/CODE_CONVENTIONS.md for coding conventions.


๐Ÿ“„ License

PolyForm Noncommercial 1.0.0 โ€” free for personal and noncommercial use. Commercial use requires a separate license from the author. See LICENSE.

Project details


Download files

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

Source Distribution

jprotect-0.1.0.tar.gz (25.5 kB view details)

Uploaded Source

Built Distribution

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

jprotect-0.1.0-py3-none-any.whl (27.9 kB view details)

Uploaded Python 3

File details

Details for the file jprotect-0.1.0.tar.gz.

File metadata

  • Download URL: jprotect-0.1.0.tar.gz
  • Upload date:
  • Size: 25.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.12

File hashes

Hashes for jprotect-0.1.0.tar.gz
Algorithm Hash digest
SHA256 a4c1b827acdf1c597f1c5eb80dda605c7bf8b1239256684d1da6078b40485866
MD5 2c15c71d721d957941dee24d68809116
BLAKE2b-256 7585a660b10430b18956e029f7e0ad63e34b0904e8602fc7b2442f9a55a9bf7f

See more details on using hashes here.

File details

Details for the file jprotect-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: jprotect-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 27.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.12

File hashes

Hashes for jprotect-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 ea387d7e18a6e9d345e414ae7820464080518358e1328f074f5b7a13750a1d05
MD5 2b821efb5a236205b86fd60a666f36a6
BLAKE2b-256 670b0b1d24d200e748d0d4a12267bc7fb0e1ddb14dd43036021c8a86f9990e54

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page