tabayyan 0.5.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (80) hide show
  1. tabayyan-0.5.1/.dockerignore +9 -0
  2. tabayyan-0.5.1/.github/workflows/docs.yml +19 -0
  3. tabayyan-0.5.1/.github/workflows/release.yml +36 -0
  4. tabayyan-0.5.1/.github/workflows/tests.yml +36 -0
  5. tabayyan-0.5.1/.gitignore +16 -0
  6. tabayyan-0.5.1/.pre-commit-config.yaml +14 -0
  7. tabayyan-0.5.1/.pre-commit-hooks.yaml +6 -0
  8. tabayyan-0.5.1/CHANGELOG.md +75 -0
  9. tabayyan-0.5.1/CODE_OF_CONDUCT.md +6 -0
  10. tabayyan-0.5.1/CONTRIBUTING.md +29 -0
  11. tabayyan-0.5.1/Dockerfile +14 -0
  12. tabayyan-0.5.1/LICENSE +143 -0
  13. tabayyan-0.5.1/Makefile +23 -0
  14. tabayyan-0.5.1/PKG-INFO +329 -0
  15. tabayyan-0.5.1/README.ar.md +91 -0
  16. tabayyan-0.5.1/README.md +302 -0
  17. tabayyan-0.5.1/REFERENCES.md +60 -0
  18. tabayyan-0.5.1/SECURITY.md +24 -0
  19. tabayyan-0.5.1/benchmarks/RECALL.md +23 -0
  20. tabayyan-0.5.1/benchmarks/RESULTS.md +24 -0
  21. tabayyan-0.5.1/benchmarks/perf.py +51 -0
  22. tabayyan-0.5.1/benchmarks/recall.py +158 -0
  23. tabayyan-0.5.1/benchmarks/run.py +173 -0
  24. tabayyan-0.5.1/docs/benchmarks.md +14 -0
  25. tabayyan-0.5.1/docs/cli.md +10 -0
  26. tabayyan-0.5.1/docs/config.md +36 -0
  27. tabayyan-0.5.1/docs/detectors.md +17 -0
  28. tabayyan-0.5.1/docs/faq.md +44 -0
  29. tabayyan-0.5.1/docs/index.md +15 -0
  30. tabayyan-0.5.1/docs/middleware.md +59 -0
  31. tabayyan-0.5.1/docs/presidio.md +30 -0
  32. tabayyan-0.5.1/docs/showcase.md +33 -0
  33. tabayyan-0.5.1/docs/threat-model.md +37 -0
  34. tabayyan-0.5.1/examples/basic_scan.py +24 -0
  35. tabayyan-0.5.1/examples/showcase.py +42 -0
  36. tabayyan-0.5.1/examples/tabayyan_demo.ipynb +122 -0
  37. tabayyan-0.5.1/mkdocs.yml +18 -0
  38. tabayyan-0.5.1/publish.sh +129 -0
  39. tabayyan-0.5.1/pyproject.toml +44 -0
  40. tabayyan-0.5.1/src/tabayyan/__init__.py +46 -0
  41. tabayyan-0.5.1/src/tabayyan/checksums.py +82 -0
  42. tabayyan-0.5.1/src/tabayyan/cli.py +220 -0
  43. tabayyan-0.5.1/src/tabayyan/config.py +92 -0
  44. tabayyan-0.5.1/src/tabayyan/confusables.py +99 -0
  45. tabayyan-0.5.1/src/tabayyan/detectors/__init__.py +12 -0
  46. tabayyan-0.5.1/src/tabayyan/detectors/base.py +15 -0
  47. tabayyan-0.5.1/src/tabayyan/detectors/domains.py +37 -0
  48. tabayyan-0.5.1/src/tabayyan/detectors/generic.py +50 -0
  49. tabayyan-0.5.1/src/tabayyan/detectors/names.py +94 -0
  50. tabayyan-0.5.1/src/tabayyan/detectors/saudi.py +114 -0
  51. tabayyan-0.5.1/src/tabayyan/engine.py +50 -0
  52. tabayyan-0.5.1/src/tabayyan/entities.py +71 -0
  53. tabayyan-0.5.1/src/tabayyan/homoglyph.py +166 -0
  54. tabayyan-0.5.1/src/tabayyan/integrations/__init__.py +4 -0
  55. tabayyan-0.5.1/src/tabayyan/integrations/presidio.py +132 -0
  56. tabayyan-0.5.1/src/tabayyan/middleware.py +281 -0
  57. tabayyan-0.5.1/src/tabayyan/redaction.py +166 -0
  58. tabayyan-0.5.1/src/tabayyan/streaming.py +72 -0
  59. tabayyan-0.5.1/tests/__init__.py +0 -0
  60. tabayyan-0.5.1/tests/synthetic.py +42 -0
  61. tabayyan-0.5.1/tests/test_checksums.py +54 -0
  62. tabayyan-0.5.1/tests/test_cli.py +71 -0
  63. tabayyan-0.5.1/tests/test_cli_domains.py +38 -0
  64. tabayyan-0.5.1/tests/test_config.py +38 -0
  65. tabayyan-0.5.1/tests/test_cross_validation.py +57 -0
  66. tabayyan-0.5.1/tests/test_cross_validation_stdnum.py +53 -0
  67. tabayyan-0.5.1/tests/test_engine.py +27 -0
  68. tabayyan-0.5.1/tests/test_generic.py +32 -0
  69. tabayyan-0.5.1/tests/test_golden_cards.py +39 -0
  70. tabayyan-0.5.1/tests/test_golden_iban.py +41 -0
  71. tabayyan-0.5.1/tests/test_golden_vectors.py +42 -0
  72. tabayyan-0.5.1/tests/test_homoglyph.py +74 -0
  73. tabayyan-0.5.1/tests/test_middleware.py +195 -0
  74. tabayyan-0.5.1/tests/test_names.py +32 -0
  75. tabayyan-0.5.1/tests/test_presidio_integration.py +100 -0
  76. tabayyan-0.5.1/tests/test_recall.py +31 -0
  77. tabayyan-0.5.1/tests/test_redaction.py +76 -0
  78. tabayyan-0.5.1/tests/test_saudi.py +76 -0
  79. tabayyan-0.5.1/tests/test_streaming.py +55 -0
  80. tabayyan-0.5.1/tests/test_tokenize.py +38 -0
