diff --git a/.github/workflows/bench.yml b/.github/workflows/bench.yml index ea9debb..043d429 100644 --- a/.github/workflows/bench.yml +++ b/.github/workflows/bench.yml @@ -16,7 +16,7 @@ jobs: strategy: matrix: - os: [ubuntu-20.04, ubuntu-18.04, macos-latest] + os: [ubuntu-22.04, macos-latest] python: ["3.11"] go: ["1.19"] diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c1a1e30..7628f32 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -16,7 +16,7 @@ jobs: strategy: matrix: - os: [ubuntu-18.04] + os: [ubuntu-22.04] python: [3.7, 3.8, "3.10", "3.11"] go: ["1.19", "1.16"] diff --git a/changes.rst b/changes.rst index 042a0b1..b3856a5 100644 --- a/changes.rst +++ b/changes.rst @@ -1,5 +1,13 @@ .. currentmodule:: bitproto +Version 1.1.1 +------------- + +.. _version-1.1.1 + +- Fix bug: enum importting other bitproto's field name generation bug. #53 #52 +- Fix bug: import statements of bitproto importings should be placed ahead of other declarations. #53 + Version 1.1.0 ------------- diff --git a/compiler/bitproto/__init__.py b/compiler/bitproto/__init__.py index 8d7b784..ec3f16b 100644 --- a/compiler/bitproto/__init__.py +++ b/compiler/bitproto/__init__.py @@ -4,9 +4,9 @@ Bit level data interchange format. -:copyright: (c) 2020~2022 by Chao Wang . +:copyright: (c) 2020~2023 by Chao Wang . """ -__version__ = "1.1.0" +__version__ = "1.1.1" __description__ = "bit level data interchange format." diff --git a/compiler/bitproto/linter.py b/compiler/bitproto/linter.py index 610c82a..77224fb 100644 --- a/compiler/bitproto/linter.py +++ b/compiler/bitproto/linter.py @@ -80,7 +80,6 @@ def lint(self, proto: Proto) -> int: """ warning_count: int = 0 for definition_type in SUPPORTED_TYPES: - items: List[Tuple[str, Definition]] if definition_type is Proto: # proto is not a member of itself. items = [(proto.name, proto)] diff --git a/compiler/bitproto/renderer/formatter.py b/compiler/bitproto/renderer/formatter.py index d9d06ee..d8646a0 100644 --- a/compiler/bitproto/renderer/formatter.py +++ b/compiler/bitproto/renderer/formatter.py @@ -64,7 +64,6 @@ @unique class CaseStyle(Enum_): - KEEP = 0 SNAKE = 1 UPPER = 2 @@ -401,17 +400,23 @@ def format_definition_name( Joins a with a dot delimer if given definition is a definition imported. """ definition_name = self.format_definition_name_inner_proto(d, class_) - protos = [scope for scope in d.scope_stack if isinstance(scope, Proto)] - if len(protos) <= 1: + parent = d.scope_stack[-1] + + if not isinstance(parent, Proto): + # Member of Non-Proto scopes: message, enum etc. return definition_name if not self.support_import_as_member(): return definition_name - proto = protos[-1] # Last is the imported parent. - items = [self._get_definition_name(proto), definition_name] - return self.delimer_cross_proto().join(items) + if not parent.scope_stack: + # `parent` is the top proto. + return definition_name + # `parent` is imported in another proto. + return self.delimer_cross_proto().join( + [self._get_definition_name(parent), definition_name] + ) @final def format_name_related_to_definition( diff --git a/compiler/bitproto/renderer/impls/go/renderer.py b/compiler/bitproto/renderer/impls/go/renderer.py index 75c9f3e..47efb06 100644 --- a/compiler/bitproto/renderer/impls/go/renderer.py +++ b/compiler/bitproto/renderer/impls/go/renderer.py @@ -54,13 +54,6 @@ def render(self) -> None: self.push(f'bp "{GO_LIB_IMPORT_PATH}"', indent=1) self.push(f")") - self.push_empty_line() - - self.push_comment("Avoid possible golang import not used error") - self.push(f"var formatInt = strconv.FormatInt") - self.push(f"var jsonMarshal = json.Marshal") - self.push(f"var _ = bp.Useless") - class BlockImportChildProto(BlockBindProto[F]): @override(Block) @@ -81,6 +74,15 @@ def separator(self) -> str: return "\n" +class BlockAvoidGeneralImportsNotUsed(Block): + @override(Block) + def render(self) -> None: + self.push_comment("Avoid possible golang import not used error") + self.push(f"var formatInt = strconv.FormatInt") + self.push(f"var jsonMarshal = json.Marshal") + self.push(f"var _ = bp.Useless") + + class BlockAliasMethodBase(BlockBindAlias[F]): @cached_property def method_receiver(self) -> str: @@ -750,6 +752,7 @@ def blocks(self) -> List[Block[F]]: BlockPackageName(self.bound), BlockGeneralImports(), BlockImportChildProtoList(), + BlockAvoidGeneralImportsNotUsed(), BlockBoundDefinitionList(), ] diff --git a/compiler/bitproto/utils.py b/compiler/bitproto/utils.py index 2786e15..6c08269 100644 --- a/compiler/bitproto/utils.py +++ b/compiler/bitproto/utils.py @@ -206,7 +206,6 @@ def __delattr__(self, name): setattr(class_, "__delattr__", __delattr__) if post_init: - init_func = getattr(class_, "__init__") def decorate_init(func): diff --git a/lib/py/bitprotolib/bp.py b/lib/py/bitprotolib/bp.py index c9daf70..14d7efa 100644 --- a/lib/py/bitprotolib/bp.py +++ b/lib/py/bitprotolib/bp.py @@ -191,7 +191,9 @@ class MessageBase(Accessor): def to_dict(self) -> Dict[str, Any]: """Converts this message to a dict.""" - return asdict(self, dict_factory=getattr(self, "dict_factory", dict)) + return asdict( + self, dict_factory=getattr(self, "dict_factory", dict) # type:ignore + ) def to_json( self, indent: Optional[int] = None, separators: Optional[Tuple[str, str]] = None diff --git a/tests/test_encoding/encoding-cases/issue-52/Makefile b/tests/test_encoding/encoding-cases/issue-52/Makefile new file mode 100644 index 0000000..86adf83 --- /dev/null +++ b/tests/test_encoding/encoding-cases/issue-52/Makefile @@ -0,0 +1,47 @@ +PY_SOURCE_FILE=main.py +BIN=main + +BP_LIB_DIR=../../../../../lib/c +BP_LIC_C_PATH=$(BP_LIB_DIR)/bitproto.c + +C_SOURCE_FILE=main.c +C_SOURCE_FILE_LIST=$(C_SOURCE_FILE) a_bp.c b_bp.c $(BP_LIC_C_PATH) +C_BIN=$(BIN) +CC_OPTIMIZATION_ARG?= + +GO_BIN=$(BIN) + + +bp-c: + @bitproto c a.bitproto c/ + @bitproto c b.bitproto c/ + +bp-py: + @bitproto py a.bitproto py/ + @bitproto py b.bitproto py/ + +bp-go: + @bitproto go a.bitproto go/bp/a $(OPTIMIZATION_MODE_ARGS) + @bitproto go b.bitproto go/bp/b $(OPTIMIZATION_MODE_ARGS) + +build-c: bp-c + @cd c && $(CC) $(C_SOURCE_FILE_LIST) -I. -I$(BP_LIB_DIR) -o $(C_BIN) $(CC_OPTIMIZATION_ARG) + +build-go: bp-go + @cd go && go build -o $(GO_BIN) + +build-py: bp-py + +run-c: build-c + @cd c && ./$(C_BIN) + +run-go: build-go + @cd go && ./$(GO_BIN) + +run-py: build-py + @cd py && python $(PY_SOURCE_FILE) + +clean: + @rm -fr c/$(C_BIN) go/$(GO_BIN) */*_bp.* */**/*_bp.* py/__pycache__ + +run: run-py run-c run-go diff --git a/tests/test_encoding/encoding-cases/issue-52/a.bitproto b/tests/test_encoding/encoding-cases/issue-52/a.bitproto new file mode 100644 index 0000000..9a3a965 --- /dev/null +++ b/tests/test_encoding/encoding-cases/issue-52/a.bitproto @@ -0,0 +1,7 @@ +proto a + +import bb "b.bitproto" + +message A { + bb.X x = 1; +} diff --git a/tests/test_encoding/encoding-cases/issue-52/b.bitproto b/tests/test_encoding/encoding-cases/issue-52/b.bitproto new file mode 100644 index 0000000..68c8a5d --- /dev/null +++ b/tests/test_encoding/encoding-cases/issue-52/b.bitproto @@ -0,0 +1,7 @@ +proto b; + +option go.package_path = "github.com/hit9/bitproto/tests/test_encoding/encoding-cases/issue-52/go/bp/b"; + +enum X : uint1 { + OK = 0; +} diff --git a/tests/test_encoding/encoding-cases/issue-52/c/main.c b/tests/test_encoding/encoding-cases/issue-52/c/main.c new file mode 100644 index 0000000..36e63df --- /dev/null +++ b/tests/test_encoding/encoding-cases/issue-52/c/main.c @@ -0,0 +1,9 @@ +#include "a_bp.h" +#include "b_bp.h" +#include + +int main(void) { + struct A a = {.x = OK}; + assert(a.x == OK); + return 0; +} diff --git a/tests/test_encoding/encoding-cases/issue-52/go/bp/a/.gitkeep b/tests/test_encoding/encoding-cases/issue-52/go/bp/a/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/tests/test_encoding/encoding-cases/issue-52/go/bp/a/go.mod b/tests/test_encoding/encoding-cases/issue-52/go/bp/a/go.mod new file mode 100644 index 0000000..a120ed1 --- /dev/null +++ b/tests/test_encoding/encoding-cases/issue-52/go/bp/a/go.mod @@ -0,0 +1,3 @@ +module github.com/hit9/bitproto/tests/test_encoding/encoding-cases/issue-52/go/bp/a + +go 1.15 diff --git a/tests/test_encoding/encoding-cases/issue-52/go/bp/b/.gitkeep b/tests/test_encoding/encoding-cases/issue-52/go/bp/b/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/tests/test_encoding/encoding-cases/issue-52/go/bp/b/go.mod b/tests/test_encoding/encoding-cases/issue-52/go/bp/b/go.mod new file mode 100644 index 0000000..d9c619f --- /dev/null +++ b/tests/test_encoding/encoding-cases/issue-52/go/bp/b/go.mod @@ -0,0 +1 @@ +module github.com/hit9/bitproto/tests/test_encoding/encoding-cases/issue-52/go/bp/b diff --git a/tests/test_encoding/encoding-cases/issue-52/go/go.mod b/tests/test_encoding/encoding-cases/issue-52/go/go.mod new file mode 100644 index 0000000..5b27226 --- /dev/null +++ b/tests/test_encoding/encoding-cases/issue-52/go/go.mod @@ -0,0 +1,14 @@ +module github.com/hit9/bitproto/tests/test_encoding/encoding-cases/issue-52 + +replace github.com/hit9/bitproto/lib/go => ../../../../../lib/go + +replace github.com/hit9/bitproto/tests/test_encoding/encoding-cases/issue-52/go/bp/a => ./bp/a +replace github.com/hit9/bitproto/tests/test_encoding/encoding-cases/issue-52/go/bp/b => ./bp/b + +go 1.15 + +require ( + github.com/hit9/bitproto/lib/go v0.0.0-00010101000000-000000000000 // indirect + github.com/hit9/bitproto/tests/test_encoding/encoding-cases/issue-52/go/bp/a v0.0.0-00010101000000-000000000000 + github.com/hit9/bitproto/tests/test_encoding/encoding-cases/issue-52/go/bp/b v0.0.0-00010101000000-000000000000 +) diff --git a/tests/test_encoding/encoding-cases/issue-52/go/main.go b/tests/test_encoding/encoding-cases/issue-52/go/main.go new file mode 100644 index 0000000..b75d9ee --- /dev/null +++ b/tests/test_encoding/encoding-cases/issue-52/go/main.go @@ -0,0 +1,17 @@ +package main + +import ( + a "github.com/hit9/bitproto/tests/test_encoding/encoding-cases/issue-52/go/bp/a" + b "github.com/hit9/bitproto/tests/test_encoding/encoding-cases/issue-52/go/bp/b" +) + +func assert(condition bool) { + if !condition { + panic("assertion failed") + } +} + +func main() { + v := a.A{X: b.OK} + assert(v.X == b.OK) +} diff --git a/tests/test_encoding/encoding-cases/issue-52/py/main.py b/tests/test_encoding/encoding-cases/issue-52/py/main.py new file mode 100644 index 0000000..8f73934 --- /dev/null +++ b/tests/test_encoding/encoding-cases/issue-52/py/main.py @@ -0,0 +1,11 @@ +import a_bp +import b_bp + + +def main(): + a = a_bp.A() + assert a.x == b_bp.X.OK + + +if __name__ == "__main__": + main() diff --git a/tests/test_encoding/test_encoding.py b/tests/test_encoding/test_encoding.py index 7453799..c533e69 100644 --- a/tests/test_encoding/test_encoding.py +++ b/tests/test_encoding/test_encoding.py @@ -135,3 +135,13 @@ def test_encoding_signed() -> None: def test_encoding_complexx() -> None: _TestCase("complexx", support_optimization_mode=False).run() + + +def test_encoding_issue52() -> None: + _TestCase( + "issue-52", + langs=["py", "c"], + compare_output=False, + compare_output_as_json=False, + support_optimization_mode=False, + )