mongo-aggro 0.1.0__tar.gz → 0.2.2__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 (126) hide show
  1. mongo_aggro-0.2.2/.codespellrc +3 -0
  2. mongo_aggro-0.2.2/.github/instructions/commit-style.instructions.md +3 -0
  3. mongo_aggro-0.2.2/.github/instructions/python-coding.instructions.md +7 -0
  4. mongo_aggro-0.2.2/.github/workflows/ci.yml +75 -0
  5. mongo_aggro-0.2.2/.github/workflows/docs.yml +49 -0
  6. mongo_aggro-0.2.2/.gitignore +143 -0
  7. mongo_aggro-0.2.2/.pre-commit-config.yaml +53 -0
  8. mongo_aggro-0.2.2/CONTRIBUTING.md +110 -0
  9. mongo_aggro-0.2.2/Makefile +83 -0
  10. mongo_aggro-0.2.2/PKG-INFO +193 -0
  11. mongo_aggro-0.2.2/README.md +150 -0
  12. mongo_aggro-0.2.2/docs/api/accumulators.md +112 -0
  13. mongo_aggro-0.2.2/docs/api/expressions.md +820 -0
  14. mongo_aggro-0.2.2/docs/api/operators.md +176 -0
  15. mongo_aggro-0.2.2/docs/api/pipeline.md +12 -0
  16. mongo_aggro-0.2.2/docs/api/stages.md +256 -0
  17. mongo_aggro-0.2.2/docs/examples/advanced.md +310 -0
  18. mongo_aggro-0.2.2/docs/examples/basic.md +244 -0
  19. mongo_aggro-0.2.2/docs/examples/real-world.md +394 -0
  20. mongo_aggro-0.2.2/docs/getting-started/installation.md +55 -0
  21. mongo_aggro-0.2.2/docs/getting-started/quickstart.md +118 -0
  22. mongo_aggro-0.2.2/docs/guide/accumulators.md +254 -0
  23. mongo_aggro-0.2.2/docs/guide/expressions.md +357 -0
  24. mongo_aggro-0.2.2/docs/guide/operators.md +2103 -0
  25. mongo_aggro-0.2.2/docs/guide/pipeline.md +118 -0
  26. mongo_aggro-0.2.2/docs/guide/stages.md +644 -0
  27. mongo_aggro-0.2.2/docs/index.md +71 -0
  28. mongo_aggro-0.2.2/docs/integrations/beanie.md +310 -0
  29. mongo_aggro-0.2.2/docs/integrations/index.md +48 -0
  30. mongo_aggro-0.2.2/docs/integrations/mongoengine.md +348 -0
  31. mongo_aggro-0.2.2/docs/integrations/pymongo.md +412 -0
  32. mongo_aggro-0.2.2/mkdocs.yml +110 -0
  33. mongo_aggro-0.2.2/mongo_aggro/__init__.py +588 -0
  34. {mongo_aggro-0.1.0 → mongo_aggro-0.2.2}/mongo_aggro/accumulators.py +30 -12
  35. {mongo_aggro-0.1.0 → mongo_aggro-0.2.2}/mongo_aggro/base.py +49 -9
  36. mongo_aggro-0.2.2/mongo_aggro/expressions/__init__.py +396 -0
  37. mongo_aggro-0.2.2/mongo_aggro/expressions/arithmetic.py +329 -0
  38. mongo_aggro-0.2.2/mongo_aggro/expressions/array.py +425 -0
  39. mongo_aggro-0.2.2/mongo_aggro/expressions/base.py +180 -0
  40. mongo_aggro-0.2.2/mongo_aggro/expressions/bitwise.py +84 -0
  41. mongo_aggro-0.2.2/mongo_aggro/expressions/comparison.py +161 -0
  42. mongo_aggro-0.2.2/mongo_aggro/expressions/conditional.py +117 -0
  43. mongo_aggro-0.2.2/mongo_aggro/expressions/date.py +665 -0
  44. mongo_aggro-0.2.2/mongo_aggro/expressions/encrypted.py +116 -0
  45. mongo_aggro-0.2.2/mongo_aggro/expressions/logical.py +72 -0
  46. mongo_aggro-0.2.2/mongo_aggro/expressions/object.py +122 -0
  47. mongo_aggro-0.2.2/mongo_aggro/expressions/set.py +150 -0
  48. mongo_aggro-0.2.2/mongo_aggro/expressions/size.py +48 -0
  49. mongo_aggro-0.2.2/mongo_aggro/expressions/string.py +365 -0
  50. mongo_aggro-0.2.2/mongo_aggro/expressions/trigonometry.py +283 -0
  51. mongo_aggro-0.2.2/mongo_aggro/expressions/type.py +205 -0
  52. mongo_aggro-0.2.2/mongo_aggro/expressions/variable.py +73 -0
  53. mongo_aggro-0.2.2/mongo_aggro/expressions/window.py +327 -0
  54. mongo_aggro-0.2.2/mongo_aggro/operators/__init__.py +65 -0
  55. mongo_aggro-0.2.2/mongo_aggro/operators/array.py +41 -0
  56. mongo_aggro-0.2.2/mongo_aggro/operators/base.py +15 -0
  57. mongo_aggro-0.2.2/mongo_aggro/operators/bitwise.py +81 -0
  58. mongo_aggro-0.2.2/mongo_aggro/operators/comparison.py +82 -0
  59. mongo_aggro-0.2.2/mongo_aggro/operators/element.py +32 -0
  60. mongo_aggro-0.2.2/mongo_aggro/operators/geo.py +171 -0
  61. mongo_aggro-0.2.2/mongo_aggro/operators/logical.py +111 -0
  62. mongo_aggro-0.2.2/mongo_aggro/operators/misc.py +102 -0
  63. mongo_aggro-0.2.2/mongo_aggro/operators/regex.py +25 -0
  64. mongo_aggro-0.2.2/mongo_aggro/stages/__init__.py +110 -0
  65. mongo_aggro-0.2.2/mongo_aggro/stages/array.py +69 -0
  66. mongo_aggro-0.2.2/mongo_aggro/stages/change.py +109 -0
  67. mongo_aggro-0.2.2/mongo_aggro/stages/core.py +170 -0
  68. mongo_aggro-0.2.2/mongo_aggro/stages/geo.py +93 -0
  69. mongo_aggro-0.2.2/mongo_aggro/stages/group.py +154 -0
  70. mongo_aggro-0.2.2/mongo_aggro/stages/join.py +221 -0
  71. mongo_aggro-0.2.2/mongo_aggro/stages/misc.py +45 -0
  72. mongo_aggro-0.2.2/mongo_aggro/stages/output.py +136 -0
  73. mongo_aggro-0.2.2/mongo_aggro/stages/search.py +315 -0
  74. mongo_aggro-0.2.2/mongo_aggro/stages/session.py +111 -0
  75. mongo_aggro-0.2.2/mongo_aggro/stages/stats.py +152 -0
  76. mongo_aggro-0.2.2/mongo_aggro/stages/transform.py +136 -0
  77. mongo_aggro-0.2.2/mongo_aggro/stages/window.py +139 -0
  78. mongo_aggro-0.2.2/poetry.lock +2255 -0
  79. {mongo_aggro-0.1.0 → mongo_aggro-0.2.2}/pyproject.toml +10 -36
  80. mongo_aggro-0.2.2/tests/__init__.py +1 -0
  81. mongo_aggro-0.2.2/tests/conftest.py +6 -0
  82. mongo_aggro-0.2.2/tests/expressions/__init__.py +1 -0
  83. mongo_aggro-0.2.2/tests/expressions/test_arithmetic.py +242 -0
  84. mongo_aggro-0.2.2/tests/expressions/test_array.py +300 -0
  85. mongo_aggro-0.2.2/tests/expressions/test_comparison.py +246 -0
  86. mongo_aggro-0.2.2/tests/expressions/test_conditional.py +178 -0
  87. mongo_aggro-0.2.2/tests/expressions/test_date.py +370 -0
  88. mongo_aggro-0.2.2/tests/expressions/test_field.py +83 -0
  89. mongo_aggro-0.2.2/tests/expressions/test_logical.py +236 -0
  90. mongo_aggro-0.2.2/tests/expressions/test_nested.py +201 -0
  91. mongo_aggro-0.2.2/tests/expressions/test_string.py +233 -0
  92. mongo_aggro-0.2.2/tests/expressions/test_type.py +169 -0
  93. mongo_aggro-0.2.2/tests/fixtures/__init__.py +0 -0
  94. mongo_aggro-0.2.2/tests/fixtures/expression.py +11 -0
  95. mongo_aggro-0.2.2/tests/fixtures/pipeline.py +152 -0
  96. mongo_aggro-0.2.2/tests/operators/__init__.py +0 -0
  97. mongo_aggro-0.2.2/tests/operators/test_array.py +90 -0
  98. mongo_aggro-0.2.2/tests/operators/test_bitwise.py +94 -0
  99. mongo_aggro-0.2.2/tests/operators/test_comparison.py +143 -0
  100. mongo_aggro-0.2.2/tests/operators/test_element.py +59 -0
  101. mongo_aggro-0.2.2/tests/operators/test_geo.py +146 -0
  102. mongo_aggro-0.2.2/tests/operators/test_logical.py +143 -0
  103. mongo_aggro-0.2.2/tests/operators/test_misc.py +137 -0
  104. mongo_aggro-0.2.2/tests/operators/test_regex.py +38 -0
  105. mongo_aggro-0.2.2/tests/stages/__init__.py +1 -0
  106. mongo_aggro-0.2.2/tests/stages/test_array.py +73 -0
  107. mongo_aggro-0.2.2/tests/stages/test_change.py +94 -0
  108. mongo_aggro-0.2.2/tests/stages/test_core.py +269 -0
  109. mongo_aggro-0.2.2/tests/stages/test_geo.py +84 -0
  110. mongo_aggro-0.2.2/tests/stages/test_group.py +179 -0
  111. mongo_aggro-0.2.2/tests/stages/test_join.py +184 -0
  112. mongo_aggro-0.2.2/tests/stages/test_output.py +149 -0
  113. mongo_aggro-0.2.2/tests/stages/test_search.py +330 -0
  114. mongo_aggro-0.2.2/tests/stages/test_session.py +103 -0
  115. mongo_aggro-0.2.2/tests/stages/test_stats.py +134 -0
  116. mongo_aggro-0.2.2/tests/stages/test_transform.py +159 -0
  117. mongo_aggro-0.2.2/tests/stages/test_window.py +154 -0
  118. mongo_aggro-0.2.2/tests/test_accumulators.py +274 -0
  119. mongo_aggro-0.2.2/tests/test_pipeline.py +338 -0
  120. mongo_aggro-0.2.2/uv.lock +1440 -0
  121. mongo_aggro-0.1.0/PKG-INFO +0 -537
  122. mongo_aggro-0.1.0/README.md +0 -496
  123. mongo_aggro-0.1.0/mongo_aggro/__init__.py +0 -188
  124. mongo_aggro-0.1.0/mongo_aggro/operators.py +0 -247
  125. mongo_aggro-0.1.0/mongo_aggro/stages.py +0 -990
  126. {mongo_aggro-0.1.0 → mongo_aggro-0.2.2}/LICENSE +0 -0
