cengal.build_tools.build_extensions.versions.v_0.go_extension
1#!/usr/bin/env python 2# coding=utf-8 3 4# Copyright © 2012-2024 ButenkoMS. All rights reserved. Contacts: <gtalk@butenkoms.space> 5# 6# Licensed under the Apache License, Version 2.0 (the "License"); 7# you may not use this file except in compliance with the License. 8# You may obtain a copy of the License at 9# 10# http://www.apache.org/licenses/LICENSE-2.0 11# 12# Unless required by applicable law or agreed to in writing, software 13# distributed under the License is distributed on an "AS IS" BASIS, 14# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15# See the License for the specific language governing permissions and 16# limitations under the License. 17 18 19__all__ = [ 20 'CengalGoBuildExtension', 21] 22 23 24""" 25Module Docstring 26Docstrings: http://www.python.org/dev/peps/pep-0257/ 27""" 28 29__author__ = "ButenkoMS <gtalk@butenkoms.space>" 30__copyright__ = "Copyright © 2012-2024 ButenkoMS. All rights reserved. Contacts: <gtalk@butenkoms.space>" 31__credits__ = ["ButenkoMS <gtalk@butenkoms.space>", ] 32__license__ = "Apache License, Version 2.0" 33__version__ = "4.4.1" 34__maintainer__ = "ButenkoMS <gtalk@butenkoms.space>" 35__email__ = "gtalk@butenkoms.space" 36# __status__ = "Prototype" 37__status__ = "Development" 38# __status__ = "Production" 39 40 41# from distutils.dist import Distribution 42from os import environ 43 44from setuptools._distutils.dist import Distribution 45 46from cengal.file_system.path_manager import path_relative_to_src, RelativePath, get_relative_path_part, sep 47from cengal.file_system.directory_manager import current_src_dir, change_current_dir, ensure_dir 48from cengal.file_system.directory_manager import filtered_file_list, FilteringType, filtered_file_list_traversal, file_list_traversal, file_list_traversal_ex, FilteringEntity 49from cengal.file_system.file_manager import current_src_file_dir, file_exists, full_ext, file_name as get_file_name, last_ext 50from cengal.build_tools.prepare_cflags import prepare_cflags, concat_cflags, prepare_compile_time_env, adjust_definition_names, \ 51 dict_of_tuples_to_dict, list_to_dict 52from cengal.introspection.inspect import get_exception, exception_to_printable_text, entity_repr_limited_try_qualname, pifrl, pdi 53from cengal.text_processing.text_processing import find_text 54from cengal.system import OS_TYPE, TEMPLATE_MODULE_NAME 55from shutil import rmtree 56from os import remove 57from os.path import splitext, normpath, join as path_join, basename, split 58from setuptools import Extension as SetuptoolsExtension 59from Cython.Distutils import Extension as CythonExtension 60from distutils.command.build import build as build_orig 61from distutils.command.build_ext import build_ext as build_ext_orig 62from setuptools.command.sdist import sdist as sdist_orig 63import json 64import importlib 65 66from os.path import isdir, exists, isfile, dirname 67 68import setuptools 69import platform 70import sys 71import os 72 73from cengal.file_system.path_manager import RelativePath, get_relative_path_part 74from cengal.file_system.directory_manager import current_src_dir 75from cengal.file_system.directory_manager import file_list_traversal, FilteringEntity 76from cengal.build_tools.prepare_cflags import prepare_compile_time_flags, prepare_compile_time_env 77from cengal.os.execute import prepare_params, escape_text, escape_param, prepare_command 78from setuptools.discovery import find_package_path 79import subprocess 80from pprint import pprint 81from typing import List, Dict, Optional, Iterable, Callable, Sequence, Tuple, Union, Type, Any 82 83from .build_extensions import CengalBuildExtension 84 85 86def wrap_definition_text(text: str) -> str: 87 return text 88 89 90def wrap_definition_text_v(text: str) -> str: 91 return escape_param(text) 92 93 94def wrap_definition_text_f(text: str) -> str: 95 return f'`{text}`' 96 97 98def prepare_definition_value(value: Union[None, bool, int, str]) -> Union[None, str]: 99 if value is None: 100 return None 101 elif isinstance(value, bool): 102 return 'true' if value else 'false' 103 elif isinstance(value, int): 104 return str(value) 105 elif isinstance(value, str): 106 return wrap_definition_text(value) 107 else: 108 return wrap_definition_text(f'{value}') 109 110 111def prepare_definition_value_v(value: Union[None, bool, int, str]) -> Union[None, str]: 112 if value is None: 113 return None 114 elif isinstance(value, bool): 115 return 'true' if value else 'false' 116 elif isinstance(value, int): 117 return str(value) 118 elif isinstance(value, str): 119 return wrap_definition_text_v(value) 120 else: 121 return wrap_definition_text_v(f'{value}') 122 123 124def prepare_definition_value_f(value: Union[None, bool, int, str]) -> Union[None, str]: 125 if value is None: 126 return None 127 elif isinstance(value, bool): 128 return 'true' if value else 'false' 129 elif isinstance(value, (int, float)): 130 return str(value) 131 elif isinstance(value, str): 132 return wrap_definition_text_f(value) 133 else: 134 return wrap_definition_text_f(f'{value}') 135 136 137def wrap_definition_pair(name: str, value: Any) -> str: 138 return f'-d:{name}' if value is None else f'-d:{name}={value}' 139 140 141def prepare_definition(name: str, value: Optional[Union[bool, int, str]] = None) -> str: 142 return wrap_definition_pair(name, prepare_definition_value(value)) 143 144 145def prepare_definition_v(name: str, value: Optional[Union[bool, int, str]] = None) -> str: 146 return wrap_definition_pair(name, prepare_definition_value_v(value)) 147 148 149class CengalGoBuildExtension(CengalBuildExtension): 150 base_class: Optional[Type] = None 151 store_as_data: bool = True 152 153 def __init__(self, 154 module_name: Optional[str] = None, 155 src_dir: str = './src', 156 out_dir_name: str = 'compiled', 157 flags: Optional[List[str]] = None, 158 definitions: Optional[Union[Sequence[str], Dict[str, Union[Union[None, bool, int, str], Tuple[bool, Union[None, bool, str, int]]]]]] = None, 159 additional_build_params: Optional[List[str]] = None, 160 additional_go_packages: Optional[List[str]] = None, 161 definitions_module_name: str = 'compile_time_py_definitions', 162 **kwargs) -> None: 163 super().__init__(kwargs) 164 self.module_name: str = module_name 165 self.out_dir_name: str = out_dir_name 166 self._src_dir: str = src_dir 167 self.src_dir: str = None 168 self.out_dir: str = None 169 self.flags: Optional[List[str]] = flags or list() 170 self.definitions: Optional[Union[Sequence[str], Dict[str, Union[Union[None, bool, int, str], Tuple[bool, Union[None, bool, str, int]]]]]] = definitions or dict() 171 result_flags = adjust_definition_names(list_to_dict(prepare_compile_time_flags()), 'GOF_', 'GOD_') # GOF is Go Flag; GOD is Go Definition 172 self.result_definitions: Optional[Dict[str, Union[None, bool, int, float, str]]] = adjust_definition_names(prepare_compile_time_env(), 'GOF_', 'GOD_') # GOF is Go Flag; GOD is Go Definition 173 self.result_definitions.update(result_flags) 174 self.result_definitions.update(dict_of_tuples_to_dict(list_to_dict(definitions))) 175 self.result_definitions.update(list_to_dict(flags)) 176 self.additional_build_params: Optional[List[str]] = additional_build_params 177 self.additional_go_packages: Optional[List[str]] = additional_go_packages 178 self.definitions_module_name: str = definitions_module_name 179 self.definitions_module_file_name: str = f'{definitions_module_name}.go' 180 181 @property 182 def module_name_str(self): 183 if self.module_name: 184 return self.module_name 185 else: 186 namespace = self.name 187 namespace_parts = namespace.split('.') 188 return'/'.join(namespace_parts[:-1]) 189 190 def __call__(self): 191 try: 192 # self.src_dir: str = self._src_dir if os.path.isabs(self._src_dir) else RelativePath(self.dir_path)(self._src_dir) 193 self.src_dir: str = self._src_dir 194 self.out_dir: str = RelativePath(self.dir_path)(self.out_dir_name) 195 print() 196 print('==================================================') 197 print(f'<<< GO COMPILATION: {self.module_name_str} >>>') 198 print('=======================') 199 go_module_setup_files = [ 200 'go.mod', 201 'go.sum', 202 ] 203 adjusted_exported_files_list = list() 204 need_to_init_go_module = False 205 for file_name in go_module_setup_files: 206 if not file_exists(path_join(self.dir_path, file_name)): 207 need_to_init_go_module = True 208 break 209 210 if need_to_init_go_module: 211 with change_current_dir(self.dir_path): 212 params = ['go', 'mod', 'init', self.module_name_str] 213 result = subprocess.run(params, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True) 214 print(result.stdout) 215 216 env = os.environ.copy() 217 additional_env = dict() 218 additional_env['LD_LIBRARY_PATH'] = f"{env.get('LD_LIBRARY_PATH', '')}{os.pathsep}." 219 env.update(additional_env) 220 params = ['gopy', 'build', f'-output={self.out_dir_name}', f'-vm={sys.executable}'] 221 if self.additional_build_params: 222 params.extend(self.additional_build_params) 223 224 params.append(self.src_dir) 225 params.append(f'./{get_file_name(self.definitions_module_name)}') 226 if self.additional_go_packages: 227 params.extend(self.additional_go_packages) 228 229 compiler_output: str = str() 230 with change_current_dir(self.dir_path): 231 self._ensure_gitignore() 232 self._generate_definitions_module() 233 print('> Go compiler command line:') 234 print(prepare_command(params[0], params[1:])) 235 print('> Go compiler params:') 236 pprint(params) 237 print('> Additional environmental variables:') 238 pprint(additional_env) 239 result = subprocess.run(params, env=env, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True) 240 compiler_output = result.stdout 241 242 successed: bool = find_text(compiler_output, 'cmd had error:') is None 243 print(f'{successed=}') 244 print('> Go compiler output:') 245 print(compiler_output) 246 exported_files_list = self._exported_files_list() 247 adjusted_exported_files_list = list() 248 for file_path in exported_files_list: 249 adjusted_exported_files_list.append(get_relative_path_part(file_path, self.dir_path)) 250 251 if successed: 252 print('> Exported files:') 253 print(adjusted_exported_files_list) 254 255 print('==================================================') 256 # raise RuntimeError 257 return adjusted_exported_files_list if successed else None 258 except: 259 print('==================================================') 260 print('!!! GO COMPILATION EXCEPTION !!!') 261 print('==================================================') 262 print(exception_to_printable_text(get_exception())) 263 print('==================================================') 264 return None 265 266 def sdist(self) -> Optional[List[str]]: 267 src_dir_path: str = RelativePath(self.dir_path)(self._src_dir) 268 def filter(entity: FilteringEntity, data: Any): 269 if FilteringEntity.filename == entity: 270 dirpath, filename = data 271 if filename in { 272 '__init__.py', 273 '__x__build_config.py', 274 '__build_config.py', 275 }: 276 return False 277 278 if last_ext(filename) in {'so', 'dylib', 'pyd', 'dll', 'py', 'pyw', 'gitignore', 'pyc'}: 279 return False 280 281 return True 282 elif FilteringEntity.dirname == entity: 283 dirpath, dirname = data 284 if dirname in { 285 '__pycache__', 286 }: 287 return False 288 289 return True 290 elif FilteringEntity.dirpath == entity: 291 dirpath, dirnames, filenames = data 292 dirpath_basename = basename(dirpath) 293 if dirpath_basename in { 294 '__pycache__', 295 }: 296 return False 297 298 return True 299 elif FilteringEntity.aggregated == entity: 300 result_full_file_names: List[str] = list() 301 for dirpath, new_dirnames, new_filenames in data: 302 for file_name in new_filenames: 303 result_full_file_names.append(path_join(dirpath, file_name)) 304 305 return result_full_file_names 306 else: 307 raise NotImplementedError 308 309 result_full_file_names: List[str] = file_list_traversal_ex(src_dir_path, filter, True) 310 go_module_setup_files = [ 311 'go.mod', 312 'go.sum', 313 ] 314 adjusted_exported_files_list = list() 315 for file_name in go_module_setup_files: 316 if file_exists(path_join(self.dir_path, file_name)): 317 adjusted_exported_files_list.append(file_name) 318 319 for file_path in result_full_file_names: 320 adjusted_exported_files_list.append(get_relative_path_part(file_path, self.dir_path)) 321 322 return adjusted_exported_files_list 323 324 def _exported_files_list(self) -> List[str]: 325 def filter(data_type: FilteringEntity, data): 326 if FilteringEntity.dirpath == data_type: 327 return True 328 elif FilteringEntity.dirname == data_type: 329 return False 330 elif FilteringEntity.filename == data_type: 331 _, file_name = data 332 if file_name in {'__init__.py', 'go.py'}: 333 return True 334 elif file_name in {'build.py', 'Makefile'}: 335 return False 336 elif last_ext(file_name) in {'so', 'dylib', 'pyd', 'dll', 'py', 'pyw'}: 337 return True 338 else: 339 return False 340 elif FilteringEntity.aggregated == data_type: 341 result_full_file_names: List[str] = list() 342 for dirpath, new_dirnames, new_filenames in data: 343 for file_name in new_filenames: 344 result_full_file_names.append(path_join(dirpath, file_name)) 345 346 return result_full_file_names 347 else: 348 raise NotImplementedError 349 350 result_full_file_names: List[str] = file_list_traversal(self.out_dir, filter, True) 351 return result_full_file_names if result_full_file_names else None 352 353 def _ensure_gitignore(self): 354 gitignore_path = self.dir_path_rel('.gitignore') 355 if file_exists(gitignore_path): 356 with open(gitignore_path, 'r+t') as f: 357 content = f.read() 358 if self.definitions_module_name not in content: 359 f.write(f'{self.definitions_module_name}/\n') 360 361 out_dir_name = basename(self.out_dir) 362 out_dir_name_ignorable = f'{out_dir_name}/' 363 if out_dir_name_ignorable not in content: 364 f.write(f'{out_dir_name_ignorable}\n') 365 366 # if 'go.mod' not in content: 367 # f.write(f'go.mod\n') 368 369 # if 'go.sum' not in content: 370 # f.write(f'go.sum\n') 371 else: 372 with open(gitignore_path, 'xt') as f: 373 f.write(f'{self.definitions_module_name}/\n') 374 out_dir_name = basename(self.out_dir) 375 out_dir_name_ignorable = f'{out_dir_name}/' 376 f.write(f'{out_dir_name_ignorable}\n') 377 # f.write(f'go.mod\n') 378 # f.write(f'go.sum\n') 379 380 def _generate_definitions_module(self): 381 file_content_template: str = """// {config_file_name} 382package {config_module_name} 383 384const ( 385{constants_text} 386) 387""" 388 constants_strings: List[str] = list() 389 for name, value in self.result_definitions.items(): 390 prepared_value = prepare_definition_value_f(value) 391 if prepared_value is None: 392 continue 393 394 constants_strings.append(f'\t{name} = {prepared_value}') 395 396 constants_text: str = '\n'.join(constants_strings) 397 file_content: str = file_content_template.format( 398 config_file_name=self.definitions_module_file_name, 399 config_module_name=get_file_name(self.definitions_module_name), 400 constants_text=constants_text, 401 ) 402 403 definitions_module_dir = self.dir_path_rel(self.definitions_module_name) 404 ensure_dir(definitions_module_dir) 405 definitions_module_dir_rel = RelativePath(definitions_module_dir) 406 with open(self.dir_path_rel(definitions_module_dir_rel(self.definitions_module_file_name)), 'wt') as f: 407 f.write(file_content)
class
CengalGoBuildExtension(cengal.build_tools.build_extensions.versions.v_0.build_extensions.CengalBuildExtension):
150class CengalGoBuildExtension(CengalBuildExtension): 151 base_class: Optional[Type] = None 152 store_as_data: bool = True 153 154 def __init__(self, 155 module_name: Optional[str] = None, 156 src_dir: str = './src', 157 out_dir_name: str = 'compiled', 158 flags: Optional[List[str]] = None, 159 definitions: Optional[Union[Sequence[str], Dict[str, Union[Union[None, bool, int, str], Tuple[bool, Union[None, bool, str, int]]]]]] = None, 160 additional_build_params: Optional[List[str]] = None, 161 additional_go_packages: Optional[List[str]] = None, 162 definitions_module_name: str = 'compile_time_py_definitions', 163 **kwargs) -> None: 164 super().__init__(kwargs) 165 self.module_name: str = module_name 166 self.out_dir_name: str = out_dir_name 167 self._src_dir: str = src_dir 168 self.src_dir: str = None 169 self.out_dir: str = None 170 self.flags: Optional[List[str]] = flags or list() 171 self.definitions: Optional[Union[Sequence[str], Dict[str, Union[Union[None, bool, int, str], Tuple[bool, Union[None, bool, str, int]]]]]] = definitions or dict() 172 result_flags = adjust_definition_names(list_to_dict(prepare_compile_time_flags()), 'GOF_', 'GOD_') # GOF is Go Flag; GOD is Go Definition 173 self.result_definitions: Optional[Dict[str, Union[None, bool, int, float, str]]] = adjust_definition_names(prepare_compile_time_env(), 'GOF_', 'GOD_') # GOF is Go Flag; GOD is Go Definition 174 self.result_definitions.update(result_flags) 175 self.result_definitions.update(dict_of_tuples_to_dict(list_to_dict(definitions))) 176 self.result_definitions.update(list_to_dict(flags)) 177 self.additional_build_params: Optional[List[str]] = additional_build_params 178 self.additional_go_packages: Optional[List[str]] = additional_go_packages 179 self.definitions_module_name: str = definitions_module_name 180 self.definitions_module_file_name: str = f'{definitions_module_name}.go' 181 182 @property 183 def module_name_str(self): 184 if self.module_name: 185 return self.module_name 186 else: 187 namespace = self.name 188 namespace_parts = namespace.split('.') 189 return'/'.join(namespace_parts[:-1]) 190 191 def __call__(self): 192 try: 193 # self.src_dir: str = self._src_dir if os.path.isabs(self._src_dir) else RelativePath(self.dir_path)(self._src_dir) 194 self.src_dir: str = self._src_dir 195 self.out_dir: str = RelativePath(self.dir_path)(self.out_dir_name) 196 print() 197 print('==================================================') 198 print(f'<<< GO COMPILATION: {self.module_name_str} >>>') 199 print('=======================') 200 go_module_setup_files = [ 201 'go.mod', 202 'go.sum', 203 ] 204 adjusted_exported_files_list = list() 205 need_to_init_go_module = False 206 for file_name in go_module_setup_files: 207 if not file_exists(path_join(self.dir_path, file_name)): 208 need_to_init_go_module = True 209 break 210 211 if need_to_init_go_module: 212 with change_current_dir(self.dir_path): 213 params = ['go', 'mod', 'init', self.module_name_str] 214 result = subprocess.run(params, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True) 215 print(result.stdout) 216 217 env = os.environ.copy() 218 additional_env = dict() 219 additional_env['LD_LIBRARY_PATH'] = f"{env.get('LD_LIBRARY_PATH', '')}{os.pathsep}." 220 env.update(additional_env) 221 params = ['gopy', 'build', f'-output={self.out_dir_name}', f'-vm={sys.executable}'] 222 if self.additional_build_params: 223 params.extend(self.additional_build_params) 224 225 params.append(self.src_dir) 226 params.append(f'./{get_file_name(self.definitions_module_name)}') 227 if self.additional_go_packages: 228 params.extend(self.additional_go_packages) 229 230 compiler_output: str = str() 231 with change_current_dir(self.dir_path): 232 self._ensure_gitignore() 233 self._generate_definitions_module() 234 print('> Go compiler command line:') 235 print(prepare_command(params[0], params[1:])) 236 print('> Go compiler params:') 237 pprint(params) 238 print('> Additional environmental variables:') 239 pprint(additional_env) 240 result = subprocess.run(params, env=env, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True) 241 compiler_output = result.stdout 242 243 successed: bool = find_text(compiler_output, 'cmd had error:') is None 244 print(f'{successed=}') 245 print('> Go compiler output:') 246 print(compiler_output) 247 exported_files_list = self._exported_files_list() 248 adjusted_exported_files_list = list() 249 for file_path in exported_files_list: 250 adjusted_exported_files_list.append(get_relative_path_part(file_path, self.dir_path)) 251 252 if successed: 253 print('> Exported files:') 254 print(adjusted_exported_files_list) 255 256 print('==================================================') 257 # raise RuntimeError 258 return adjusted_exported_files_list if successed else None 259 except: 260 print('==================================================') 261 print('!!! GO COMPILATION EXCEPTION !!!') 262 print('==================================================') 263 print(exception_to_printable_text(get_exception())) 264 print('==================================================') 265 return None 266 267 def sdist(self) -> Optional[List[str]]: 268 src_dir_path: str = RelativePath(self.dir_path)(self._src_dir) 269 def filter(entity: FilteringEntity, data: Any): 270 if FilteringEntity.filename == entity: 271 dirpath, filename = data 272 if filename in { 273 '__init__.py', 274 '__x__build_config.py', 275 '__build_config.py', 276 }: 277 return False 278 279 if last_ext(filename) in {'so', 'dylib', 'pyd', 'dll', 'py', 'pyw', 'gitignore', 'pyc'}: 280 return False 281 282 return True 283 elif FilteringEntity.dirname == entity: 284 dirpath, dirname = data 285 if dirname in { 286 '__pycache__', 287 }: 288 return False 289 290 return True 291 elif FilteringEntity.dirpath == entity: 292 dirpath, dirnames, filenames = data 293 dirpath_basename = basename(dirpath) 294 if dirpath_basename in { 295 '__pycache__', 296 }: 297 return False 298 299 return True 300 elif FilteringEntity.aggregated == entity: 301 result_full_file_names: List[str] = list() 302 for dirpath, new_dirnames, new_filenames in data: 303 for file_name in new_filenames: 304 result_full_file_names.append(path_join(dirpath, file_name)) 305 306 return result_full_file_names 307 else: 308 raise NotImplementedError 309 310 result_full_file_names: List[str] = file_list_traversal_ex(src_dir_path, filter, True) 311 go_module_setup_files = [ 312 'go.mod', 313 'go.sum', 314 ] 315 adjusted_exported_files_list = list() 316 for file_name in go_module_setup_files: 317 if file_exists(path_join(self.dir_path, file_name)): 318 adjusted_exported_files_list.append(file_name) 319 320 for file_path in result_full_file_names: 321 adjusted_exported_files_list.append(get_relative_path_part(file_path, self.dir_path)) 322 323 return adjusted_exported_files_list 324 325 def _exported_files_list(self) -> List[str]: 326 def filter(data_type: FilteringEntity, data): 327 if FilteringEntity.dirpath == data_type: 328 return True 329 elif FilteringEntity.dirname == data_type: 330 return False 331 elif FilteringEntity.filename == data_type: 332 _, file_name = data 333 if file_name in {'__init__.py', 'go.py'}: 334 return True 335 elif file_name in {'build.py', 'Makefile'}: 336 return False 337 elif last_ext(file_name) in {'so', 'dylib', 'pyd', 'dll', 'py', 'pyw'}: 338 return True 339 else: 340 return False 341 elif FilteringEntity.aggregated == data_type: 342 result_full_file_names: List[str] = list() 343 for dirpath, new_dirnames, new_filenames in data: 344 for file_name in new_filenames: 345 result_full_file_names.append(path_join(dirpath, file_name)) 346 347 return result_full_file_names 348 else: 349 raise NotImplementedError 350 351 result_full_file_names: List[str] = file_list_traversal(self.out_dir, filter, True) 352 return result_full_file_names if result_full_file_names else None 353 354 def _ensure_gitignore(self): 355 gitignore_path = self.dir_path_rel('.gitignore') 356 if file_exists(gitignore_path): 357 with open(gitignore_path, 'r+t') as f: 358 content = f.read() 359 if self.definitions_module_name not in content: 360 f.write(f'{self.definitions_module_name}/\n') 361 362 out_dir_name = basename(self.out_dir) 363 out_dir_name_ignorable = f'{out_dir_name}/' 364 if out_dir_name_ignorable not in content: 365 f.write(f'{out_dir_name_ignorable}\n') 366 367 # if 'go.mod' not in content: 368 # f.write(f'go.mod\n') 369 370 # if 'go.sum' not in content: 371 # f.write(f'go.sum\n') 372 else: 373 with open(gitignore_path, 'xt') as f: 374 f.write(f'{self.definitions_module_name}/\n') 375 out_dir_name = basename(self.out_dir) 376 out_dir_name_ignorable = f'{out_dir_name}/' 377 f.write(f'{out_dir_name_ignorable}\n') 378 # f.write(f'go.mod\n') 379 # f.write(f'go.sum\n') 380 381 def _generate_definitions_module(self): 382 file_content_template: str = """// {config_file_name} 383package {config_module_name} 384 385const ( 386{constants_text} 387) 388""" 389 constants_strings: List[str] = list() 390 for name, value in self.result_definitions.items(): 391 prepared_value = prepare_definition_value_f(value) 392 if prepared_value is None: 393 continue 394 395 constants_strings.append(f'\t{name} = {prepared_value}') 396 397 constants_text: str = '\n'.join(constants_strings) 398 file_content: str = file_content_template.format( 399 config_file_name=self.definitions_module_file_name, 400 config_module_name=get_file_name(self.definitions_module_name), 401 constants_text=constants_text, 402 ) 403 404 definitions_module_dir = self.dir_path_rel(self.definitions_module_name) 405 ensure_dir(definitions_module_dir) 406 definitions_module_dir_rel = RelativePath(definitions_module_dir) 407 with open(self.dir_path_rel(definitions_module_dir_rel(self.definitions_module_file_name)), 'wt') as f: 408 f.write(file_content)
CengalGoBuildExtension( module_name: Union[str, NoneType] = None, src_dir: str = './src', out_dir_name: str = 'compiled', flags: Union[List[str], NoneType] = None, definitions: Union[Sequence[str], Dict[str, Union[NoneType, bool, int, str, Tuple[bool, Union[NoneType, bool, str, int]]]], NoneType] = None, additional_build_params: Union[List[str], NoneType] = None, additional_go_packages: Union[List[str], NoneType] = None, definitions_module_name: str = 'compile_time_py_definitions', **kwargs)
154 def __init__(self, 155 module_name: Optional[str] = None, 156 src_dir: str = './src', 157 out_dir_name: str = 'compiled', 158 flags: Optional[List[str]] = None, 159 definitions: Optional[Union[Sequence[str], Dict[str, Union[Union[None, bool, int, str], Tuple[bool, Union[None, bool, str, int]]]]]] = None, 160 additional_build_params: Optional[List[str]] = None, 161 additional_go_packages: Optional[List[str]] = None, 162 definitions_module_name: str = 'compile_time_py_definitions', 163 **kwargs) -> None: 164 super().__init__(kwargs) 165 self.module_name: str = module_name 166 self.out_dir_name: str = out_dir_name 167 self._src_dir: str = src_dir 168 self.src_dir: str = None 169 self.out_dir: str = None 170 self.flags: Optional[List[str]] = flags or list() 171 self.definitions: Optional[Union[Sequence[str], Dict[str, Union[Union[None, bool, int, str], Tuple[bool, Union[None, bool, str, int]]]]]] = definitions or dict() 172 result_flags = adjust_definition_names(list_to_dict(prepare_compile_time_flags()), 'GOF_', 'GOD_') # GOF is Go Flag; GOD is Go Definition 173 self.result_definitions: Optional[Dict[str, Union[None, bool, int, float, str]]] = adjust_definition_names(prepare_compile_time_env(), 'GOF_', 'GOD_') # GOF is Go Flag; GOD is Go Definition 174 self.result_definitions.update(result_flags) 175 self.result_definitions.update(dict_of_tuples_to_dict(list_to_dict(definitions))) 176 self.result_definitions.update(list_to_dict(flags)) 177 self.additional_build_params: Optional[List[str]] = additional_build_params 178 self.additional_go_packages: Optional[List[str]] = additional_go_packages 179 self.definitions_module_name: str = definitions_module_name 180 self.definitions_module_file_name: str = f'{definitions_module_name}.go'
definitions: Union[Sequence[str], Dict[str, Union[NoneType, bool, int, str, Tuple[bool, Union[NoneType, bool, str, int]]]], NoneType]
def
sdist(self) -> Union[List[str], NoneType]:
267 def sdist(self) -> Optional[List[str]]: 268 src_dir_path: str = RelativePath(self.dir_path)(self._src_dir) 269 def filter(entity: FilteringEntity, data: Any): 270 if FilteringEntity.filename == entity: 271 dirpath, filename = data 272 if filename in { 273 '__init__.py', 274 '__x__build_config.py', 275 '__build_config.py', 276 }: 277 return False 278 279 if last_ext(filename) in {'so', 'dylib', 'pyd', 'dll', 'py', 'pyw', 'gitignore', 'pyc'}: 280 return False 281 282 return True 283 elif FilteringEntity.dirname == entity: 284 dirpath, dirname = data 285 if dirname in { 286 '__pycache__', 287 }: 288 return False 289 290 return True 291 elif FilteringEntity.dirpath == entity: 292 dirpath, dirnames, filenames = data 293 dirpath_basename = basename(dirpath) 294 if dirpath_basename in { 295 '__pycache__', 296 }: 297 return False 298 299 return True 300 elif FilteringEntity.aggregated == entity: 301 result_full_file_names: List[str] = list() 302 for dirpath, new_dirnames, new_filenames in data: 303 for file_name in new_filenames: 304 result_full_file_names.append(path_join(dirpath, file_name)) 305 306 return result_full_file_names 307 else: 308 raise NotImplementedError 309 310 result_full_file_names: List[str] = file_list_traversal_ex(src_dir_path, filter, True) 311 go_module_setup_files = [ 312 'go.mod', 313 'go.sum', 314 ] 315 adjusted_exported_files_list = list() 316 for file_name in go_module_setup_files: 317 if file_exists(path_join(self.dir_path, file_name)): 318 adjusted_exported_files_list.append(file_name) 319 320 for file_path in result_full_file_names: 321 adjusted_exported_files_list.append(get_relative_path_part(file_path, self.dir_path)) 322 323 return adjusted_exported_files_list
Inherited Members
- cengal.build_tools.build_extensions.versions.v_0.build_extensions.CengalBuildExtension
- kwargs
- path
- dir_path
- dir_path_rel
- module_import_str
- name
- package
- files