def parse_commands(body_text): ast = gfm.parse(body_text) for para in ast.children: # This makes us ignore commands inside blockquotes, lists, code # blocks, etc. if not isinstance(para, marko.block.Paragraph): continue # Within a paragraph, we want to find RawText chunks that cover an # entire line. So they should start/end with the edge of the paragraph # *or* a LineBreak. In commonmark, there's a distinction between # "soft" and "hard" line breaks, but in practice github seems to # render both of them as hard line breaks, so we don't bother # distinguishing. def is_line_boundary(i): if i < 0: return True if i >= len(para.children): return True if isinstance(para.children[i], marko.inline.LineBreak): return True return False for i, child in enumerate(para.children): if ( is_line_boundary(i - 1) and is_line_boundary(i + 1) and isinstance(child, marko.inline.RawText) ): line = child.children.strip() if line.startswith("/"): yield line.split()
def collect(self): examples = lisp_examples(gfm.parse(slurp(self.fspath))) for index, example in enumerate(examples): yield ReadmeItem.from_parent( self, name=str(index + 1), code=example['code'], # mandatory output=example.get('output'), # might not be present )
def get_spec(file_name: Path, preset: Dict[str, str], config: Dict[str, str]) -> SpecObject: functions: Dict[str, str] = {} protocols: Dict[str, ProtocolDefinition] = {} constant_vars: Dict[str, VariableDefinition] = {} preset_vars: Dict[str, VariableDefinition] = {} config_vars: Dict[str, VariableDefinition] = {} ssz_dep_constants: Dict[str, str] = {} ssz_objects: Dict[str, str] = {} dataclasses: Dict[str, str] = {} custom_types: Dict[str, str] = {} with open(file_name) as source_file: document = gfm.parse(source_file.read()) current_name = None should_skip = False for child in document.children: if isinstance(child, BlankLine): continue if should_skip: should_skip = False continue if isinstance(child, Heading): current_name = _get_name_from_heading(child) elif isinstance(child, FencedCode): if child.lang != "python": continue source = _get_source_from_code_block(child) if source.startswith("def"): current_name = _get_function_name_from_source(source) self_type_name = _get_self_type_from_source(source) function_def = "\n".join(line.rstrip() for line in source.splitlines()) if self_type_name is None: functions[current_name] = function_def else: if self_type_name not in protocols: protocols[self_type_name] = ProtocolDefinition( functions={}) protocols[self_type_name].functions[ current_name] = function_def elif source.startswith("@dataclass"): dataclasses[current_name] = "\n".join( line.rstrip() for line in source.splitlines()) elif source.startswith("class"): class_name, parent_class = _get_class_info_from_source(source) # check consistency with spec assert class_name == current_name if parent_class: assert parent_class == "Container" # NOTE: trim whitespace from spec ssz_objects[current_name] = "\n".join( line.rstrip() for line in source.splitlines()) else: raise Exception("unrecognized python code element") elif isinstance(child, Table): for row in child.children: cells = row.children if len(cells) >= 2: name_cell = cells[0] name = name_cell.children[0].children value_cell = cells[1] value = value_cell.children[0].children if isinstance(value, list): # marko parses `**X**` as a list containing a X value = value[0].children if not _is_constant_id(name): # Check for short type declarations if value.startswith("uint") or value.startswith( "Bytes") or value.startswith("ByteList"): custom_types[name] = value continue if value.startswith("get_generalized_index"): ssz_dep_constants[name] = value continue value_def = _parse_value(name, value) if name in preset: preset_vars[name] = VariableDefinition( value_def.type_name, preset[name], value_def.comment) elif name in config: config_vars[name] = VariableDefinition( value_def.type_name, config[name], value_def.comment) else: constant_vars[name] = value_def elif isinstance(child, LinkRefDef): comment = _get_eth2_spec_comment(child) if comment == "skip": should_skip = True return SpecObject( functions=functions, protocols=protocols, custom_types=custom_types, constant_vars=constant_vars, preset_vars=preset_vars, config_vars=config_vars, ssz_dep_constants=ssz_dep_constants, ssz_objects=ssz_objects, dataclasses=dataclasses, )