Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 11 additions & 7 deletions .github/workflows/docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,19 +15,23 @@ jobs:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v2
- name: Set up Python 3.10
uses: actions/setup-python@v2
- uses: actions/checkout@v6

- name: Set up Python 3.14
uses: actions/setup-python@v6
with:
python-version: "3.10"
python-version: ${{ env.PYTHON_VERSION }}

- name: Install uv
uses: astral-sh/setup-uv@v4
uses: astral-sh/setup-uv@v7
with:
enable-cache: true

- name: Install dependencies
run: uv sync
run: uv sync --all-groups

- name: Build and deploy documentation
run: |
git config --global user.name "github-actions"
git config --global user.email "action@github.com"
uv run mudkip build --check --update-gh-pages --repository https://x-access-token:${GH_TOKEN}@github.com/rx-modules/bolt-expressions
uv run mudkip build --check --update-gh-pages --repository https://x-access-token:${GH_TOKEN}@github.com/rx-modules/bolt-expressions
83 changes: 64 additions & 19 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,47 +6,92 @@ on:
pull_request:
branches: [main]

env:
PYTHON_VERSION: "3.14"

jobs:
main:
release:
name: Test and release
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0

- name: Set up Python 3.10
- name: Set up Python 3.14
uses: actions/setup-python@v6
with:
python-version: "3.12"
python-version: ${{ env.PYTHON_VERSION }}

- name: Install uv
uses: astral-sh/setup-uv@v7
with:
enable-cache: true

- name: Install dependencies
run: uv sync
run: uv sync --all-groups

- name: Run tests
run: uv run pytest -v

- name: Check formatting
run: uv run ruff format --check src/bolt_expressions examples tests
run: uv run ruff check

- name: Check imports
run: uv run ruff check --select I src/bolt_expressions examples tests
- name: Action | Semantic Version Release
id: release
if: github.ref == 'refs/heads/main'
run: |
# 1. Run the versioning logic
uv run semantic-release version

- name: Release
if: |
github.repository == 'rx-modules/bolt-expressions'
&& github.event_name == 'push'
&& github.ref == 'refs/heads/main'
# 2. Extract version info for subsequent steps
echo "tag=$(uv run semantic-release version --print-tag)" >> $GITHUB_OUTPUT

# 3. Check if a release actually happened
if [ -d "dist" ] && [ "$(ls -A dist)" ]; then
echo "released=true" >> $GITHUB_OUTPUT
fi
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PYPI_TOKEN: ${{ secrets.PYPI_TOKEN }}
run: |
git config --global user.name "github-actions"
git config --global user.email "action@github.com"
uv run semantic-release publish -v DEBUG -D commit_author="github-actions <action@github.com>"

- name: Publish | Upload to GitHub Release Assets
uses: python-semantic-release/publish-action@v10.5.3
if: steps.release.outputs.released == 'true'
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
tag: ${{ steps.release.outputs.tag }}

- name: Upload | Distribution Artifacts
uses: actions/upload-artifact@v4
if: steps.release.outputs.released == 'true'
with:
name: distribution-artifacts
path: dist
if-no-files-found: error

deploy:
# 1. Separate out the deploy step from the publish step to run each step at
# the least amount of token privilege
# 2. Also, deployments can fail, and its better to have a separate job if you need to retry
# and it won't require reversing the release.
runs-on: ubuntu-latest
needs: release
if: ${{ needs.release.outputs.released == 'true' }}

permissions:
contents: read
id-token: write

steps:
- name: Setup | Download Build Artifacts
uses: actions/download-artifact@v4
id: artifact-download
with:
name: distribution-artifacts
path: dist

- name: Publish package distributions to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
with:
packages-dir: dist
print-hash: true
verbose: true
2 changes: 1 addition & 1 deletion .python-version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
3.12
3.14
1 change: 0 additions & 1 deletion examples/composite_literal/beet.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
name: bolt-expressions-composite-literal
minecraft: "1.20"

data_pack:
load: [src]
Expand Down
1 change: 0 additions & 1 deletion examples/operation_condition/beet.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
name: bolt-expressions-operation-condition
minecraft: "1.20"

data_pack:
load: [src]
Expand Down
1 change: 0 additions & 1 deletion examples/source_typing/beet.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
name: bolt-expressions-source-typing
minecraft: "1.20"

