diff --git a/exasol_script_languages_container_tool/lib/models/language_definition_components.py b/exasol_script_languages_container_tool/lib/models/language_definition_components.py index f688c80..c373dfc 100644 --- a/exasol_script_languages_container_tool/lib/models/language_definition_components.py +++ b/exasol_script_languages_container_tool/lib/models/language_definition_components.py @@ -13,12 +13,20 @@ class SLCLanguage(Enum): @dataclass class SLCParameter: + """ + Key value pair of a parameter passed to the Udf client. For example: `lang=java` + """ + key: str value: List[str] @dataclass class UdfClientBucketPath: + """ + Path to the udf client relative to a BucketFS path. For example `buckets/bfsdefault/default/exaudf/exaudfclient_py3` + """ + bucketfs_name: str bucket_name: str executable: PurePosixPath @@ -29,6 +37,11 @@ def __str__(self) -> str: @dataclass class UdfClientRelativePath: + """ + Path to the udf client relative to the Script Languages Container root path. + For example `/exaudf/exaudfclient_py3` + """ + executable: PurePosixPath def __str__(self) -> str: @@ -37,6 +50,10 @@ def __str__(self) -> str: @dataclass class ChrootPath: + """ + Path to the Script Languages Container root directory in the BucketFS. For example: `/bfsdefault/default/my_slc` + """ + bucketfs_name: str bucket_name: str path_in_bucket: Optional[PurePosixPath] = None @@ -47,6 +64,10 @@ def __str__(self) -> str: @dataclass class LanguageDefinitionURL: + """ + Contains all necessary components of the Language Definition URL. + """ + protocol: str parameters: List[SLCParameter] chroot_path: ChrootPath @@ -70,6 +91,10 @@ def __str__(self) -> str: @dataclass class BuiltInLanguageDefinitionURL: + """ + Contains the language of the Builtin Language Definition. + """ + language: SLCLanguage def __str__(self) -> str: @@ -78,6 +103,11 @@ def __str__(self) -> str: @dataclass class LanguageDefinitionComponents: + """ + Contains the alias and the Language Definition URL if custom Script Languages Container or BuiltIn Language + Definition if BuiltIn language. + """ + alias: str url: Union[LanguageDefinitionURL, BuiltInLanguageDefinitionURL] diff --git a/exasol_script_languages_container_tool/lib/models/language_definitions_builder.py b/exasol_script_languages_container_tool/lib/models/language_definitions_builder.py index 0bd4353..dbcb910 100644 --- a/exasol_script_languages_container_tool/lib/models/language_definitions_builder.py +++ b/exasol_script_languages_container_tool/lib/models/language_definitions_builder.py @@ -6,6 +6,11 @@ class LanguageDefinitionsBuilder: + """ + Provides generation of "ALTER SESSION", "ALTER SYSTEM" commands and pure language definitions string + replacing the aliases provides in the source Language Definition Components with custom aliases. + """ + def __init__(self, lang_def_components: List[LanguageDefinitionComponents]): self.lang_def_components = lang_def_components self.custom_aliases: Dict[str, str] = dict() diff --git a/exasol_script_languages_container_tool/lib/tasks/upload/language_def_parser.py b/exasol_script_languages_container_tool/lib/tasks/upload/language_def_parser.py index 442da8e..c376310 100644 --- a/exasol_script_languages_container_tool/lib/tasks/upload/language_def_parser.py +++ b/exasol_script_languages_container_tool/lib/tasks/upload/language_def_parser.py @@ -29,7 +29,7 @@ def _parse_builtin_language_definition(url: str) -> BuiltInLanguageDefinitionURL def _build_udf_client_abs_path_from_fragments( fragment_parts: Tuple[str, ...] ) -> UdfClientBucketPath: - if len(fragment_parts) < 4 or fragment_parts[0] != "buckets": + if len(fragment_parts) < 4: raise ValueError( f"Expected format of the fragment in the URL for a bucket udf client path is " f"'/buckets///' or" @@ -50,18 +50,19 @@ def _parse_udf_client_path( fragment_path = PurePosixPath(fragment) fragment_parts = fragment_path.parts - if len(fragment_parts) == 0: + if len(fragment_parts) == 0 or ( + fragment_path.is_absolute() and len(fragment_parts) == 1 + ): raise ValueError("Udf client executable path must not be empty.") if fragment_path.is_absolute(): fragment_parts = fragment_path.parts[1:] # Remove leading "/" - return _build_udf_client_abs_path_from_fragments(fragment_parts) - elif fragment_parts[0] == "buckets": + + if fragment_parts[0] == "buckets": return _build_udf_client_abs_path_from_fragments(fragment_parts) else: - udf_client_path = UdfClientRelativePath( - executable=PurePosixPath("/".join(fragment_parts)) - ) + # Use original path from URL as is + udf_client_path = UdfClientRelativePath(executable=fragment_path) return udf_client_path diff --git a/test/unit/test_language_def_parser.py b/test/unit/test_language_def_parser.py index ae91817..ecaf0ae 100644 --- a/test/unit/test_language_def_parser.py +++ b/test/unit/test_language_def_parser.py @@ -48,10 +48,22 @@ executable=PurePosixPath("slc/exaudf/exaudfclient"), ), ), + ( + "/buckets/defaultbfs/default/slc/exaudf/exaudfclient", + UdfClientBucketPath( + bucketfs_name="defaultbfs", + bucket_name="default", + executable=PurePosixPath("slc/exaudf/exaudfclient"), + ), + ), ( "exaudf/exaudfclient", UdfClientRelativePath(executable=PurePosixPath("exaudf/exaudfclient")), ), + ( + "/exaudf/exaudfclient", + UdfClientRelativePath(executable=PurePosixPath("/exaudf/exaudfclient")), + ), ] PARAMETERS = [ @@ -96,7 +108,8 @@ def test_lang_def_parser( assert result.udf_client_path == expected_udf_client_path assert result.parameters == expected_param - assert f"{alias}={result}" == lang_def + if not udf_client_path.startswith("/buckets"): + assert f"{alias}={result}" == lang_def BUILTIN_LANGUAGES = [