@@ -0,0 +1,3 @@
1
+ [codespell]
2
+ skip = *.json,*.lock,*.min.js,.git,__pycache__,.mypy_cache,.pytest_cache,.venv,venv
3
+ ignore-words-list = BottomN,Nin,bottomN,nin
@@ -0,0 +1,3 @@
1
+ # Commit Style Guidance
2
+
3
+ All commit messages must use the prescribed types (`feat`, `ref`, `doc`, `ci`, `cd`, `dep`, `style`, `fix`) and follow Conventional Commits. The first line must describe all actions in ≤50 characters, be a single sentence that explains everything that changed, and be followed by an empty line and detail lines that start with `-` describing each change. If referencing a specific Sentry or GitHub issue with a unique code, include it as `(type #code: ...)`, e.g., `(fix #gh45: use x instead of y)`.
@@ -0,0 +1,7 @@
1
+ # Python Coding Guidance
2
+
3
+ 1. Simplicity always wins—write readable, clean Python that adheres to PEP 8, as though Black and isort already ran. Wrap or break any docstring, comment, or f-string exceeding 79 characters into multiple lines.
4
+ 2. Determine the highest Python version used in this repo, prefer that (or specify it if multiple versions exist), and leverage its modern type hints extensively. Favor typing tools (TypeVar, generics, Literal, etc.) or Pydantic models when available; avoid magic literals by defining named constants.
5
+ 3. Prefer functional programming over OOP whenever feasible, defaulting to enums (IntEnum, StrEnum, etc.) over mappings and selecting the enum variant that matches the data. Keep every line ≤79 characters.
6
+ 4. Detect and use the repo’s package manager—prefer `uv`, then `poetry`, then `pipenv`, then `pip`—and always rely on existing Makefile targets instead of inventing new commands when a Makefile exists.
7
+ 5. Never use unparameterized collection types; always annotate what items they hold (e.g., `list[str]`, `dict[str, int | str]`). If the item types vary or are unknown, use `Any` (after importing it from `typing`) so the collection remains precise (e.g., `dict[str, Any]`).
@@ -0,0 +1,75 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+
9
+ jobs:
10
+ lint:
11
+ runs-on: ubuntu-latest
12
+ steps:
13
+ - uses: actions/checkout@v4
14
+
15
+ - name: Install uv
16
+ uses: astral-sh/setup-uv@v4
17
+
18
+ - name: Set up Python
19
+ run: uv python install 3.12
20
+
21
+ - name: Install dependencies
22
+ run: uv sync --extra dev
23
+
24
+ - name: Run pre-commit
25
+ run: uv run pre-commit run --all-files
26
+
27
+ test:
28
+ runs-on: ubuntu-latest
29
+ needs: lint
30
+ strategy:
31
+ matrix:
32
+ python-version: ["3.10", "3.11", "3.12"]
33
+ steps:
34
+ - uses: actions/checkout@v4
35
+
36
+ - name: Install uv
37
+ uses: astral-sh/setup-uv@v4
38
+
39
+ - name: Set up Python ${{ matrix.python-version }}
40
+ run: uv python install ${{ matrix.python-version }}
41
+
42
+ - name: Install dependencies
43
+ run: uv sync --extra dev --extra test
44
+
45
+ - name: Run tests
46
+ run: uv run pytest -v --cov=mongo_aggro --cov-report=xml
47
+
48
+ - name: Upload coverage
49
+ uses: codecov/codecov-action@v4
50
+ if: matrix.python-version == '3.12'
51
+ with:
52
+ file: ./coverage.xml
53
+ fail_ci_if_error: false
54
+
55
+ publish:
56
+ runs-on: ubuntu-latest
57
+ needs: test
58
+ if: github.event_name == 'push' && github.ref == 'refs/heads/main'
59
+ environment: pypi
60
+ permissions:
61
+ id-token: write
62
+ steps:
63
+ - uses: actions/checkout@v4
64
+
65
+ - name: Install uv
66
+ uses: astral-sh/setup-uv@v4
67
+
68
+ - name: Set up Python
69
+ run: uv python install 3.12
70
+
71
+ - name: Build package
72
+ run: uv build
73
+
74
+ - name: Publish to PyPI
75
+ uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,49 @@
1
+ name: Documentation
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ workflow_dispatch:
7
+
8
+ permissions:
9
+ contents: read
10
+ pages: write
11
+ id-token: write
12
+
13
+ concurrency:
14
+ group: "pages"
15
+ cancel-in-progress: false
16
+
17
+ jobs:
18
+ build:
19
+ runs-on: ubuntu-latest
20
+ steps:
21
+ - uses: actions/checkout@v4
22
+
23
+ - name: Install uv
24
+ uses: astral-sh/setup-uv@v4
25
+
26
+ - name: Set up Python
27
+ run: uv python install 3.12
28
+
29
+ - name: Install dependencies
30
+ run: uv sync --extra docs
31
+
32
+ - name: Build documentation
33
+ run: uv run mkdocs build
34
+
35
+ - name: Upload artifact
36
+ uses: actions/upload-pages-artifact@v3
37
+ with:
38
+ path: ./site
39
+
40
+ deploy:
41
+ environment:
42
+ name: github-pages
43
+ url: ${{ steps.deployment.outputs.page_url }}
44
+ runs-on: ubuntu-latest
45
+ needs: build
46
+ steps:
47
+ - name: Deploy to GitHub Pages
48
+ id: deployment
49
+ uses: actions/deploy-pages@v4
@@ -0,0 +1,143 @@
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ !**/__pycache__/
4
+ *.py[cod]
5
+ *$py.class
6
+ app/__pycache__/
7
+ media/
8
+ web_app/
9
+ dash_app/
10
+ .sourcery.yaml
11
+ # C extensions
12
+ *.so
13
+ # Distribution / packaging
14
+ .Python
15
+ build/
16
+ develop-eggs/
17
+ dist/
18
+ database/
19
+ downloads/
20
+ eggs/
21
+ .eggs/
22
+ lib/
23
+ lib64/
24
+ parts/
25
+ sdist/
26
+ var/
27
+ wheels/
28
+ pip-wheel-metadata/
29
+ share/python-wheels/
30
+ *.egg-info/
31
+ .installed.cfg
32
+ *.egg
33
+ MANIFEST
34
+
35
+ # PyInstaller
36
+ # Usually these files are written by a python script from a template
37
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
38
+ *.manifest
39
+ *.spec
40
+
41
+ # Installer logs
42
+ pip-log.txt
43
+ pip-delete-this-directory.txt
44
+
45
+ # Unit test / coverage reports
46
+ htmlcov/
47
+ .tox/
48
+ .nox/
49
+ junit.xml
50
+ .coverage
51
+ .coverage.*
52
+ .cache
53
+ nosetests.xml
54
+ coverage.xml
55
+ *.cover
56
+ *.py,cover
57
+ .hypothesis/
58
+ .pytest_cache/
59
+
60
+ # Translations
61
+ *.mo
62
+ *.pot
63
+
64
+ # Django stuff:
65
+ *.log
66
+ local_settings.py
67
+ db.sqlite3
68
+ db.sqlite3-journal
69
+
70
+ # Flask stuff:
71
+ instance/
72
+ .webassets-cache
73
+
74
+ # Scrapy stuff:
75
+ .scrapy
76
+
77
+ # Sphinx documentation
78
+ docs/_build/
79
+
80
+ # PyBuilder
81
+ target/
82
+
83
+ # Jupyter Notebook
84
+ .ipynb_checkpoints
85
+
86
+ # IPython
87
+ profile_default/
88
+ ipython_config.py
89
+
90
+ # pyenv
91
+ .python-version
92
+
93
+ # pipenv
94
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
95
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
96
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
97
+ # install all needed dependencies.
98
+ #Pipfile.lock
99
+
100
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow
101
+ __pypackages__/
102
+
103
+ # Celery stuff
104
+ celerybeat-schedule
105
+ celerybeat.pid
106
+
107
+ # SageMath parsed files
108
+ *.sage.py
109
+
110
+ # Environments
111
+ .venv
112
+ env/
113
+ venv/
114
+ ENV/
115
+ env.bak/
116
+ venv.bak/
117
+
118
+ # Spyder project settings
119
+ .spyderproject
120
+ .spyproject
121
+
122
+ # Rope project settings
123
+ .ropeproject
124
+
125
+ # mkdocs documentation
126
+ /site
127
+
128
+ # mypy
129
+ .mypy_cache/
130
+ .dmypy.json
131
+ dmypy.json
132
+
133
+ # Pyre type checker
134
+ .pyre/
135
+
136
+ .vscode/
137
+ media/
138
+ .idea/
139
+ .env
140
+ ./app/utils/Faker.py
141
+ poetry.toml
142
+ docker/
143
+ site/
@@ -0,0 +1,53 @@
1
+ # See https://pre-commit.com for more information
2
+ # See https://pre-commit.com/hooks.html for more hooks
3
+ repos:
4
+ - repo: https://github.com/pre-commit/pre-commit-hooks
5
+ rev: v5.0.0
6
+ hooks:
7
+ - id: trailing-whitespace
8
+ - id: end-of-file-fixer
9
+ - id: check-yaml
10
+ - id: check-added-large-files
11
+ - id: check-toml
12
+
13
+ - repo: https://github.com/codespell-project/codespell
14
+ rev: v2.3.0
15
+ hooks:
16
+ - id: codespell
17
+ args: ["--config", ".codespellrc"]
18
+
19
+ - repo: https://github.com/psf/black
20
+ rev: 24.10.0
21
+ hooks:
22
+ - id: black
23
+
24
+ - repo: https://github.com/pycqa/isort
25
+ rev: 5.13.2
26
+ hooks:
27
+ - id: isort
28
+
29
+ - repo: https://github.com/astral-sh/ruff-pre-commit
30
+ rev: v0.8.4
31
+ hooks:
32
+ - id: ruff
33
+ args: ["--fix"]
34
+
35
+ - repo: https://github.com/asottile/pyupgrade
36
+ rev: v3.19.0
37
+ hooks:
38
+ - id: pyupgrade
39
+ args: ["--py312-plus"]
40
+
41
+ - repo: https://github.com/pre-commit/mirrors-mypy
42
+ rev: v1.13.0
43
+ hooks:
44
+ - id: mypy
45
+ additional_dependencies:
46
+ - mypy-extensions==1.0.0
47
+ - pydantic>=2.10.0
48
+ - types-requests
49
+
50
+ - repo: https://github.com/python-poetry/poetry
51
+ rev: 2.0.1
52
+ hooks:
53
+ - id: poetry-check
@@ -0,0 +1,110 @@
1
+ # Contributing to Mongo Aggro
2
+
3
+ Thank you for your interest in contributing!
4
+
5
+ ## Development Setup
6
+
7
+ ### Prerequisites
8
+
9
+ - Python 3.12+
10
+ - [uv](https://github.com/astral-sh/uv) for package management
11
+
12
+ ### Setup
13
+
14
+ ```bash
15
+ git clone https://github.com/hamedghenaat/mongo-aggro.git
16
+ cd mongo-aggro
17
+
18
+ # Install dependencies
19
+ uv sync --all-extras
20
+
21
+ # Install pre-commit hooks
22
+ uv run pre-commit install
23
+ ```
24
+
25
+ ## Development Workflow
26
+
27
+ ```bash
28
+ # Run tests
29
+ make test
30
+
31
+ # Run linter
32
+ make lint
33
+
34
+ # Format code
35
+ make format
36
+
37
+ # Run all checks
38
+ make check
39
+ ```
40
+
41
+ ## Code Style
42
+
43
+ - **Ruff** for linting and formatting
44
+ - **79 character** line limit
45
+ - **Type hints** required on all functions
46
+ - **Google-style** docstrings
47
+
48
+ ### Example
49
+
50
+ ```python
51
+ def model_dump(self, **kwargs: Any) -> dict[str, Any]:
52
+ """
53
+ Convert stage to MongoDB dictionary.
54
+
55
+ Args:
56
+ **kwargs: Additional Pydantic arguments.
57
+
58
+ Returns:
59
+ MongoDB aggregation stage dictionary.
60
+
61
+ Example:
62
+ >>> Match(query={"status": "active"}).model_dump()
63
+ {"$match": {"status": "active"}}
64
+ """
65
+ return {"$match": self.query}
66
+ ```
67
+
68
+ ## Adding Features
69
+
70
+ ### New Stage
71
+
72
+ 1. Add class in `mongo_aggro/stages.py`
73
+ 2. Export in `mongo_aggro/__init__.py`
74
+ 3. Add tests in `tests/test_stages.py`
75
+ 4. Update documentation
76
+
77
+ ### New Expression
78
+
79
+ 1. Add class in `mongo_aggro/expressions.py`
80
+ 2. Export in `mongo_aggro/__init__.py`
81
+ 3. Add tests in `tests/test_expressions.py`
82
+
83
+ ## Commit Style
84
+
85
+ Use conventional commits:
86
+ - `feat:` New features
87
+ - `fix:` Bug fixes
88
+ - `doc:` Documentation
89
+ - `ref:` Refactoring
90
+ - `ci:` CI/CD changes
91
+
92
+ ```bash
93
+ git commit -m "feat: add new stage
94
+
95
+ - Add NewStage class
96
+ - Add tests
97
+ - Update documentation"
98
+ ```
99
+
100
+ ## Pull Request Process
101
+
102
+ 1. Create feature branch
103
+ 2. Make changes with tests
104
+ 3. Run `make check`
105
+ 4. Push and create PR
106
+ 5. Address review comments
107
+
108
+ ## Questions?
109
+
110
+ Open an issue for any questions.
@@ -0,0 +1,83 @@
1
+ .PHONY: help install install-dev install-test install-all lint format test test-cov clean build publish docs docs-serve
2
+
3
+ PYTHON := python
4
+ UV := uv
5
+
6
+ help: ## Show this help message
7
+ @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-20s\033[0m %s\n", $$1, $$2}'
8
+
9
+ install: ## Install production dependencies
10
+ $(UV) sync --no-dev
11
+
12
+ install-dev: ## Install development dependencies
13
+ $(UV) sync --extra dev
14
+
15
+ install-test: ## Install test dependencies
16
+ $(UV) sync --extra test
17
+
18
+ install-all: ## Install all dependencies (dev + test + docs)
19
+ $(UV) sync --extra dev --extra test --extra docs
20
+
21
+ lint: ## Run all linters
22
+ $(UV) run ruff check .
23
+ $(UV) run mypy mongo_aggro
24
+
25
+ format: ## Format code with black and isort
26
+ $(UV) run black .
27
+ $(UV) run isort .
28
+ $(UV) run ruff check --fix .
29
+
30
+ test: ## Run tests
31
+ $(UV) run pytest
32
+
33
+ test-cov: ## Run tests with coverage
34
+ $(UV) run pytest --cov=mongo_aggro --cov-report=term-missing --cov-report=html
35
+
36
+ test-fast: ## Run tests without coverage (faster)
37
+ $(UV) run pytest -x -q
38
+
39
+ pre-commit: ## Run pre-commit hooks on all files
40
+ $(UV) run pre-commit run --all-files
41
+
42
+ pre-commit-install: ## Install pre-commit hooks
43
+ $(UV) run pre-commit install
44
+
45
+ clean: ## Clean build artifacts
46
+ rm -rf build/
47
+ rm -rf dist/
48
+ rm -rf *.egg-info/
49
+ rm -rf .pytest_cache/
50
+ rm -rf .mypy_cache/
51
+ rm -rf .ruff_cache/
52
+ rm -rf htmlcov/
53
+ rm -rf .coverage
54
+ find . -type d -name __pycache__ -exec rm -rf {} + 2>/dev/null || true
55
+ find . -type f -name "*.pyc" -delete
56
+
57
+ build: ## Build package
58
+ $(UV) build
59
+
60
+ publish: ## Publish to PyPI (usage: make publish REPO=pypi)
61
+ $(UV) run twine upload --repository $(REPO) dist/*
62
+
63
+ publish-test: ## Publish to TestPyPI
64
+ $(UV) run twine upload --repository testpypi dist/*
65
+
66
+ check: ## Run all checks (lint + test)
67
+ $(MAKE) lint
68
+ $(MAKE) test
69
+
70
+ ci: ## Run CI pipeline (format check + lint + test)
71
+ $(UV) run black --check .
72
+ $(UV) run isort --check-only .
73
+ $(MAKE) lint
74
+ $(MAKE) test-cov
75
+
76
+ docs: ## Build documentation
77
+ $(UV) run mkdocs build
78
+
79
+ docs-serve: ## Serve documentation locally
80
+ $(UV) run mkdocs serve
81
+
82
+ docs-deploy: ## Deploy documentation to GitHub Pages
83
+ $(UV) run mkdocs gh-deploy --force