Source code for ase2sprkkr.gui.examples

""" Function related to ASE2SPRKKR examples """

from pathlib import Path
import ast
import textwrap
import re
import shutil

from ase2sprkkr.common.decorators import cached_property
import ase2sprkkr

[docs] def examples_dir(): """ Base dir for all examples """ return Path(ase2sprkkr.__file__).parent / "examples"
[docs] class Example:
[docs] @staticmethod def by_number(example:int): """ Directory for the given example """ # Find the matching example directory prefix = f"A{example:02d}_" for d in examples_dir().iterdir(): if d.is_dir() and d.name.startswith(prefix): return Example(d) raise FileNotFoundError(f"No example directory matching {prefix}* found.")
[docs] def __init__(self, path: Path): self.dir = path
[docs] def copy(self, dest_dir: str): """ Copy contents of ase2sprkkr.examples.A{n:02d}_* directory into dest_dir and return the path to the .py script inside that example directory (excluding __init__.py). :param n: Example number (integer) :param dest_dir: Destination directory where files will be copied :return: Path to the .py example script """ # Create destination directory dest_dir = Path(dest_dir) dest_dir.mkdir(parents=True, exist_ok=True) # Copy contents of example dir → destination for item in self.dir.iterdir(): dst = dest_dir / item.name if item.name.startswith('__'): continue if item.is_dir(): shutil.copytree(item, dst, dirs_exist_ok=True) else: shutil.copy2(item, dst)
@property def name(self): return self.dir.name @cached_property def main_script(self): """ Find Python script inside example directory (excluding __init__.py). Now we suspose, that the first such one is the main. """ for p in self.dir.glob("*.py"): if p.name != "__init__.py": return p raise FileNotFoundError("No .py script found inside example directory.") @cached_property def docstring(self): # Read the file content source = self.source() # Parse the AST try: tree = ast.parse(source) # Return the module-level docstring return ast.get_docstring(tree) except SyntaxError: return None # in case the file is invalid Python @property def short_docstring(self): def first_sentence(text: str) -> str: match = re.match(r'^\s*([^.]*\.)', text) if match: return match.group(1) return text.strip() if self.docstring is None: return None out = first_sentence(self.docstring) out = re.sub(r'\s*\n\s*', ' ', out) return out
[docs] def source(self): return self.main_script.read_text(encoding="utf-8")
[docs] def body_of_main(self): pattern = re.compile( r"^def\s+main\s*\([^)]*\)\s*:\s*\n" # match 'def main(...):' r"((?:[ \t]+.*\n|\n)+)", # capture indented block re.MULTILINE ) code = self.source() match = pattern.search(code) if not match: return None body = match.group(1) if not body: return code # Dedent the body return textwrap.dedent(body)
[docs] def list_of_examples(): """ Return list of tuples: (subdir_name, docstring of example_main_script) """ base_dir = examples_dir() pattern = re.compile(r"^A\d{2}_") # matches A{number*2}_ return [ Example(d) for d in base_dir.iterdir() if d.is_dir() and pattern.match(d.name) ]