From 1b487118488662882b8fa432ae499c97cbf20195 Mon Sep 17 00:00:00 2001 From: Vijai Kumar S Date: Mon, 8 Jul 2024 17:25:46 +0530 Subject: [PATCH 1/2] Start with fixing the problematic enum in ACT. The current patch done after python binding generation is now automated inside act. The scope needs to be expanded across the script --- Source/buildbindingpython.go | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/Source/buildbindingpython.go b/Source/buildbindingpython.go index 1837f9db..cdd1eebf 100644 --- a/Source/buildbindingpython.go +++ b/Source/buildbindingpython.go @@ -41,6 +41,15 @@ import ( "strings" ) +// Keep a map of reserved keywords in Python +var pythonReservedKeywords = map[string]bool{ + "False": true, "None": true, "True": true, "and": true, "as": true, "assert": true, "async": true, + "await": true, "break": true, "class": true, "continue": true, "def": true, "del": true, "elif": true, + "else": true, "except": true, "finally": true, "for": true, "from": true, "global": true, "if": true, + "import": true, "in": true, "is": true, "lambda": true, "nonlocal": true, "not": true, "or": true, + "pass": true, "raise": true, "return": true, "try": true, "while": true, "with": true, "yield": true, +} + // BuildBindingPythonDynamic builds dynamic Python bindings of a library's API in form of explicitly loaded // functions handles. func BuildBindingPythonDynamic(componentdefinition ComponentDefinition, outputFolder string, outputFolderExample string, indentString string) error { @@ -179,7 +188,12 @@ func buildDynamicPythonImplementation(componentdefinition ComponentDefinition, w w.Writeln("class %s(CTypesEnum):", enum.Name) for j:= 0; j Date: Sat, 17 Aug 2024 13:12:50 +0200 Subject: [PATCH 2/2] Extend the reserved keyword check across the entire Python binding --- .gitignore | 5 +++- Source/actutils.go | 41 ++++++++++++++++++++++++++ Source/automaticcomponenttoolkit.go | 9 ++++-- Source/buildbindingpython.go | 45 ++++++++++++++++++++++------- 4 files changed, 85 insertions(+), 15 deletions(-) diff --git a/.gitignore b/.gitignore index f9b9a402..0df76f45 100644 --- a/.gitignore +++ b/.gitignore @@ -25,4 +25,7 @@ Examples/**/obj debug .vscode -.DS_Store \ No newline at end of file +.DS_Store + +# Jetbrains +.idea/ diff --git a/Source/actutils.go b/Source/actutils.go index d503143b..8662cbda 100644 --- a/Source/actutils.go +++ b/Source/actutils.go @@ -34,11 +34,52 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package main import ( + "errors" + "fmt" + "log" "os" ) +var ( + ErrPythonBuildFailed = errors.New("failed to build dynamic Python implementation") + ErrFileDeletionFailed = errors.New("failed to write to output file") + ErrReservedKeyword = errors.New("failed to generate bindings as you are using a reserved keyword") +) + +// Keep a map of reserved keywords in Python +var pythonReservedKeywords = map[string]bool{ + "False": true, "None": true, "True": true, "and": true, "as": true, "assert": true, "async": true, + "await": true, "break": true, "class": true, "continue": true, "def": true, "del": true, "elif": true, + "else": true, "except": true, "finally": true, "for": true, "from": true, "global": true, "if": true, + "import": true, "in": true, "is": true, "lambda": true, "nonlocal": true, "not": true, "or": true, + "pass": true, "raise": true, "return": true, "try": true, "while": true, "with": true, "yield": true, +} + // FileExists returns true if and only if the file in a given path exists func FileExists(path string) (bool) { _, err := os.Stat(path); return !os.IsNotExist(err); +} + +// ReservedKeywordExit logs the formatted error, deletes the partially created file, and returns a named error. +func ReservedKeywordExit(bindingPath string, format string, a ...interface{}) error { + // Format the message using variadic arguments + msg := fmt.Sprintf(format, a...) + + // Log the error message + log.Printf("%s", msg) + + // Attempt to delete the partially created file + log.Printf("Deleting partially created binding file: %s", bindingPath) + err := os.Remove(bindingPath) + if err != nil { + // Log and return a wrapped error with context + log.Printf("Failed to delete incomplete file %s: %v", bindingPath, err) + return fmt.Errorf("%w: %v", ErrFileDeletionFailed, err) + } + + log.Printf("Deleted binding file") + + // Return the reserved keyword error + return ErrReservedKeyword } \ No newline at end of file diff --git a/Source/automaticcomponenttoolkit.go b/Source/automaticcomponenttoolkit.go index 760a3167..56310ca3 100644 --- a/Source/automaticcomponenttoolkit.go +++ b/Source/automaticcomponenttoolkit.go @@ -732,10 +732,13 @@ func main() { err = createComponent(component, outfolderBase, bindingsDirectoryOverride, interfacesDirectoryOverride, stubDirectoryOverride, suppressBindings, suppressStub, suppressInterfaces, suppressSubcomponents, suppressLicense, suppressExamples) if (err != nil) { - log.Println("Fatal error") - log.Fatal(err) + if err == ErrPythonBuildFailed { + log.Println("Python binding generation failed (Due to usage of reserved keywords)") + } else { + log.Println("Fatal error") + log.Fatal(err) + } } else { log.Println("Success") } - } diff --git a/Source/buildbindingpython.go b/Source/buildbindingpython.go index cdd1eebf..8c3b8e31 100644 --- a/Source/buildbindingpython.go +++ b/Source/buildbindingpython.go @@ -41,14 +41,9 @@ import ( "strings" ) -// Keep a map of reserved keywords in Python -var pythonReservedKeywords = map[string]bool{ - "False": true, "None": true, "True": true, "and": true, "as": true, "assert": true, "async": true, - "await": true, "break": true, "class": true, "continue": true, "def": true, "del": true, "elif": true, - "else": true, "except": true, "finally": true, "for": true, "from": true, "global": true, "if": true, - "import": true, "in": true, "is": true, "lambda": true, "nonlocal": true, "not": true, "or": true, - "pass": true, "raise": true, "return": true, "try": true, "while": true, "with": true, "yield": true, -} +// Store the python file path +var pythonBindingFile = ""; + // BuildBindingPythonDynamic builds dynamic Python bindings of a library's API in form of explicitly loaded // functions handles. @@ -59,6 +54,7 @@ func BuildBindingPythonDynamic(componentdefinition ComponentDefinition, outputFo libraryname := componentdefinition.LibraryName DynamicPythonImpl := path.Join(outputFolder, namespace+".py"); + pythonBindingFile = DynamicPythonImpl; log.Printf("Creating \"%s\"", DynamicPythonImpl) dynpythonfile, err := CreateLanguageFile (DynamicPythonImpl, indentString) if err != nil { @@ -71,6 +67,9 @@ func BuildBindingPythonDynamic(componentdefinition ComponentDefinition, outputFo err = buildDynamicPythonImplementation(componentdefinition, dynpythonfile) if err != nil { + if err == ErrReservedKeyword { + return ErrPythonBuildFailed + } return err; } @@ -150,6 +149,9 @@ func buildDynamicPythonImplementation(componentdefinition ComponentDefinition, w w.Writeln(" SUCCESS = 0") for i := 0; i