Skip to content

Commit 802e924

Browse files
Merge pull request #16 from Moo-Ack-Productions/milestone-4-1
BpyBuild 0.4.1
2 parents a0741ec + f27fb7f commit 802e924

File tree

21 files changed

+645
-241
lines changed

21 files changed

+645
-241
lines changed

.pre-commit-config.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,5 +20,10 @@ repos:
2020
hooks:
2121
# Run the linter.
2222
- id: ruff
23+
24+
# Sort imports
25+
- id: ruff
26+
args: [--select, I, --fix]
27+
2328
# Run the formatter.
2429
- id: ruff-format

CHANGELOG.txt

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,109 @@
11
# Changelog
22

33

4+
## [0.4.1] - 2024-06-01
5+
6+
7+
### Fix: Properly install addon if not already installed
8+
9+
Signed-off-by: Mahid Sheikh <mahid@standingpad.org>
10+
11+
### Fix: Removed redundant argument in build_config
12+
13+
14+
15+
### Docs: Added details on name and file restrictions
16+
17+
### Docs: Removed tests.md for now
18+
19+
### Docs: Clarified Getting Started
20+
21+
Co-authored-by: Patrick W. Crawford <theduckcow@live.com>
22+
### Docs: Added missing period to README
23+
24+
### Docs: Added info on using BpyBuild in addon tests
25+
26+
### Docs: Added info on tests in CONTRIBUTING.md
27+
28+
### Docs: Fixed warning in actions guide
29+
30+
31+
32+
### Feat: Add version shorthands like + and ..
33+
34+
The idea of version shorthands is to reduce the need for comically large
35+
config files with giant lists of versions. Instead of the following:
36+
37+
```yaml
38+
install_versions:
39+
- 2.8
40+
...
41+
- 4.0
42+
```
43+
44+
Developers can now do this:
45+
46+
```yaml
47+
install_versions:
48+
- 2.8..4.0
49+
```
50+
51+
Way better for developer experience
52+
53+
Signed-off-by: Mahid Sheikh <mahid@standingpad.org>
54+
55+
### Feat: Added string input checks
56+
57+
Seeing as build configs are basically untrusted user input, the current
58+
system of not checking if the strings are valid is a pretty big security
59+
risk. As such, BpyBuild now checks multiple parts of the config to make
60+
sure that strings do not contain harmful characters, by limiting what
61+
characters are allowed in the first place.
62+
63+
### Feat: Improved errors for config issues
64+
65+
### Feat: Added error handling for config parsing
66+
67+
### Feat: Actions can now be declared without a script
68+
69+
70+
71+
### Refactor: Changed how install_versions is checked
72+
73+
Previously we checked install_versions with a try-except statement that
74+
would attempt to convert the value to a float and throw an error if it
75+
failed. However, floats in YAML are actual floats, so we can just check
76+
if the float is of the type float with isinstance(ver, float)
77+
78+
### Refactor: Migrated from cattrs to manual parsing
79+
80+
Although cattrs was useful for parsing the config data to an attrs
81+
object, it had issues with errors being undecipherable to the end user.
82+
In addition, cattrs seemed too overkill for a simple config. Thus, we've
83+
moved away from cattrs and implemented our own basic parser to manually
84+
parse and construct the Config object, with better errors.
85+
86+
87+
88+
### Style: Added docs for BpyError and BpyWarning
89+
90+
### Style: Applied Ruff's import sorter to all files
91+
92+
### Style: Updated codedocs
93+
94+
### Style: Switch to native types with __futures__
95+
96+
### Style: Added TypeDicts for annotation YAML data
97+
98+
99+
100+
### Test: Remove xgettext-replacement test
101+
102+
Signed-off-by: Mahid Sheikh <mahid@standingpad.org>
103+
104+
105+
<!-- generated by git-cliff -->
106+
4107
## [0.4.0] - 2024-04-18
5108

6109

CONTRIBUTING.md

Lines changed: 66 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
# Contributing Guide
22
Hey there, looks like you're interested in contributing to Bpy-Build! To get started, read this guide which has a lot of important information regarding contributions.
33

