1#!/usr/bin/env python3 2""" 3# Created: Mon Jun 20 20:07:30 2022 (-0400) 4# @author: Jacob Faibussowitsch 5""" 6from __future__ import annotations 7 8from .._typing import * 9 10import clang.cindex as clx # type: ignore[import] 11 12_T = TypeVar('_T') 13_U = TypeVar('_U') 14 15classid_map: dict[str, str] = {} 16check_function_map: dict[str, FunctionChecker] = {} 17check_doc_map: dict[clx.CursorKind, DocChecker] = {} 18 19def filter_check_function_map(allowed_symbol_names: Collection[str]) -> None: 20 r"""Remove checks from check_function_map 21 22 Parameters 23 ---------- 24 allowed_symbol_names : 25 a set of symbol names 26 27 Notes 28 ----- 29 After this routine returns, the check function map will only contain functions whose symbol name 30 was in `allowed_symbol_names` 31 """ 32 if allowed_symbol_names: 33 global check_function_map 34 35 # note the list, this makes a copy of the keys allowing us to delete entries "in place" 36 for key in list(check_function_map.keys()): 37 if key not in allowed_symbol_names: 38 del check_function_map[key] 39 return 40 41def __register_base(key: _T, value: _U, target_map: dict[_T, _U], exist_ok: bool) -> None: 42 if key in target_map: 43 if not exist_ok: 44 raise RuntimeError(f'Key {key} already registered with check map') 45 46 target_map[key] = value 47 return 48 49def register_classid(struct_name: str, classid_name: str, exist_ok: bool = False) -> None: 50 r"""Register a classid to match struct names 51 52 Parameters 53 ---------- 54 struct_name : 55 the fully qualified structure typename to match against, e.g. _p_PetscObject * 56 classid_name : 57 the string name of the classid variable, e.g. "KSP_CLASSID" 58 exist_ok : optional 59 is it ok if there already exists a classid for this struct? 60 61 Raises 62 ------ 63 RuntimeError 64 if a classid has already been registered for `struct_name` and `exist_ok` is False 65 """ 66 __register_base(struct_name, classid_name, classid_map, exist_ok) 67 return 68 69def register_symbol_check(name: str, function: FunctionChecker, exist_ok: bool = False) -> None: 70 r"""Register a symbol checking function 71 72 Parameters 73 ---------- 74 name : 75 the name of the symbol this checker will trigger on 76 function : 77 the function to check the symbol 78 exist_ok : optional 79 is it ok if there already exists a checker for this kind? 80 81 Raises 82 ------ 83 RuntimeError 84 if a function has already been registered for `name` and `exist_ok` is False 85 """ 86 __register_base(name, function, check_function_map, exist_ok) 87 return 88 89def register_doc_check(cursor_kind: clx.CursorKind, function: DocChecker, exist_ok: bool = False) -> None: 90 r"""Register a docs-checking function 91 92 Parameters 93 ---------- 94 cursor_kind : 95 the kind of cursor this docs checker will trigger on, (e.g. functions, enums, etc.) 96 function : 97 the function to check the docstring 98 exist_ok : optional 99 is it ok if there already exists a checker for this kind? 100 101 Raises 102 ------ 103 RuntimeError 104 if a function has already been registered for `cursor_kind` and `exist_ok` is False 105 """ 106 __register_base(cursor_kind, function, check_doc_map, exist_ok) 107 return 108 109def __register_all_classids() -> None: 110 r""" 111 Adding new classes 112 ------------------ 113 114 You must register new instances of PETSc classes in the classid_map which expects its 115 contents to be in the form: 116 117 "CaseSensitiveNameOfPrivateStruct *" : "CaseSensitiveNameOfCorrespondingClassId", 118 119 See below for examples. 120 121 * please add your new class in alphabetical order and preserve the alignment! * 122 123 The automated way to do it (in emacs) is to slap it in the first entry then highlight 124 the contents (i.e. excluding "classid_map = {" and the closing "}") and do: 125 126 1. M-x sort-fields RET 127 2. M-x align-regexp RET : RET 128 """ 129 default_classid_map = { 130 "_p_AO *" : "AO_CLASSID", 131 "_p_PetscBench *" : "BM_CLASSID", 132 "_p_Characteristic *" : "CHARACTERISTIC_CLASSID", 133 "_p_DM *" : "DM_CLASSID", 134 "_p_DMAdaptor *" : "DMADAPTOR_CLASSID", 135 "_p_DMField *" : "DMFIELD_CLASSID", 136 "_p_DMKSP *" : "DMKSP_CLASSID", 137 "_p_DMLabel *" : "DMLABEL_CLASSID", 138 "_p_DMPlexTransform *" : "DMPLEXTRANSFORM_CLASSID", 139 "_p_DMSwarmCellDM *" : "DMSWARMCELLDM_CLASSID", 140 "_p_DMSNES *" : "DMSNES_CLASSID", 141 "_p_DMTS *" : "DMTS_CLASSID", 142 "_p_IS *" : "IS_CLASSID", 143 "_p_ISLocalToGlobalMapping *" : "IS_LTOGM_CLASSID", 144 "_p_KSP *" : "KSP_CLASSID", 145 "_p_KSPGuess *" : "KSPGUESS_CLASSID", 146 "_p_LineSearch *" : "SNESLINESEARCH_CLASSID", 147 "_p_Mat *" : "MAT_CLASSID", 148 "_p_MatCoarsen *" : "MAT_COARSEN_CLASSID", 149 "_p_MatColoring *" : "MAT_COLORING_CLASSID", 150 "_p_MatFDColoring *" : "MAT_FDCOLORING_CLASSID", 151 "_p_MatMFFD *" : "MATMFFD_CLASSID", 152 "_p_MatNullSpace *" : "MAT_NULLSPACE_CLASSID", 153 "_p_MatPartitioning *" : "MAT_PARTITIONING_CLASSID", 154 "_p_MatTransposeColoring *" : "MAT_TRANSPOSECOLORING_CLASSID", 155 "_p_PC *" : "PC_CLASSID", 156 "_p_PF *" : "PF_CLASSID", 157 "_p_PetscContainer *" : "PETSC_CONTAINER_CLASSID", 158 "_p_PetscConvEst *" : "PETSC_OBJECT_CLASSID", 159 "_p_PetscDS *" : "PETSCDS_CLASSID", 160 "_p_PetscDraw *" : "PETSC_DRAW_CLASSID", 161 "_p_PetscDrawAxis *" : "PETSC_DRAWAXIS_CLASSID", 162 "_p_PetscDrawBar *" : "PETSC_DRAWBAR_CLASSID", 163 "_p_PetscDrawHG *" : "PETSC_DRAWHG_CLASSID", 164 "_p_PetscDrawLG *" : "PETSC_DRAWLG_CLASSID", 165 "_p_PetscDrawSP *" : "PETSC_DRAWSP_CLASSID", 166 "_p_PetscDualSpace *" : "PETSCDUALSPACE_CLASSID", 167 "_p_PetscFE *" : "PETSCFE_CLASSID", 168 "_p_PetscFV *" : "PETSCFV_CLASSID", 169 "_p_PetscLimiter *" : "PETSCLIMITER_CLASSID", 170 "_p_PetscLinterDummyObj *" : "PETSC_LINTER_DUMMY_OBJECT", 171 "_p_PetscLogHandler *" : "PETSCLOGHANDLER_CLASSID", 172 "_p_PetscObject *" : "PETSC_OBJECT_CLASSID", 173 "_p_PetscPartitioner *" : "PETSCPARTITIONER_CLASSID", 174 "_p_PetscQuadrature *" : "PETSCQUADRATURE_CLASSID", 175 "_p_PetscRandom *" : "PETSC_RANDOM_CLASSID", 176 "_p_PetscSF *" : "PETSCSF_CLASSID", 177 "_p_PetscSection *" : "PETSC_SECTION_CLASSID", 178 "_p_PetscSectionSym *" : "PETSC_SECTION_SYM_CLASSID", 179 "_p_PetscSpace *" : "PETSCSPACE_CLASSID", 180 "_p_PetscViewer *" : "PETSC_VIEWER_CLASSID", 181 "_p_PetscWeakForm *" : "PETSCWEAKFORM_CLASSID", 182 "_p_SNES *" : "SNES_CLASSID", 183 "_p_TS *" : "TS_CLASSID", 184 "_p_TSAdapt *" : "TSADAPT_CLASSID", 185 "_p_TSGLLEAdapt *" : "TSGLLEADAPT_CLASSID", 186 "_p_TSTrajectory *" : "TSTRAJECTORY_CLASSID", 187 "_p_Tao *" : "TAO_CLASSID", 188 "_p_TaoLineSearch *" : "TAOLINESEARCH_CLASSID", 189 "_p_PetscRegressor *" : "PETSCREGRESSOR_CLASSID", 190 "_p_Vec *" : "VEC_CLASSID", 191 "_p_VecTagger *" : "VEC_TAGGER_CLASSID", 192 } 193 for key, value in default_classid_map.items(): 194 register_classid(key, value) 195 return 196 197def __register_all_symbol_checks() -> None: 198 from . import _code 199 200 default_checks = { 201 "PetscValidHeaderSpecificType" : _code.checkPetscValidHeaderSpecificType, 202 "PetscValidHeaderSpecific" : _code.checkPetscValidHeaderSpecific, 203 "PetscValidHeader" : _code.checkPetscValidHeader, 204 "PetscAssertPointer" : _code.check_obj_idx_generic, 205 "PetscCheckSameType" : _code.check_obj_idx_generic, 206 "PetscValidType" : _code.check_obj_idx_generic, 207 "PetscCheckSameComm" : _code.check_obj_idx_generic, 208 "PetscCheckSameTypeAndComm" : _code.check_obj_idx_generic, 209 "PetscValidLogicalCollectiveScalar" : _code.checkPetscValidLogicalCollectiveScalar, 210 "PetscValidLogicalCollectiveReal" : _code.checkPetscValidLogicalCollectiveReal, 211 "PetscValidLogicalCollectiveInt" : _code.checkPetscValidLogicalCollectiveInt, 212 "PetscValidLogicalCollectiveMPIInt" : _code.checkPetscValidLogicalCollectiveMPIInt, 213 "PetscValidLogicalCollectiveBool" : _code.checkPetscValidLogicalCollectiveBool, 214 "PetscValidLogicalCollectiveEnum" : _code.checkPetscValidLogicalCollectiveEnum, 215 "VecNestCheckCompatible2" : _code.check_obj_idx_generic, 216 "VecNestCheckCompatible3" : _code.check_obj_idx_generic, 217 "MatCheckPreallocated" : _code.check_obj_idx_generic, 218 "MatCheckProduct" : _code.check_obj_idx_generic, 219 "MatCheckSameLocalSize" : _code.check_obj_idx_generic, 220 "MatCheckSameSize" : _code.check_obj_idx_generic, 221 "PetscValidDevice" : _code.check_obj_idx_generic, 222 "PetscCheckCompatibleDevices" : _code.check_obj_idx_generic, 223 "PetscValidDeviceContext" : _code.check_obj_idx_generic, 224 "PetscCheckCompatibleDeviceContexts" : _code.check_obj_idx_generic, 225 "PetscSFCheckGraphSet" : _code.check_obj_idx_generic, 226 } 227 for key, value in default_checks.items(): 228 register_symbol_check(key, value) 229 return 230 231def __register_all_doc_checks() -> None: 232 from . import _docs 233 234 default_checks = { 235 clx.CursorKind.FUNCTION_DECL : _docs.check_petsc_function_docstring, 236 clx.CursorKind.ENUM_DECL : _docs.check_petsc_enum_docstring, 237 } 238 for key, value in default_checks.items(): 239 register_doc_check(key, value) 240 return 241 242def __register_all() -> None: 243 __register_all_classids() 244 __register_all_symbol_checks() 245 __register_all_doc_checks() 246 return 247 248__register_all() 249