@@ -0,0 +1,9 @@
1
+ tests/
2
+ benchmarks/
3
+ docs/
4
+ .github/
5
+ .git/
6
+ __pycache__/
7
+ *.pyc
8
+ .ruff_cache/
9
+ .pytest_cache/
@@ -0,0 +1,19 @@
1
+ name: docs
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+
7
+ permissions:
8
+ contents: write
9
+
10
+ jobs:
11
+ deploy:
12
+ runs-on: ubuntu-latest
13
+ steps:
14
+ - uses: actions/checkout@v4
15
+ - uses: actions/setup-python@v5
16
+ with:
17
+ python-version: "3.12"
18
+ - run: pip install mkdocs-material
19
+ - run: mkdocs gh-deploy --force
@@ -0,0 +1,36 @@
1
+ name: release
2
+
3
+ on:
4
+ push:
5
+ tags: ["v*"]
6
+
7
+ permissions:
8
+ contents: read
9
+
10
+ jobs:
11
+ build:
12
+ runs-on: ubuntu-latest
13
+ steps:
14
+ - uses: actions/checkout@v4
15
+ - uses: actions/setup-python@v5
16
+ with:
17
+ python-version: "3.12"
18
+ - run: pip install build
19
+ - run: python -m build
20
+ - uses: actions/upload-artifact@v4
21
+ with:
22
+ name: dist
23
+ path: dist/
24
+
25
+ publish:
26
+ needs: build
27
+ runs-on: ubuntu-latest
28
+ environment: pypi
29
+ permissions:
30
+ id-token: write # OIDC trusted publishing — no API token needed
31
+ steps:
32
+ - uses: actions/download-artifact@v4
33
+ with:
34
+ name: dist
35
+ path: dist/
36
+ - uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,36 @@
1
+ name: tests
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+
8
+ jobs:
9
+ test:
10
+ runs-on: ubuntu-latest
11
+ strategy:
12
+ matrix:
13
+ python-version: ["3.9", "3.11", "3.13"]
14
+ steps:
15
+ - uses: actions/checkout@v4
16
+ - uses: actions/setup-python@v5
17
+ with:
18
+ python-version: ${{ matrix.python-version }}
19
+ - name: Install
20
+ run: pip install -e ".[dev]"
21
+ - name: Lint
22
+ run: ruff check .
23
+ - name: Test
24
+ run: pytest -q
25
+
26
+ integration:
27
+ runs-on: ubuntu-latest
28
+ steps:
29
+ - uses: actions/checkout@v4
30
+ - uses: actions/setup-python@v5
31
+ with:
32
+ python-version: "3.12"
33
+ - name: Install with Presidio extra
34
+ run: pip install -e ".[dev,presidio]"
35
+ - name: Run integration tests
36
+ run: pytest tests/test_presidio_integration.py -q
@@ -0,0 +1,16 @@
1
+ __pycache__/
2
+ *.py[cod]
3
+ *.egg-info/
4
+ .eggs/
5
+ build/
6
+ dist/
7
+ .venv/
8
+ venv/
9
+ .env
10
+ .pytest_cache/
11
+ .ruff_cache/
12
+ .coverage
13
+ htmlcov/
14
+ .idea/
15
+ .vscode/
16
+ .DS_Store
@@ -0,0 +1,14 @@
1
+ repos:
2
+ - repo: https://github.com/astral-sh/ruff-pre-commit
3
+ rev: v0.6.9
4
+ hooks:
5
+ - id: ruff
6
+ # Use Tabayyan itself to block accidental PII in commits:
7
+ - repo: local
8
+ hooks:
9
+ - id: tabayyan
10
+ name: tabayyan PII scan
11
+ entry: tabayyan scan --fail-on-find --min-confidence high
12
+ language: system
13
+ types: [text]
14
+ exclude: '^(tests/|benchmarks/|docs/)'
@@ -0,0 +1,6 @@
1
+ - id: tabayyan
2
+ name: tabayyan (Saudi PII scan)
3
+ description: Fail the commit if Saudi/PII entities are found in staged text.
4
+ entry: tabayyan scan --fail-on-find
5
+ language: python
6
+ types: [text]
@@ -0,0 +1,75 @@
1
+ # Changelog
2
+
3
+ ## 0.5.1
4
+ - **Fix:** Arabic comma (U+060C) and other Arabic punctuation no longer
5
+ corrupt Arabic-name tokenization (tightened the letter range).
6
+ - **Fix:** tokenize/restore now reproduces the original span exactly,
7
+ including Arabic-Indic digits (vault stores the source span, not the
8
+ normalized value).
9
+ - **Middleware hardening:** `protect_messages()` building block; handles
10
+ multimodal/list content, system/tool roles, and streaming (request
11
+ redacted, stream passed through). Honest 'reference adapter' disclaimer.
12
+ - **Recall benchmark** (`benchmarks/recall.py`): recall under formatting
13
+ noise + an honest context-free section exposing heuristic limits.
14
+ - **Arabic README**, before/after showcase, and an interactive notebook.
15
+ - Broadened MRN trigger phrasing (recall 0.69 -> 1.0 with context).
16
+
17
+ ## 0.5.0
18
+ - **Middleware + audit** (`Guard`, `AuditLog`): scan -> redact/block -> audit
19
+ before a prompt leaves for an LLM endpoint. Cross-border transfer flagging
20
+ (PDPL Art. 29), category-aware blocking, JSONL audit (values withheld by
21
+ default), and a duck-typed OpenAI/Azure wrapper with tokenize-restore.
22
+ - **Presidio integration** (`tabayyan[presidio]`): validated Saudi/Arabic
23
+ recognizers (SA_NATIONAL_ID, SA_IQAMA, SA_IBAN, SA_CR, SA_PHONE_NUMBER,
24
+ MEDICAL_RECORD_NUMBER, PERSON, lookalike domains). Complements Presidio;
25
+ parity-tested against the standalone engine. Runtime core stays zero-dep.
26
+ - Name detector: added field-label stopwords (الهوية، الآيبان، …) for tighter
27
+ boundaries in record-style text.
28
+
29
+ ## 0.4.2
30
+ - **IBAN & Luhn cross-validation**: differential tests against
31
+ `python-stdnum` (dev-only oracle) — Luhn over 20k random samples, IBAN
32
+ over 12k generated Saudi IBANs + mutations.
33
+ - **Golden vectors**: official card-network test PANs (Visa, Mastercard,
34
+ Amex, Discover, JCB, Diners) and canonical public example IBANs
35
+ (SA/GB/DE/FR). Runtime stays zero-dependency.
36
+
37
+ ## 0.4.1
38
+ - **National ID cross-validation**: validator differentially tested against
39
+ the community reference alhazmy13/Saudi-ID-Validator (MIT; algorithm by
40
+ Abdul-Aziz Al-Oraij) — 100% agreement on a 50k+ random sample. Updated
41
+ REFERENCES.md and the checksum disclaimer accordingly.
42
+
43
+ ## 0.4.0
44
+ - **Arabic name detection** (heuristic, context-gated, LOW confidence) — new
45
+ PERSON category; improves recall on health-sector PII.
46
+ - **Streaming** large-file scan with overlap windows (`tabayyan scan --stream`,
47
+ `tabayyan.streaming.scan_file`).
48
+ - **Reversible tokenize** redaction mode + `restore()` and a token vault.
49
+ - **Config** (`--config`, `tabayyan.config.Config`): disable/add detectors,
50
+ custom regex detectors with labels, extend confusables, tune thresholds.
51
+ - **Performance**: rewrote overlap resolution from O(n^2) to O(n log n)
52
+ (~110x faster on dense input). Added `benchmarks/perf.py`.
53
+ - **Docs**: REFERENCES.md (algorithm provenance), FAQ, threat model, config.
54
+ - Golden-vector tests; National ID disclaimer clarifying it is the
55
+ community algorithm, not an authoritative spec.
56
+
57
+ ## 0.3.0
58
+ - **Homoglyph / lookalike-domain detection** (opt-in): IDN homograph
59
+ impersonation via confusable skeletons, mixed-script labels
60
+ (incl. Arabic+Latin), and edit-distance typosquats against a watchlist.
61
+ Punycode (`xn--`) labels decoded before analysis. New `tabayyan domains`
62
+ CLI command.
63
+ - **Benchmark suite** (`benchmarks/run.py`): precision/recall/F1 on a
64
+ synthetic corpus with hard negatives, plus a naive-regex baseline that
65
+ quantifies the false positives checksum validation eliminates.
66
+ - **Adoption**: Dockerfile, pre-commit hook, PyPI release workflow (OIDC
67
+ trusted publishing), MkDocs docs, Makefile.
68
+
69
+ ## 0.2.0
70
+ - Redaction engine: mask / remove / hash / partial.
71
+ - CLI: `scan` and `redact` with stdin/file/dir input, filters, JSON, exit codes.
72
+
73
+ ## 0.1.0
74
+ - Detection core: Saudi (National ID, Iqama, IBAN, CR, mobile, MRN) +
75
+ generic (email, credit card, IP) detectors with checksum validation.
@@ -0,0 +1,6 @@
1
+ # Code of Conduct
2
+
3
+ This project follows the [Contributor Covenant](https://www.contributor-covenant.org/),
4
+ version 2.1. Be respectful, assume good faith, and keep discussion focused on
5
+ the work. Unacceptable behaviour may be reported to the maintainers via a
6
+ private channel; maintainers will respond as promptly as circumstances allow.
@@ -0,0 +1,29 @@
1
+ # Contributing
2
+
3
+ Thanks for your interest in improving Tabayyan.
4
+
5
+ ## Ground rules
6
+
7
+ 1. **No real data, ever.** All fixtures must be synthetic and generated in
8
+ `tests/synthetic.py`. PRs containing real National IDs, IBANs, MRNs, or
9
+ any other real personal data will be rejected.
10
+ 2. **Keep the core offline.** The detection engine must not introduce network
11
+ calls or non-stdlib runtime dependencies. Optional enrichment belongs in a
12
+ separate, opt-in module.
13
+ 3. **Be honest about confidence.** A new detector must state HIGH / MEDIUM /
14
+ LOW honestly. HIGH is reserved for checksum-backed types.
15
+
16
+ ## Adding a detector
17
+
18
+ 1. Subclass `Detector` in `src/tabayyan/detectors/`.
19
+ 2. Return `Match` objects with correct `category` and `confidence`.
20
+ 3. Register it in `detectors/__init__.py`.
21
+ 4. Add round-trip tests (valid detected, invalid rejected) using synthetic data.
22
+
23
+ ## Dev setup
24
+
25
+ ```bash
26
+ pip install -e ".[dev]"
27
+ pytest -q
28
+ ruff check .
29
+ ```
@@ -0,0 +1,14 @@
1
+ # Minimal image: no third-party runtime deps, CLI as entrypoint.
2
+ FROM python:3.12-slim AS base
3
+
4
+ WORKDIR /app
5
+ COPY pyproject.toml README.md LICENSE ./
6
+ COPY src ./src
7
+ RUN pip install --no-cache-dir .
8
+
9
+ # Run as non-root.
10
+ RUN useradd --create-home --uid 10001 tabayyan
11
+ USER tabayyan
12
+
13
+ ENTRYPOINT ["tabayyan"]
14
+ CMD ["--help"]
tabayyan-0.5.1/LICENSE ADDED
@@ -0,0 +1,143 @@
1
+ Apache License
2
+ Version 2.0, January 2004
3
+ http://www.apache.org/licenses/
4
+
5
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
+
7
+ 1. Definitions.
8
+
9
+ "License" shall mean the terms and conditions for use, reproduction,
10
+ and distribution as defined by Sections 1 through 9 of this document.
11
+
12
+ "Licensor" shall mean the copyright owner or entity authorized by
13
+ the copyright owner that is granting the License.
14
+
15
+ "Legal Entity" shall mean the union of the acting entity and all
16
+ other entities that control, are controlled by, or are under common
17
+ control with that entity. For the purposes of this definition,
18
+ "control" means (i) the power, direct or indirect, to cause the
19
+ direction or management of such entity, whether by contract or
20
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
21
+ outstanding shares, or (iii) beneficial ownership of such entity.
22
+
23
+ "You" (or "Your") shall mean an individual or Legal Entity
24
+ exercising permissions granted by this License.
25
+
26
+ "Source" form shall mean the preferred form for making modifications,
27
+ including but not limited to software source code, documentation
28
+ source, and configuration files.
29
+
30
+ "Object" form shall mean any form resulting from mechanical
31
+ transformation or translation of a Source form, including but not
32
+ limited to compiled object code, generated documentation, and
33
+ conversions to other media types.
34
+
35
+ "Work" shall mean the work of authorship, whether in Source or
36
+ Object form, made available under the License, as indicated by a
37
+ copyright notice that is included in or attached to the work.
38
+
39
+ "Derivative Works" shall mean any work, whether in Source or Object
40
+ form, that is based on (or derived from) the Work and for which the
41
+ editorial revisions, annotations, elaborations, or other modifications
42
+ represent, as a whole, an original work of authorship.
43
+
44
+ "Contribution" shall mean any work of authorship, including the
45
+ original version of the Work and any modifications or additions
46
+ to that Work or Derivative Works thereof, that is intentionally
47
+ submitted to Licensor for inclusion in the Work.
48
+
49
+ "Contributor" shall mean Licensor and any individual or Legal Entity
50
+ on behalf of whom a Contribution has been received by Licensor and
51
+ subsequently incorporated within the Work.
52
+
53
+ 2. Grant of Copyright License. Subject to the terms and conditions of
54
+ this License, each Contributor hereby grants to You a perpetual,
55
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
56
+ copyright license to reproduce, prepare Derivative Works of,
57
+ publicly display, publicly perform, sublicense, and distribute the
58
+ Work and such Derivative Works in Source or Object form.
59
+
60
+ 3. Grant of Patent License. Subject to the terms and conditions of
61
+ this License, each Contributor hereby grants to You a perpetual,
62
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
63
+ (except as stated in this section) patent license to make, have
64
+ made, use, offer to sell, sell, import, and otherwise transfer the
65
+ Work, where such license applies only to those patent claims
66
+ licensable by such Contributor that are necessarily infringed by
67
+ their Contribution(s) alone or by combination of their
68
+ Contribution(s) with the Work to which such Contribution(s) was
69
+ submitted. If You institute patent litigation against any entity
70
+ (including a cross-claim or counterclaim in a lawsuit) alleging
71
+ that the Work or a Contribution incorporated within the Work
72
+ constitutes direct or contributory patent infringement, then any
73
+ patent licenses granted to You under this License for that Work
74
+ shall terminate as of the date such litigation is filed.
75
+
76
+ 4. Redistribution. You may reproduce and distribute copies of the
77
+ Work or Derivative Works thereof in any medium, with or without
78
+ modifications, and in Source or Object form, provided that You
79
+ meet the following conditions:
80
+
81
+ (a) You must give any other recipients of the Work or Derivative
82
+ Works a copy of this License; and
83
+ (b) You must cause any modified files to carry prominent notices
84
+ stating that You changed the files; and
85
+ (c) You must retain, in the Source form of any Derivative Works
86
+ that You distribute, all copyright, patent, trademark, and
87
+ attribution notices from the Source form of the Work; and
88
+ (d) If the Work includes a "NOTICE" text file as part of its
89
+ distribution, then any Derivative Works that You distribute
90
+ must include a readable copy of the attribution notices
91
+ contained within such NOTICE file.
92
+
93
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
94
+ any Contribution intentionally submitted for inclusion in the Work
95
+ by You to the Licensor shall be under the terms and conditions of
96
+ this License, without any additional terms or conditions.
97
+
98
+ 6. Trademarks. This License does not grant permission to use the trade
99
+ names, trademarks, service marks, or product names of the Licensor,
100
+ except as required for reasonable and customary use in describing
101
+ the origin of the Work and reproducing the content of the NOTICE file.
102
+
103
+ 7. Disclaimer of Warranty. Unless required by applicable law or agreed
104
+ to in writing, Licensor provides the Work (and each Contributor
105
+ provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES
106
+ OR CONDITIONS OF ANY KIND, either express or implied, including,
107
+ without limitation, any warranties or conditions of TITLE,
108
+ NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR
109
+ PURPOSE. You are solely responsible for determining the
110
+ appropriateness of using or redistributing the Work.
111
+
112
+ 8. Limitation of Liability. In no event and under no legal theory,
113
+ whether in tort (including negligence), contract, or otherwise,
114
+ unless required by applicable law (such as deliberate and grossly
115
+ negligent acts) or agreed to in writing, shall any Contributor be
116
+ liable to You for damages, including any direct, indirect, special,
117
+ incidental, or consequential damages of any character arising as a
118
+ result of this License or out of the use or inability to use the
119
+ Work.
120
+
121
+ 9. Accepting Warranty or Additional Liability. While redistributing
122
+ the Work or Derivative Works thereof, You may choose to offer,
123
+ and charge a fee for, acceptance of support, warranty, indemnity,
124
+ or other liability obligations and/or rights consistent with this
125
+ License. However, in accepting such obligations, You may act only
126
+ on Your own behalf and on Your sole responsibility, not on behalf
127
+ of any other Contributor.
128
+
129
+ END OF TERMS AND CONDITIONS
130
+
131
+ Copyright 2026 Tabayyan contributors
132
+
133
+ Licensed under the Apache License, Version 2.0 (the "License");
134
+ you may not use this file except in compliance with the License.
135
+ You may obtain a copy of the License at
136
+
137
+ http://www.apache.org/licenses/LICENSE-2.0
138
+
139
+ Unless required by applicable law or agreed to in writing, software
140
+ distributed under the License is distributed on an "AS IS" BASIS,
141
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
142
+ See the License for the specific language governing permissions and
143
+ limitations under the License.
@@ -0,0 +1,23 @@
1
+ .PHONY: install test lint bench build docker clean
2
+
3
+ install:
4
+ pip install -e ".[dev]"
5
+
6
+ test:
7
+ pytest -q
8
+
9
+ lint:
10
+ ruff check .
11
+
12
+ bench:
13
+ python benchmarks/run.py --write
14
+
15
+ build:
16
+ python -m build
17
+
18
+ docker:
19
+ docker build -t tabayyan:local .
20
+
21
+ clean:
22
+ rm -rf build dist *.egg-info .pytest_cache .ruff_cache
23
+ find . -type d -name __pycache__ -exec rm -rf {} +