From f97a727d9ec8167bee83a8fc54a9ff1f9f0ad8d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kriszti=C3=A1n=20Fekete?= Date: Sun, 14 Sep 2025 20:51:54 +0200 Subject: [PATCH 1/3] fix: venv when source root is mapped in container When running a container with mapped source root, there can be a conflict over .venv when outside is macos and inside is linux, with the venv not being usable in one of them. Also included more ai tools in the container definition. --- .envrc | 12 +++++++++--- Makefile | 2 +- dev/Containerfile | 14 ++++++++++++-- dev/vm | 15 +++++---------- 4 files changed, 27 insertions(+), 16 deletions(-) diff --git a/.envrc b/.envrc index 39a80592..c7ca4f7b 100644 --- a/.envrc +++ b/.envrc @@ -6,16 +6,22 @@ layout_uv() { VIRTUAL_ENV="$(pwd)/.venv" fi - if [[ -z $VIRTUAL_ENV || ! -d $VIRTUAL_ENV ]]; then + if [[ -d ".venv.$(uname)" ]]; then + VIRTUAL_ENV="$(pwd)/.venv.$(uname)" + fi + + if [[ -z $VIRTUAL_ENV || ! -d $VIRTUAL_ENV ]] || ! $VIRTUAL_ENV/bin/python -c True; then log_status "No virtual environment exists. Executing \`uv venv\` to create one." - uv venv - VIRTUAL_ENV="$(pwd)/.venv" + VIRTUAL_ENV="$(pwd)/.venv.$(uname)" + uv venv --clear "$VIRTUAL_ENV" fi + UV_PROJECT_ENVIRONMENT="$VIRTUAL_ENV" PATH_add "$VIRTUAL_ENV/bin" export UV_ACTIVE=1 export VENV_ACTIVE=1 export VIRTUAL_ENV + export UV_PROJECT_ENVIRONMENT } layout_uv diff --git a/Makefile b/Makefile index 9a441abc..2ae25090 100644 --- a/Makefile +++ b/Makefile @@ -9,5 +9,5 @@ executables: shiv: shiv -o executables/bead.shiv -c bead -p '/usr/bin/python -sE' . -container-image: +vm: podman build --no-cache -t bead-dev - < dev/Containerfile diff --git a/dev/Containerfile b/dev/Containerfile index 35f5bbfc..5b8e822f 100644 --- a/dev/Containerfile +++ b/dev/Containerfile @@ -2,7 +2,7 @@ FROM python:3.12-slim-trixie RUN apt update -RUN apt install -y direnv fd-find fzf git less ripgrep tree graphviz unzip sqlite3 visidata pipx +RUN apt install -y direnv fd-find fzf git less ripgrep tree graphviz unzip sqlite3 visidata pipx npm # uv COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/ @@ -10,9 +10,19 @@ COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/ # aider RUN uv venv --python python3.12 /opt/aider RUN bash -c 'source /opt/aider/bin/activate && uv pip install aider-chat' - ENV PATH="$PATH:/opt/aider/bin" +# opencode +ADD https://github.com/sst/opencode/releases/latest/download/opencode-linux-arm64.zip /tmp/opencode-linux-arm64.zip +RUN unzip /tmp/opencode-linux-arm64.zip -d /opt/opencode && chmod -R a-w /opt/opencode +ENV PATH="$PATH:/opt/opencode" +# RUN mkdir -p /opt/opencode-ai && npm install -g --prefix /opt/opencode-ai opencode-ai +# ENV PATH="$PATH:/opt/opencode-ai/bin" + +# gemini-cli +RUN mkdir -p /opt/gemini && npm install -g --prefix /opt/gemini @google/gemini-cli +ENV PATH="$PATH:/opt/gemini/bin" + RUN cat > /opt/bashrc < Date: Sun, 14 Sep 2025 21:02:41 +0200 Subject: [PATCH 2/3] feat(project): Add contribution guidelines and PR template - Clarify that contributions are dedicated to the public domain under The Unlicense. - Add a Contributing section to README.md and make documentation links repository-relative. - Create a CONTRIBUTING.md file with detailed development guidelines. - Create a pull request template to ensure contributors agree to the license terms. --- .github/pull_request_template.md | 6 +++ CONTRIBUTING.md | 90 ++++++++++++++++++++++++++++++++ README.md | 25 ++++++--- 3 files changed, 115 insertions(+), 6 deletions(-) create mode 100644 .github/pull_request_template.md create mode 100644 CONTRIBUTING.md diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 00000000..ae3d92df --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,6 @@ + + +**Before submitting, please confirm the following:** + +- [ ] I have read and understood the project's [CONTRIBUTING.md](CONTRIBUTING.md) file. +- [ ] I agree to dedicate my contribution to the public domain under the terms of the [LICENSE](LICENSE) file. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000..b178d127 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,90 @@ +# Contributing to Bead + +Thank you for your interest in contributing to the Bead project! We welcome contributions from everyone. To ensure a smooth and collaborative process, please review these guidelines. + +This document provides instructions for both human developers and AI agents to ensure that all contributions are consistent and high-quality. + +## Development Workflow + +### Version Control & Commits + +We use Git for version control. Please follow these conventions for your commits: + +- **Use the [Conventional Commits](https://www.conventionalcommits.org/) format.** This helps us automate releases and makes the project history easy to read. +- Your commit message should clearly explain the **reason** for the change. +- Focus on the **"why"** of the change in the commit body, not just the "what." + +### Build, Lint, and Test Commands + +Before submitting your contribution, please ensure it passes all checks. + +#### Testing +- **Run all tests**: `make test` or `tox` +- **Run a single test**: `pytest path/to/test_file.py::TestClass::test_method` or `pytest path/to/test_file.py -k "test_name"` +- **Check test coverage**: `pytest --cov=. --cov-report=term-missing` + +#### Linting & Formatting +- **Run the linter**: `flake8 bead bead_cli tests` +- **Format imports automatically**: `isort .` +- **Run the static type checker**: `pytype -k -j auto bead bead_cli __main__.py tests tracelog.py dev/build.py` or `uvx ty check` +- **Run all pre-commit hooks**: `pre-commit run --all-files` + +#### Building +- **Build a wheel**: `uv build --wheel` +- **Build executables**: `make executables` + +## Code Style Guidelines + +### General Principles +- Keep code simple, readable, and self-explanatory. +- Use meaningful names that reveal intent for variables, functions, classes, etc. + +### Variables +- If a variable's name conflicts with its content or meaning, it **MUST** be renamed. + +### Functions +- Each function should do one thing and do it well. +- Keep functions small (a few lines). +- Prefer a maximum of 2-3 parameters. +- Function names should describe the action being performed. +- If a function's name conflicts with its behavior, it **MUST** be renamed. + +### Classes +- Each class should have a single responsibility. +- Follow the [SOLID principles](https://en.wikipedia.org/wiki/SOLID). + +### Imports +- Place all imports at the top of the file. +- Use one import per line. +- Our configuration for `isort` enforces single-line, lexicographically sorted imports. + +### Formatting +- Maximum line length is 99 characters. +- Use 4 spaces for indentation. +- We follow PEP8 with the following exceptions: W503, W504, E251, E241, E221, E722. + +### Types +- Use type hints where they improve clarity and correctness. +- Pyright is configured to ignore unknown parameter/variable types. +- We use `pytype` for static type checking. + +### Error Handling +- Handle errors and exceptions properly to ensure robustness. +- Consider the security implications of your code. +- Avoid bare `except:` clauses. + +### Comments +- Prefer self-explanatory code over comments. +- Only add comments when they provide information that isn't apparent from the code itself. +- If you add comments, ensure they are kept up-to-date with code changes. + +### Database/SQL +- Isolate functions that use direct SQL from other logic. +- These functions should perform a single database operation. +- They should return materialized values (e.g., lists of objects), not cursors or generators. +- Hide the database implementation details from the rest of the application. + +### Bead-Specific Knowledge +- `content_id` and `kind` are internal, technical identifiers (long strings). They are not supplied directly by the user. +- Users specify beads and files by their names. +- `bead_ref_base` refers to a user-provided name or filename. diff --git a/README.md b/README.md index ccbe07d4..6bdcfdde 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -[![Tests](https://github.com/e3krisztian/bead/actions/workflows/test.yml/badge.svg)](https://github.com/e3krisztian/bead/actions/workflows/test.yml) +[![Tests](../../actions/workflows/test.yml/badge.svg)](../../actions/workflows/test.yml) B-E-+ @@ -37,7 +37,7 @@ New computations get a new, universally unique `kind` (technically an uuid). ## Status -### Used in production for almost 10 years now, there are hundreds of frozen computations +### Used in production since 2015, there are hundreds of frozen computations Although most of the important stuff is implemented, there are still some raw edges. @@ -46,8 +46,11 @@ Documentation for the tool is mostly the command line help. The `doc` directory has concept descriptions, maybe some use cases, but there are also design fragments - you might be mislead by them as they are nor describing the current situations nor are they showing the future. + FIXME: clean up documentation. +NOTE: https://bead.zip has new user documentation (as of September, 2025). + ## Install instructions @@ -71,14 +74,16 @@ $ cp executables/bead ~/.local/bin Alternatively it can be installed with pipx: +For production use choose the latest released, non-pre-release version: ``` -pipx install git+https://github.com/e3krisztian/bead +pipx install git+https://github.com/bead-project/bead@VERSION ``` -For development version, or + +or for latest development version: + ``` -pipx install git+https://github.com/e3krisztian/bead@VERSION +pipx install git+https://github.com/bead-project/bead ``` -for any tagged versions. ---- @@ -90,4 +95,12 @@ If you test it, please give [feedback](../../issues) on Any other nuisance reported - however minor you think it be - is important and welcome! +## Contributing + +We welcome contributions! If you feel like working on code, please open an issue first to discuss your ideas. + +This project is dedicated to the public domain via the [LICENSE](LICENSE) file. By submitting a pull request, you agree to irrevocably release your work under the same license. + +Please see [CONTRIBUTING.md](CONTRIBUTING.md) for detailed guidelines on our development process. + Thank you for your interest! From abd00a7f0262dc16fb7e12c0d14c4090551863ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kriszti=C3=A1n=20Fekete?= Date: Mon, 15 Sep 2025 21:05:11 +0200 Subject: [PATCH 3/3] feat(devenv) remove tox, use ruff instead of flake8 --- .github/workflows/test.yml | 3 ++ CONTRIBUTING.md | 4 +-- Makefile | 8 ++--- bead/tech/__init__.py | 2 +- dev/test | 2 +- pyproject.toml | 19 ++++++++++-- test_requirements.txt | 2 +- tox.ini | 61 -------------------------------------- uv.lock | 43 --------------------------- 9 files changed, 27 insertions(+), 117 deletions(-) delete mode 100644 tox.ini diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index d6c3983d..c62c022d 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -32,6 +32,9 @@ jobs: - name: Install dependencies run: uv sync --dev + - name: Lint with ruff + run: uv run ruff check . + - name: Run CLI tests run: uv run python -m pytest bead_cli/ -v diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b178d127..ccc6cc27 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -19,12 +19,12 @@ We use Git for version control. Please follow these conventions for your commits Before submitting your contribution, please ensure it passes all checks. #### Testing -- **Run all tests**: `make test` or `tox` +- **Run all tests**: `make test` - **Run a single test**: `pytest path/to/test_file.py::TestClass::test_method` or `pytest path/to/test_file.py -k "test_name"` - **Check test coverage**: `pytest --cov=. --cov-report=term-missing` #### Linting & Formatting -- **Run the linter**: `flake8 bead bead_cli tests` +- **Run the linter**: `ruff check .` - **Format imports automatically**: `isort .` - **Run the static type checker**: `pytype -k -j auto bead bead_cli __main__.py tests tracelog.py dev/build.py` or `uvx ty check` - **Run all pre-commit hooks**: `pre-commit run --all-files` diff --git a/Makefile b/Makefile index 2ae25090..68778348 100644 --- a/Makefile +++ b/Makefile @@ -1,13 +1,11 @@ -.PHONY: test clean executables shiv +.PHONY: test clean executables test: - tox + uv run python -m pytest --cov=. --cov-report=term-missing + uv run ruff check . executables: dev/build.py -shiv: - shiv -o executables/bead.shiv -c bead -p '/usr/bin/python -sE' . - vm: podman build --no-cache -t bead-dev - < dev/Containerfile diff --git a/bead/tech/__init__.py b/bead/tech/__init__.py index 10d94972..11131d3c 100644 --- a/bead/tech/__init__.py +++ b/bead/tech/__init__.py @@ -1,4 +1,4 @@ -# flake8: noqa +# ruff: noqa ''' Technologies diff --git a/dev/test b/dev/test index 3ce7a001..77e7e445 100755 --- a/dev/test +++ b/dev/test @@ -6,7 +6,7 @@ cd $(dirname "$0") packages_to_test=(bead bead_cli tests) pwd -flake8 "${packages_to_test[@]}" +ruff check . mypy --ignore-missing-imports "${packages_to_test[@]}" # coverage diff --git a/pyproject.toml b/pyproject.toml index 3452a978..33dde481 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -55,12 +55,25 @@ dev = [ "mypy", "pre-commit", "ruff", - "flake8", "pytype>=2024.10.11", ] -[tool.flake8] -line_length= 120 +[tool.ruff] +line-length = 120 +lint.ignore = [ + "E251", # unexpected spaces around keyword / parameter equals + "E241", # multiple spaces after ',' + "E221", # multiple spaces before operator + "E722", # do not use bare except +] +exclude = [ + "appdirs.py", + "test-env", + ".eggs", +] + +[tool.ruff.lint.mccabe] +max-complexity = 10 [tool.isort] force_single_line=true diff --git a/test_requirements.txt b/test_requirements.txt index df5fbb22..d2a26cdc 100644 --- a/test_requirements.txt +++ b/test_requirements.txt @@ -1,4 +1,4 @@ -flake8 +ruff mypy==0.761 freezegun==0.3.12 pytest-cov==2.8.1 diff --git a/tox.ini b/tox.ini deleted file mode 100644 index 8346d0bd..00000000 --- a/tox.ini +++ /dev/null @@ -1,61 +0,0 @@ -[package] - -name = bead -deps = - -rrequirements.txt - -rtest_requirements.txt -envs = py310,py311,py312,313 - - -# ################################### -# generic config - -[tox] -# does not work since 1.8 :( -# envlist = {[package]envs} -envlist = py310,py311,py312,313 - -skip_missing_interpreters = true - -# do not require setup.py -skipsdist = true - -[testenv] -# tox-2.0.1: UnicodeDecodeError in tox install if LC_ALL = C -setenv = - LC_ALL = en_US.utf-8 - -deps = - {[package]deps} - -commands = - /bin/pwd - python --version - pytest --version - pytest --cov=. --cov-report=term-missing - flake8 bead bead_cli tests - - -[flake8] -# Disable pep8 "W503 line break before binary operator" (since pep8 1.6.2) -# "W504 line break after binary operator" - -ignore = W503,W504,E251,E241,E221,E722 -# E251 unexpected spaces around keyword / parameter equals -# E241 multiple spaces after ',' -# E221 multiple spaces before operator -# E722 do not use bare except -max-line-length = 99 -exclude = - .tox, - .git, - __pycache__, - test-env, - build, - dist, - *.pyc, - *.egg-info, - .cache, - .eggs, - ./appdirs.py -max-complexity = 10 diff --git a/uv.lock b/uv.lock index 1b35e4ac..bcaea4a2 100644 --- a/uv.lock +++ b/uv.lock @@ -57,7 +57,6 @@ dependencies = [ [package.dev-dependencies] dev = [ { name = "build" }, - { name = "flake8" }, { name = "freezegun" }, { name = "mypy" }, { name = "pip" }, @@ -81,7 +80,6 @@ requires-dist = [ [package.metadata.requires-dev] dev = [ { name = "build" }, - { name = "flake8" }, { name = "freezegun" }, { name = "mypy" }, { name = "pip", specifier = ">=25.1.1" }, @@ -396,20 +394,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/4d/36/2a115987e2d8c300a974597416d9de88f2444426de9571f4b59b2cca3acc/filelock-3.18.0-py3-none-any.whl", hash = "sha256:c401f4f8377c4464e6db25fff06205fd89bdd83b65eb0488ed1b160f780e21de", size = 16215, upload-time = "2025-03-14T07:11:39.145Z" }, ] -[[package]] -name = "flake8" -version = "7.2.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "mccabe" }, - { name = "pycodestyle" }, - { name = "pyflakes" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/e7/c4/5842fc9fc94584c455543540af62fd9900faade32511fab650e9891ec225/flake8-7.2.0.tar.gz", hash = "sha256:fa558ae3f6f7dbf2b4f22663e5343b6b6023620461f8d4ff2019ef4b5ee70426", size = 48177, upload-time = "2025-03-29T20:08:39.329Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/83/5c/0627be4c9976d56b1217cb5187b7504e7fd7d3503f8bfd312a04077bd4f7/flake8-7.2.0-py2.py3-none-any.whl", hash = "sha256:93b92ba5bdb60754a6da14fa3b93a9361fd00a59632ada61fd7b130436c40343", size = 57786, upload-time = "2025-03-29T20:08:37.902Z" }, -] - [[package]] name = "freezegun" version = "1.5.2" @@ -702,15 +686,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/4f/65/6079a46068dfceaeabb5dcad6d674f5f5c61a6fa5673746f42a9f4c233b3/MarkupSafe-3.0.2-cp313-cp313t-win_amd64.whl", hash = "sha256:e444a31f8db13eb18ada366ab3cf45fd4b31e4db1236a4448f68778c1d1a5a2f", size = 15739, upload-time = "2024-10-18T15:21:42.784Z" }, ] -[[package]] -name = "mccabe" -version = "0.7.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/e7/ff/0ffefdcac38932a54d2b5eed4e0ba8a408f215002cd178ad1df0f2806ff8/mccabe-0.7.0.tar.gz", hash = "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325", size = 9658, upload-time = "2022-01-24T01:14:51.113Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/27/1a/1f68f9ba0c207934b35b86a8ca3aad8395a3d6dd7921c0686e23853ff5a9/mccabe-0.7.0-py2.py3-none-any.whl", hash = "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e", size = 7350, upload-time = "2022-01-24T01:14:49.62Z" }, -] - [[package]] name = "mdurl" version = "0.1.2" @@ -974,15 +949,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/20/af/7ba371f966657f6e7b1c9876cae7e9f1c5d3635c3df1329636b99e615494/pycnite-2024.7.31-py3-none-any.whl", hash = "sha256:9ff9c09d35056435b867e14ebf79626ca94b6017923a0bf9935377fa90d4cbb3", size = 22939, upload-time = "2024-07-31T12:43:14.248Z" }, ] -[[package]] -name = "pycodestyle" -version = "2.13.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/04/6e/1f4a62078e4d95d82367f24e685aef3a672abfd27d1a868068fed4ed2254/pycodestyle-2.13.0.tar.gz", hash = "sha256:c8415bf09abe81d9c7f872502a6eee881fbe85d8763dd5b9924bb0a01d67efae", size = 39312, upload-time = "2025-03-29T17:33:30.669Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/07/be/b00116df1bfb3e0bb5b45e29d604799f7b91dd861637e4d448b4e09e6a3e/pycodestyle-2.13.0-py2.py3-none-any.whl", hash = "sha256:35863c5974a271c7a726ed228a14a4f6daf49df369d8c50cd9a6f58a5e143ba9", size = 31424, upload-time = "2025-03-29T17:33:29.405Z" }, -] - [[package]] name = "pycparser" version = "2.22" @@ -1004,15 +970,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/7e/32/a7125fb28c4261a627f999d5fb4afff25b523800faed2c30979949d6facd/pydot-4.0.1-py3-none-any.whl", hash = "sha256:869c0efadd2708c0be1f916eb669f3d664ca684bc57ffb7ecc08e70d5e93fee6", size = 37087, upload-time = "2025-06-17T20:09:55.25Z" }, ] -[[package]] -name = "pyflakes" -version = "3.3.2" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/af/cc/1df338bd7ed1fa7c317081dcf29bf2f01266603b301e6858856d346a12b3/pyflakes-3.3.2.tar.gz", hash = "sha256:6dfd61d87b97fba5dcfaaf781171ac16be16453be6d816147989e7f6e6a9576b", size = 64175, upload-time = "2025-03-31T13:21:20.34Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/15/40/b293a4fa769f3b02ab9e387c707c4cbdc34f073f945de0386107d4e669e6/pyflakes-3.3.2-py2.py3-none-any.whl", hash = "sha256:5039c8339cbb1944045f4ee5466908906180f13cc99cc9949348d10f82a5c32a", size = 63164, upload-time = "2025-03-31T13:21:18.503Z" }, -] - [[package]] name = "pygments" version = "2.19.1"