diff options
author | Dylan Baker <dylan@pnwbakers.com> | 2023-06-30 14:58:30 -0700 |
---|---|---|
committer | Eli Schwartz <eschwartz93@gmail.com> | 2023-07-25 15:50:21 -0400 |
commit | 5449d10f01bc765e33e041a15f7c90e752ba7539 (patch) | |
tree | 66ae8c35da4c517f3d8cad6a43817fe06603c328 /mesonbuild/templates | |
parent | bbe649a5fc7bb0b955b2688c4d797b71830c8aeb (diff) | |
download | meson-5449d10f01bc765e33e041a15f7c90e752ba7539.zip meson-5449d10f01bc765e33e041a15f7c90e752ba7539.tar.gz meson-5449d10f01bc765e33e041a15f7c90e752ba7539.tar.bz2 |
templates: use a common template for C# and Java
The only real differences between these generators is the file extension
and the templates themselves. We can uses a shared abstract class
with a few abstract properties to provide all of this to the same base
class. This results in less code duplication and easier maintanence.
I've made a few cleanups to the shared template:
- use `str.capitalize()` instead of `str.upper()[0] + str[1:]`
- use `open` as a context manager
- use f-strings
- put some duplicate calculations in the initializer
Diffstat (limited to 'mesonbuild/templates')
-rw-r--r-- | mesonbuild/templates/cstemplates.py | 51 | ||||
-rw-r--r-- | mesonbuild/templates/javatemplates.py | 49 | ||||
-rw-r--r-- | mesonbuild/templates/samplefactory.py | 31 | ||||
-rw-r--r-- | mesonbuild/templates/sampleimpl.py | 78 |
4 files changed, 110 insertions, 99 deletions
diff --git a/mesonbuild/templates/cstemplates.py b/mesonbuild/templates/cstemplates.py index 39653d4..d2d5ec9 100644 --- a/mesonbuild/templates/cstemplates.py +++ b/mesonbuild/templates/cstemplates.py @@ -13,9 +13,7 @@ # limitations under the License. from __future__ import annotations -import re - -from mesonbuild.templates.sampleimpl import SampleImpl +from mesonbuild.templates.sampleimpl import ClassImpl hello_cs_template = '''using System; @@ -92,42 +90,11 @@ test('{test_name}', test_exe) ''' -class CSharpProject(SampleImpl): - - def create_executable(self) -> None: - lowercase_token = re.sub(r'[^a-z0-9]', '_', self.name.lower()) - uppercase_token = lowercase_token.upper() - class_name = uppercase_token[0] + lowercase_token[1:] - source_name = uppercase_token[0] + lowercase_token[1:] + '.cs' - open(source_name, 'w', encoding='utf-8').write( - hello_cs_template.format(project_name=self.name, - class_name=class_name)) - open('meson.build', 'w', encoding='utf-8').write( - hello_cs_meson_template.format(project_name=self.name, - exe_name=self.name, - source_name=source_name, - version=self.version)) - - def create_library(self) -> None: - lowercase_token = re.sub(r'[^a-z0-9]', '_', self.name.lower()) - uppercase_token = lowercase_token.upper() - class_name = uppercase_token[0] + lowercase_token[1:] - class_test = uppercase_token[0] + lowercase_token[1:] + '_test' - project_test = lowercase_token + '_test' - lib_cs_name = uppercase_token[0] + lowercase_token[1:] + '.cs' - test_cs_name = uppercase_token[0] + lowercase_token[1:] + '_test.cs' - kwargs = {'utoken': uppercase_token, - 'ltoken': lowercase_token, - 'class_test': class_test, - 'class_name': class_name, - 'source_file': lib_cs_name, - 'test_source_file': test_cs_name, - 'test_exe_name': project_test, - 'project_name': self.name, - 'lib_name': lowercase_token, - 'test_name': lowercase_token, - 'version': self.version, - } - open(lib_cs_name, 'w', encoding='utf-8').write(lib_cs_template.format(**kwargs)) - open(test_cs_name, 'w', encoding='utf-8').write(lib_cs_test_template.format(**kwargs)) - open('meson.build', 'w', encoding='utf-8').write(lib_cs_meson_template.format(**kwargs)) +class CSharpProject(ClassImpl): + + source_ext = 'cs' + exe_template = hello_cs_template + exe_meson_template = hello_cs_meson_template + lib_template = lib_cs_template + lib_test_template = lib_cs_test_template + lib_meson_template = lib_cs_meson_template diff --git a/mesonbuild/templates/javatemplates.py b/mesonbuild/templates/javatemplates.py index 4b9c746..4163ffd 100644 --- a/mesonbuild/templates/javatemplates.py +++ b/mesonbuild/templates/javatemplates.py @@ -13,9 +13,7 @@ # limitations under the License. from __future__ import annotations -import re - -from mesonbuild.templates.sampleimpl import SampleImpl +from mesonbuild.templates.sampleimpl import ClassImpl hello_java_template = ''' @@ -96,40 +94,11 @@ test('{test_name}', test_jar) ''' -class JavaProject(SampleImpl): - - def create_executable(self) -> None: - lowercase_token = re.sub(r'[^a-z0-9]', '_', self.name.lower()) - uppercase_token = lowercase_token.upper() - class_name = uppercase_token[0] + lowercase_token[1:] - source_name = uppercase_token[0] + lowercase_token[1:] + '.java' - open(source_name, 'w', encoding='utf-8').write( - hello_java_template.format(project_name=self.name, - class_name=class_name)) - open('meson.build', 'w', encoding='utf-8').write( - hello_java_meson_template.format(project_name=self.name, - exe_name=class_name, - source_name=source_name, - version=self.version)) - - def create_library(self) -> None: - lowercase_token = re.sub(r'[^a-z0-9]', '_', self.name.lower()) - uppercase_token = lowercase_token.upper() - class_name = uppercase_token[0] + lowercase_token[1:] - class_test = uppercase_token[0] + lowercase_token[1:] + '_test' - lib_java_name = uppercase_token[0] + lowercase_token[1:] + '.java' - test_java_name = uppercase_token[0] + lowercase_token[1:] + '_test.java' - kwargs = {'utoken': uppercase_token, - 'ltoken': lowercase_token, - 'class_test': class_test, - 'class_name': class_name, - 'source_file': lib_java_name, - 'test_source_file': test_java_name, - 'project_name': self.name, - 'lib_name': lowercase_token, - 'test_name': lowercase_token, - 'version': self.version, - } - open(lib_java_name, 'w', encoding='utf-8').write(lib_java_template.format(**kwargs)) - open(test_java_name, 'w', encoding='utf-8').write(lib_java_test_template.format(**kwargs)) - open('meson.build', 'w', encoding='utf-8').write(lib_java_meson_template.format(**kwargs)) +class JavaProject(ClassImpl): + + source_ext = 'java' + exe_template = hello_java_template + exe_meson_template = hello_java_meson_template + lib_template = lib_java_template + lib_test_template = lib_java_test_template + lib_meson_template = lib_java_meson_template diff --git a/mesonbuild/templates/samplefactory.py b/mesonbuild/templates/samplefactory.py index 89c3c4c..e3c8551 100644 --- a/mesonbuild/templates/samplefactory.py +++ b/mesonbuild/templates/samplefactory.py @@ -29,20 +29,23 @@ from mesonbuild.templates.ctemplates import CProject if T.TYPE_CHECKING: from ..minit import Arguments - from .sampleimpl import SampleImpl + from .sampleimpl import ClassImpl, SampleImpl + + +_IMPL: T.Mapping[str, T.Union[T.Type[ClassImpl], T.Type[SampleImpl]]] = { + 'c': CProject, + 'cpp': CppProject, + 'cs': CSharpProject, + 'cuda': CudaProject, + 'objc': ObjCProject, + 'objcpp': ObjCppProject, + 'java': JavaProject, + 'd': DlangProject, + 'rust': RustProject, + 'fortran': FortranProject, + 'vala': ValaProject, +} def sample_generator(options: Arguments) -> SampleImpl: - return { - 'c': CProject, - 'cpp': CppProject, - 'cs': CSharpProject, - 'cuda': CudaProject, - 'objc': ObjCProject, - 'objcpp': ObjCppProject, - 'java': JavaProject, - 'd': DlangProject, - 'rust': RustProject, - 'fortran': FortranProject, - 'vala': ValaProject - }[options.language](options) + return _IMPL[options.language](options) diff --git a/mesonbuild/templates/sampleimpl.py b/mesonbuild/templates/sampleimpl.py index 4d586b1..0d31aa4 100644 --- a/mesonbuild/templates/sampleimpl.py +++ b/mesonbuild/templates/sampleimpl.py @@ -13,20 +13,92 @@ # limitations under the License. from __future__ import annotations +import abc +import re import typing as T if T.TYPE_CHECKING: from ..minit import Arguments -class SampleImpl: +class SampleImpl(metaclass=abc.ABCMeta): def __init__(self, args: Arguments): self.name = args.name self.version = args.version + @abc.abstractmethod def create_executable(self) -> None: - raise NotImplementedError('Sample implementation for "executable" not implemented!') + pass + @abc.abstractmethod def create_library(self) -> None: - raise NotImplementedError('Sample implementation for "library" not implemented!') + pass + + +class ClassImpl(SampleImpl): + + """For Class based languages, like Java and C#""" + + def __init__(self, args: Arguments): + super().__init__(args) + self.lowercase_token = re.sub(r'[^a-z0-9]', '_', self.name.lower()) + self.uppercase_token = self.lowercase_token.upper() + self.capitalized_token = self.lowercase_token.capitalize() + + @abc.abstractproperty + def exe_template(self) -> str: + pass + + @abc.abstractproperty + def exe_meson_template(self) -> str: + pass + + @abc.abstractproperty + def lib_template(self) -> str: + pass + + @abc.abstractproperty + def lib_test_template(self) -> str: + pass + + @abc.abstractproperty + def lib_meson_template(self) -> str: + pass + + @abc.abstractproperty + def source_ext(self) -> str: + pass + + def create_executable(self) -> None: + source_name = f'{self.capitalized_token}.{self.source_ext}' + with open(source_name, 'w', encoding='utf-8') as f: + f.write(self.exe_template.format(project_name=self.name, + class_name=self.capitalized_token)) + with open('meson.build', 'w', encoding='utf-8') as f: + f.write(self.exe_meson_template.format(project_name=self.name, + exe_name=self.name, + source_name=source_name, + version=self.version)) + + def create_library(self) -> None: + lib_name = f'{self.capitalized_token}.{self.source_ext}' + test_name = f'{self.capitalized_token}_test.{self.source_ext}' + kwargs = {'utoken': self.uppercase_token, + 'ltoken': self.lowercase_token, + 'class_test': f'{self.capitalized_token}_test', + 'class_name': self.capitalized_token, + 'source_file': lib_name, + 'test_source_file': test_name, + 'test_exe_name': f'{self.lowercase_token}_test', + 'project_name': self.name, + 'lib_name': self.lowercase_token, + 'test_name': self.lowercase_token, + 'version': self.version, + } + with open(lib_name, 'w', encoding='utf-8') as f: + f.write(self.lib_template.format(**kwargs)) + with open(test_name, 'w', encoding='utf-8') as f: + f.write(self.lib_test_template.format(**kwargs)) + with open('meson.build', 'w', encoding='utf-8') as f: + f.write(self.lib_meson_template.format(**kwargs)) |