def generate_module(cfg: ConfigenConf, module: ModuleConf) -> str: classes_map: Dict[str, ClassInfo] = {} imports = set() string_imports: Set[str] = set() default_flags = get_default_flags(module) for class_name in module.classes: full_name = f"{module.name}.{class_name}" cls = hydra.utils.get_class(full_name) params: List[Parameter] = [] params = params + default_flags resolved_hints = get_type_hints(cls.__init__) sig = inspect.signature(cls.__init__) for name, p in sig.parameters.items(): # Skip self as an attribute if name in ("self", "args", "kwargs"): continue type_ = type_cached = resolved_hints.get(name, p.annotation) default_ = p.default missing_value = default_ == sig.empty incompatible_value_type = not missing_value and is_incompatible( type(default_)) missing_annotation_type = name not in resolved_hints incompatible_annotation_type = not missing_annotation_type and is_incompatible( type_) if missing_annotation_type or incompatible_annotation_type: type_ = Any collect_imports(imports, Any) if not missing_value: if type_ == str or type(default_) == str: default_ = f'"{default_}"' elif isinstance(default_, list): default_ = f"field(default_factory=lambda: {default_})" elif isinstance(default_, dict): default_ = f"field(default_factory=lambda: {default_})" missing_default = missing_value if incompatible_value_type: missing_default = True collect_imports(imports, type_) if missing_default: default_ = "MISSING" string_imports.add("from omegaconf import MISSING") if incompatible_annotation_type: default_ = f"{default_} # {type_str(type_cached)}" elif incompatible_value_type: default_ = f"{default_} # {type_str(type(p.default))}" params.append( Parameter( name=name, type_str=type_str(type_), default=default_, )) classes_map[class_name] = ClassInfo( target=full_name, module=module.name, name=class_name, parameters=params, ) template = jinja_env.get_template("module.j2") return template.render( imports=convert_imports(imports, string_imports), classes=module.classes, classes_map=classes_map, header=cfg.header, )
def generate_module(cfg: ConfigenConf, module: ModuleConf) -> str: classes_map: Dict[str, ClassInfo] = {} imports = set() string_imports: Set[str] = set() for class_name in module.classes: full_name = f"{module.name}.{class_name}" cls = hydra.utils.get_class(full_name) sig = inspect.signature(cls) params: List[Parameter] = [] for name, p in sig.parameters.items(): type_ = p.annotation default_ = p.default missing_value = default_ == sig.empty incompatible_value_type = not missing_value and is_incompatible( type(default_)) missing_annotation_type = type_ == sig.empty incompatible_annotation_type = (not missing_annotation_type and is_incompatible(type_)) if missing_annotation_type or incompatible_annotation_type: type_ = Any collect_imports(imports, Any) if not missing_value: if type_ == str: default_ = f'"{default_}"' elif isinstance(default_, list): default_ = f"field(default_factory=lambda: {default_})" elif isinstance(default_, dict): default_ = f"field(default_factory=lambda: {default_})" missing_default = missing_value if (incompatible_annotation_type or incompatible_value_type or missing_default): missing_default = True collect_imports(imports, type_) if missing_default: if incompatible_annotation_type: default_ = f"MISSING # {type_str(p.annotation)}" elif incompatible_value_type: default_ = f"MISSING # {type_str(type(p.default))}" else: default_ = "MISSING" string_imports.add("from omegaconf import MISSING") params.append( Parameter( name=name, type_str=type_str(type_), default=default_, )) classes_map[class_name] = ClassInfo( target=full_name, module=module.name, name=class_name, parameters=params, ) template = jinja_env.get_template("module.j2") return template.render( imports=convert_imports(imports, string_imports), classes=module.classes, classes_map=classes_map, header=cfg.header, )
def generate_module(cfg: ConfigenConf, module: ModuleConf) -> str: classes_map: Dict[str, ClassInfo] = {} imports = set() string_imports: Set[str] = set() # Iterate through the classes in a given module. for class_name in module.classes: full_name = f"{module.name}.{class_name}" # Get class and init method sygnature. cls = hydra.utils.get_class(full_name) sig = inspect.signature(cls) # Iterate throught init arguments. params: List[Parameter] = [] for name, p in sig.parameters.items(): type_ = p.annotation default_ = p.default missing_value = default_ == sig.empty incompatible_value_type = not missing_value and is_incompatible( type(default_)) missing_annotation_type = type_ == sig.empty incompatible_annotation_type = not missing_annotation_type and is_incompatible( type_) if missing_annotation_type or incompatible_annotation_type: type_ = Any collect_imports(imports, Any) if not missing_value: if type_ == str or type(default_) == str: default_ = f'"{default_}"' elif isinstance(default_, list): default_ = f"field(default_factory=lambda: {default_})" elif isinstance(default_, dict): default_ = f"field(default_factory=lambda: {default_})" missing_default = missing_value if incompatible_annotation_type or incompatible_value_type or missing_default: missing_default = True collect_imports(imports, type_) if missing_default: if incompatible_annotation_type: default_ = f"MISSING # {type_str(p.annotation)}" elif incompatible_value_type: default_ = f"MISSING # {type_str(type(p.default))}" else: default_ = "MISSING" string_imports.add("from omegaconf import MISSING") params.append( Parameter( name=name, type_str=type_str(type_), default=default_, )) # Process module URL. if module.url is not None: url = ( "\"\"\"For more details on parameteres please refer to the original documentation:\n" " {}\n \"\"\"".format(module.url)) else: url = "None" classes_map[class_name] = ClassInfo( url=url, target=full_name, module=module.name, name=class_name, parameters=params, ) template = jinja_env.get_template("module.j2") return template.render( imports=convert_imports(imports, string_imports), classes=module.classes, classes_map=classes_map, header=cfg.header, )