4+
> [!CAUTION]
5+
> For those that have contributed to MCprep in the past, note that BpyBuild has stricter contributing requirements in comparison.
6+
47
This guide will assume you already know how to use Git and understand enough Python to know how to use type annotations.
58

69
# Building Bpy-Build
@@ -17,7 +20,7 @@ The Bpy-Build project does not allow dynamic typing at all, period. The reasons
1720
- Reliability: Dynamic typing is an extra source of bugs to deal with
1821
- Cleanliness: Dynamic typing ends up looking extremely ugly
1922

20-
All functions must be type annotated. It is possible to add `@typing.no_type_check` above functions that need to call untyped code (which is considered dynamic by Mypy, the type checker used here) to prevent Mypy from throwing errors with untyped functions. However, instances of `@typing.no_type_check` in contributions will cause said contributions to be rejected. Thus, for contributions, we creating wrappers for untyped functions and performing casts.
23+
All functions must be type annotated. Instances of `@typing.no_type_check` or `# type: ignore` that aren't justified with a comment will cause said contributions to be rejected. Thus, for contributions, we creating wrappers for untyped functions and performing casts.
2124

2225
We require every commit pass Mypy checks, which we utilize pre-commit hooks for (see the Pre-Commit Hooks section for more). Alternatively, you can use the following:
2326
```sh
@@ -26,6 +29,17 @@ just mypy
2629
# Or if you don't have just installed
2730
poetry run mypy --pretty bpy_addon_build
2831
```
32+
33+
All commits will be checked for passing tests, and PRs will be rejected if one does not pass the Mypy checks.
34+
35+
## Typing
36+
Although BpyBuild supports Python 3.8, we try to use [PEP 585](https://peps.python.org/pep-0585/) types wherever possible, using `annotations` from the `__futures__` module. This means for the most part, `dict`, `list`, `tuple`, etc. can be used with little issue. That being said, the following has to be kept in mind:
37+
- These annotations are hackish in the CPython interpreter, so these can't be used for `attrs`/`cattrs` classes, or if `cast` needs to be performed. In those cases, their `typing` counterparts will have to be used
38+
- New files that use PEP 585 annotations will need to have `from __future__ import annotations` as the first import in the file
39+
- Although it would be nice, [PEP 604](https://peps.python.org/pep-0604/) syntax for Unions is not an option with `__futures__` in Python 3.8
40+
41+
Despite some of the headaches with using annotations from `__futures__`, we encourage their use so that migrating becomes less of a burden in the future.
42+
2943
# Formatting
3044
All commits must be formatted with https://github.com/astral-sh/ruff. We have a pre-commit hook for this (see the Pre-Commit Hooks section).
3145

@@ -47,7 +61,13 @@ characters long (for reasons related to terminal
4761
length)
4862
```
4963

50-
For a small commit, like say fixing a syntax error or typo, it may be sufficient to have just a summary, but most commits will need justification. Commits should justify the changes made, not repeat them like a parrot (that's what the 50 character summary and Git diffs are for). Failiure to follow proper commit format may prevent a contribution from being accepted into Bpy-Build, so please follow the format.
64+
In addition, the 50 character summary at the top must follow the [Conventional Commit Format](https://www.conventionalcommits.org/en/v1.0.0/).
65+
66+
Commits that fall under the following **ARE REQUIRED** to give justification:
67+
- `feat`
68+
- `refactor`
69+
70+
That being said, it's best to give justification for every commit.
5171

5272
To make meeting this requirement easier, one can make a `.gitmessage` file somewhere with the following :
5373
```
@@ -70,6 +90,50 @@ git config --local commit.verbose true
7090

7191
This will make all commits use that template and perform verbose commits (where commits are opened as their own file, with saving and closing creating the commit itself).
7292

93+
## Commits MUST *fully commit* to a given change
94+
When a commit is made, the change stated in the commit must be fully committed to. For example, a commit that states `refactor: Use sys.exit method for program exit` **must** implement that change across all files, not just one or two.
95+
96+
## Signing Off Commits
97+
BpyBuild requires signing off of all commits, to certify the origin of the change. When you sign off of a commit in BpyBuild, you certify that the commit was made in line with the Developer's Certificate of Origin:
98+
99+
> Developer's Certificate of Origin 1.1
100+
> By making a contribution to this project, I certify that:
101+
>
102+
> a. The contribution was created in whole or in part by me and I have the right to submit it under the open source license indicated in the file; or \
103+
> b. The contribution is based upon previous work that, to the best of my knowledge, is covered under an appropriate open source license and I have the right under that license to submit that work with modifications, whether created in whole or in part by me, under the same open source license (unless I am permitted to submit under a different license), as indicated in the file; or \
104+
> c. The contribution was provided directly to me by some other person who certified (a), (b) or (c) and I have not modified it. \
105+
> d I understand and agree that this project and the contribution are public and that a record of the contribution (including all personal information I submit with it, including my sign-off) is maintained indefinitely and may be redistributed consistent with this project or the open source license(s) involved.
106+
107+
If indeed the change was made in line with the Developer's Certificate of Origin, add the following at the end of the commit:
108+
```
109+
Signed-off-by: Random J Developer <random@developer.example.org>
110+
```
111+
112+
**This much be your real name and a working email address.**
113+
114+
If the change was given to you by someone else, and you have permission to contribute it here, that change must be signed off by the person who gave the change to you, and anyone before that (basically a chain of sign offs). Example:
115+
```
116+
<commit message and summery by John Doe, who recieved the change from Jane Doe>
117+
118+
Signed-off-by: John Doe <johndoe@email.com>
119+
Signed-off-by: Jane Doe <janedoe@email.com>
120+
```
121+
122+
If multiple authors were involved in writing the change, then `Co-developed-by` must be present for both you and any other authors involved in the change. As an example with 2 authors:
123+
```
124+
<commit message and summery>
125+
126+
Co-developed-by: John Doe <johndoe@email.com>
127+
Signed-off-by: John Doe <johndoe@email.com>
128+
Co-developed-by: Jane Doe <janedoe@email.com>
129+
Signed-off-by: Jane Doe <janedoe@email.com>
130+
```
131+
132+
> [!NOTE]
133+
> *For those interested in where this convention comes from*
134+
>
135+
> Signing off commits was first adopted by the Linux Kernel after [the SCO lawsuits against IBM](https://en.wikipedia.org/wiki/SCO_Group,_Inc._v._International_Business_Machines_Corp.). One of SCO's main arguments was that the Linux Kernel used code from SCO's version of UNIX. Although this turned out to be false, the Linux Kernel project soon required developers to certify that their commits were allowed to be part of the Linux Kernel with signing off.
136+
73137
# Pre-Commit Hooks
74138
To make things easier for developers, we define pre-commit hooks that allow developers to commit changes and automatically have Mypy and Black run on said commit. This is not required
75139
Set up [pre-commit](https://pre-commit.com/). This must be installed separately and is not included in the Poetry dependencies. Then run `pre-commit install`. This will set up pre-commit hooks for the following:

bpy_addon_build/__init__.py

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -27,24 +27,31 @@
2727
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2828
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2929

30-
from typing import Dict, List, Optional, Union
30+
from __future__ import annotations
31+
32+
from decimal import getcontext
33+
from typing import Optional
34+
3135
import yaml
36+
from rich.console import Console
37+
3238
from bpy_addon_build.api import Api
3339
from bpy_addon_build.build_context import hooks
3440
from bpy_addon_build.build_context.build import build
3541
from bpy_addon_build.build_context.install import install
42+
from bpy_addon_build.config import Config, ConfigDict, build_config
3643

37-
from bpy_addon_build.config import Config
3844
from . import args
3945
from .build_context.core import BuildContext
40-
from cattrs.preconf.pyyaml import make_converter
41-
from rich.console import Console
4246

4347

4448
def main() -> None:
49+
# Set the precision for Decimal to
50+
# 3, which corresponds to X.XX
51+
getcontext().prec = 3
52+
4553
cli = args.parse_args()
4654
console = Console()
47-
converter = make_converter()
4855

4956
if cli.debug_mode:
5057
console.print(cli)
@@ -54,10 +61,8 @@ def main() -> None:
5461

5562
context: Optional[BuildContext] = None
5663
with open(cli.path, "r") as f:
57-
data: Dict[str, Union[str, List[float], Dict[str, Dict[str, str]]]] = (
58-
yaml.safe_load(f)
59-
)
60-
config: Config = converter.structure(data, Config)
64+
data: ConfigDict = yaml.safe_load(f)
65+
config: Config = build_config(data)
6166
api: Api = Api(config, cli.path, cli.debug_mode)
6267
context = BuildContext(cli.path, config, cli, api)
6368

bpy_addon_build/api/__init__.py

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,27 @@
1-
from types import ModuleType
2-
from typing import Dict, Optional
1+
from __future__ import annotations
2+
3+
import sys
4+
from dataclasses import dataclass
35
from pathlib import Path
6+
from types import ModuleType
7+
from typing import Optional
8+
49
from bpy_addon_build.config import Config
5-
from dataclasses import dataclass
6-
import sys
710

811

912
@dataclass
1013
class BpyError:
14+
"""Error object for BpyBuild"""
15+
16+
# Message to print in the console
1117
msg: str
1218

1319

1420
@dataclass
1521
class BpyWarning:
22+
"""Warning object for BpyBuild"""
23+
24+
# Message to print in the console
1625
msg: str
1726

1827

@@ -30,19 +39,21 @@ class Api:
3039
3140
Attributes
3241
----------
33-
build_actions: Dict[str, str]
42+
build_actions: dict[str, str]
3443
Action name to script file
3544
36-
action_mods: Dict[str, ModuleType]
45+
action_mods: dict[str, ModuleType]
3746
Action name to module
3847
"""
3948

4049
def __init__(self, conf: Config, config_path: Path, debug_mode: bool) -> None:
4150
if conf.build_actions is not None:
4251
self.build_actions = conf.build_actions
43-
self.action_mods: Dict[str, ModuleType] = {}
52+
self.action_mods: dict[str, ModuleType] = {}
4453

4554
for action in self.build_actions:
55+
if self.build_actions[action].script is None:
56+
continue
4657
mod = self.add_modules(config_path, action, debug_mode)
4758
if mod is None:
4859
continue
@@ -53,9 +64,10 @@ def add_modules(
5364
) -> Optional[ModuleType]:
5465
import importlib.util
5566

56-
path = config_path.parent.resolve().joinpath(
57-
Path(self.build_actions[action].script)
58-
)
67+
script = self.build_actions[action].script
68+
if script is None:
69+
return None
70+
path = config_path.parent.resolve().joinpath(Path(script))
5971

6072
# Add the parent folder of the script to the sys path
6173
# so that we don't get module errors

bpy_addon_build/args.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from pathlib import Path
22
from typing import List, Optional, cast
3-
from attrs import define, field, Attribute
3+
4+
from attrs import Attribute, define, field
45

56

67
# Must be ignored to pass Mypy as this has

bpy_addon_build/build_context/build.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1-
from bpy_addon_build.build_context.core import BuildContext
2-
from bpy_addon_build.build_context import hooks
31
import shutil
42
from pathlib import Path
53

4+
from bpy_addon_build.build_context import hooks
5+
from bpy_addon_build.build_context.core import BuildContext
6+
67

78
def combine_with_build(ctx: BuildContext, path: Path) -> Path:
89
"""

bpy_addon_build/build_context/core.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
1+
from __future__ import annotations
2+
13
from pathlib import Path
2-
from typing import List
4+
35
from attrs import define
6+
from rich.console import Console
7+
48
from bpy_addon_build.api import Api
59
from bpy_addon_build.args import Args
6-
710
from bpy_addon_build.config import Config
8-
from rich.console import Console
911

10-
INSTALL_PATHS: List[str] = [
12+
INSTALL_PATHS: list[str] = [
1113
"~/AppData/Roaming/Blender Foundation/Blender/{0}/scripts/addons",
1214
"~/Library/Application Support/Blender/{0}/scripts/addons",
1315
"~/.config/blender/{0}/scripts/addons",

0 commit comments

Comments
 (0)