def handle_request(self) -> Optional[str]: """Actually handle a request. Called by `do_HEAD` and `do_GET`.""" path = self.path.split("?", 1)[0] if path == "/": out = render.html_index(self.server.all_modules) else: module = removesuffix(path.lstrip("/"), ".html").replace("/", ".") if module not in self.server.all_modules: self.send_response(404) self.send_header("content-type", "text/html") self.end_headers() return render.html_error(error=f"Module {module!r} not found") mtime = "" t = extract.module_mtime(module) if t: mtime = f"{t:.1f}" if "mtime=1" in self.path: self.send_response(200) self.send_header("content-type", "text/plain") self.end_headers() return mtime try: extract.invalidate_caches(module) mod = doc.Module(extract.load_module(module)) except Exception: self.send_response(500) self.send_header("content-type", "text/html") self.end_headers() return render.html_error( error=f"Error importing {module!r}", details=traceback.format_exc(), ) out = render.html_module( module=mod, all_modules=self.server.all_modules, mtime=mtime, ) self.send_response(200) self.send_header("content-type", "text/html") self.end_headers() return out
def pdoc( *modules: Union[Path, str], output_directory: Optional[Path] = None, format: Literal["html"] = "html", ) -> str: """ Render the documentation for a list of modules. - If `output_directory` is `None`, returns the rendered documentation for the first module in the list. - If `output_directory` is set, recursively writes the rendered output for all specified modules and their submodules to the target destination. Rendering options can be configured by calling `pdoc.render.configure` in advance. """ retval = io.StringIO() if output_directory: def write(mod: doc.Module): assert output_directory outfile = output_directory / f"{mod.fullname.replace('.', '/')}.html" outfile.parent.mkdir(parents=True, exist_ok=True) outfile.write_bytes(r(mod).encode()) else: def write(mod: doc.Module): retval.write(r(mod)) all_modules = extract.parse_specs(modules) if format == "html": def r(mod: doc.Module) -> str: return render.html_module(module=mod, all_modules=all_modules) elif format == "markdown": # pragma: no cover raise NotImplementedError( "Markdown support is currently unimplemented, but PRs are welcome!" ) elif format == "repr": r = render.repr_module else: raise ValueError(f"Invalid rendering format {format!r}.") for mod in all_modules: try: m = extract.load_module(mod) except RuntimeError: warnings.warn(f"Error importing {mod}:\n{traceback.format_exc()}", RuntimeWarning) else: write(doc.Module(m)) if not output_directory: return retval.getvalue() assert output_directory if format == "html": index = render.html_index(all_modules) if index: (output_directory / "index.html").write_bytes(index.encode()) return retval.getvalue()