data_pack:
load: [src]
Expand Down
25 changes: 11 additions & 14 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ dependencies = [
"bolt>=0.38",
"frozendict>=2.4.0,<3",
"bolt-control-flow>=0.2.0",
"rich>=12.4.4,<13",
"rich>=13.2.0",
]
description = "Provides pandas-like expressions capabilities to the bolt extension of mecha"
keywords = [
Expand All @@ -30,7 +30,7 @@ keywords = [
license = "MIT"
name = "bolt-expressions"
readme = "README.md"
requires-python = ">=3.10,<4.0"
requires-python = ">=3.14,<4.0"
version = "0.18.0"

[project.urls]
Expand All @@ -40,7 +40,7 @@ Repository = "https://github.com/rx-modules/bolt-expressions"

[dependency-groups]
dev = [
"python-semantic-release>=7.27.0,<8",
"python-semantic-release>=9.21.0",
"mudkip>=0.5.1",
"pytest-insta>=0.1.11",
"pygments",
Expand All @@ -50,6 +50,7 @@ dev = [
[tool.uv]

[tool.uv.sources]
bolt-control-flow = {git = "https://github.com/rx-modules/bolt-control-flow", rev = "chore/update-to-uv-py-3-14"}
pygments = {git = "https://github.com/rx-modules/pygments"}

[build-system]
Expand All @@ -59,21 +60,17 @@ requires = ["uv_build>=0.9.26,<0.10.0"]
[tool.pytest.ini_options]
addopts = "tests src/bolt_expressions" # --doctest-modules"
minversion = "6.0"
# doctest_optionflags = "NORMALIZE_WHITESPACE IGNORE_EXCEPTION_DETAIL ELLIPSIS"

[tool.black]
include = '\.pyi?$'
target-version = ["py310"]

[tool.isort]
profile = "black"
[tool.ruff.lint]
ignore = ["F403"] # allows "*" imports

[tool.semantic_release]
branch = "main"
build_command = "uv run mudkip build --update-gh-pages --repository https://x-access-token:${GH_TOKEN}@github.com/rx-modules/bolt-expressions"
build_command = "uv build"
major_on_zero = false
version_toml = "pyproject.toml:project.version"
version_variable = ["bolt_expressions/__init__.py:__version__"]

commit_author = "github-actions <action@github.com>"
version_toml = ["pyproject.toml:project.version"]
version_variables = ["src/bolt_expressions/__init__.py:__version__"]

[tool.mudkip]
preset = "furo"
Expand Down
2 changes: 1 addition & 1 deletion src/bolt_expressions/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ def add_objective(self, name: str, criteria: str = "dummy"):
def add_constant(self, value: int):
holder, obj = self.expr.const_score(value)

if not value in self.constants:
if value not in self.constants:
self.constants.add(value)
self.expr.init_commands.append(
f"scoreboard players set {holder} {obj} {value}"
Expand Down
11 changes: 6 additions & 5 deletions src/bolt_expressions/ast.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,15 @@
Reducer,
rule,
)
import nbtlib

from .sources import Source

__all__ = [
"RunExecuteTransformer",
"ConstantScoreChecker",
"ObjectiveChecker",
"SourceJsonConverter",
"SourceNBTConverter",
]


Expand Down Expand Up @@ -80,20 +81,20 @@ def objective(self, node: AstObjective):


@dataclass
class SourceJsonConverter:
class SourceNBTConverter:
converter: Callable[[Any, AstNode], AstNode]

def convert(self, obj: Any) -> Any:
if isinstance(obj, Source):
return obj.component()
return self.convert(obj.component())

if isinstance(obj, (list, tuple)):
list_value = cast(list[Any], obj)
return [self.convert(value) for value in list_value]
return nbtlib.List([self.convert(value) for value in list_value])

if isinstance(obj, dict):
dict_value = cast(dict[str, Any], obj)
return {key: self.convert(value) for key, value in dict_value.items()}
return nbtlib.Compound({key: self.convert(value) for key, value in dict_value.items()})

return obj

Expand Down
4 changes: 0 additions & 4 deletions src/bolt_expressions/check.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,8 @@
Any,
Iterable,
TypedDict,
Union,
get_args,
get_type_hints,
is_typeddict,
)

from beet import Context
Expand All @@ -16,7 +14,6 @@
from nbtlib import (
Array,
Byte,
Compound,
Double,
Float,
Int,
Expand All @@ -39,7 +36,6 @@
)
from .typing import (
NbtType,
NbtValue,
NumericNbtValue,
access_type,
convert_type,
Expand Down
3 changes: 0 additions & 3 deletions src/bolt_expressions/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,6 @@
]


from typing import Any


class TypeCheckError(Exception):
"""Type incompatibility during type checking"""

Expand Down
2 changes: 1 addition & 1 deletion src/bolt_expressions/expose.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

from .node import ExpressionNode
from .operations import Max, Min
from .sources import Source, binary_operator, length, operator_method
from .sources import Source, binary_operator, length

T = TypeVar("T")

Expand Down
2 changes: 0 additions & 2 deletions src/bolt_expressions/node.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,7 @@
from bolt.utils import internal
from mecha import AstChildren, AstCommand, AstRoot, Mecha
from mecha.contrib.nested_location import NestedLocationResolver
from nbtlib import Path # type: ignore
from pydantic import BaseModel
from rich.pretty import pprint

from .ast_converter import AstConverter
from .casting import TypeCaster
Expand Down
2 changes: 0 additions & 2 deletions src/bolt_expressions/operations.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@
from dataclasses import dataclass, replace
from typing import Any, ClassVar, Iterable

from bolt_expressions.optimizer import IrOperation, IrSource

from .literals import convert_node
from .node import ExpressionNode, ResultType, UnrollHelper
from .optimizer import (
Expand Down
1 change: 0 additions & 1 deletion src/bolt_expressions/optimizer.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@
Path,
String,
)
from rich.pretty import pprint

from .typing import (
Accessor,
Expand Down
6 changes: 3 additions & 3 deletions src/bolt_expressions/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
ConstantScoreChecker,
ObjectiveChecker,
RunExecuteTransformer,
SourceJsonConverter,
SourceNBTConverter,
)
from .expose import wrapped_len, wrapped_max, wrapped_min
from .node import Expression
Expand Down Expand Up @@ -54,9 +54,9 @@ def bolt_expressions(ctx: Context):
handler = module_attribute_handler(
ctx, runtime.helpers["get_attribute_handler"], api
)
json_converter = SourceJsonConverter(runtime.helpers["interpolate_json"])
nbt_converter = SourceNBTConverter(runtime.helpers["interpolate_nbt"])
runtime.helpers["get_attribute_handler"] = handler
runtime.helpers["interpolate_json"] = json_converter
runtime.helpers["interpolate_nbt"] = nbt_converter

runtime.expose("min", partial(wrapped_min, runtime.globals.get("min", min)))
runtime.expose("max", partial(wrapped_max, runtime.globals.get("max", max)))
Expand Down
Loading