def define(name, prop=None): """appfile 의 정의를 확장한다. name 은 최상단 파라미터의 이름. prop 는 파라미터의 형을 지정하는 :py:class:`flowdas.meta.Property` 인스턴스. 생략하면 :py:class:`flowdas.meta.String` (). 이미 정의되어 있다면 오버라이드 한다. Since version 0.1. """ if prop is None: prop = meta.String() _defines[name] = prop
class U(meta.Union): s = meta.Integer(ordered=True) m = meta.String(ordered=True)
class DefaultProject(Project): kind = 'python-docs-ko' msg_repo = meta.String() ignores = meta.String[:](required=True) deprecated = meta.String[:](required=True) def get_doc_dir(self): return 'Doc' def get_src_links(self): return [ 'Misc', 'README.rst', 'LICENSE', 'Include/Python.h', 'Python/ceval.c', 'Include/patchlevel.h', 'Parser/Python.asdl', 'Tools/scripts/diff.py', 'Lib/test/exception_hierarchy.txt', 'Tools/scripts/serve.py', 'Grammar/Grammar', ] def get_msg_dir(self): return 'locale/ko/LC_MESSAGES' def get_bld_dir(self): return 'Doc/build' def get_htm_dir(self): return 'html' def get_build_cmd(self, *, rebuild=False): if rebuild: return "make VENVDIR=../../.. SPHINXOPTS='-D locale_dirs=../locale -D language=ko -D gettext_compact=0' autobuild-dev-html" else: return "make VENVDIR=../../.. SPHINXOPTS='-D locale_dirs=../locale -D language=ko -D gettext_compact=0 -A daily=1 -A switchers=1' html" def get_build_dir(self): return 'Doc' def setup(self): app = App() if self.msg_repo: msg_dir = app.home / self.name / 'msg' if not (msg_dir / '.git').exists(): git_clone(self.msg_repo, msg_dir, '3.8') if not app.config.docker: try: shell(f'{app.config.docker_cmd} image inspect {app.image}', capture=True) except: shell(f'{app.config.docker_cmd} pull {app.image}') def docker_build(self, *, rebuild=False): if self.name == 'python-docs-ko': app = App() home = str(app.home / 'python-docs-ko') volumes = ' '.join( f'-v {home}/{x}:/python-docs-ko/python-docs-ko/{x}' for x in ( 'project.yaml', 'msg', 'bld', )) options = ' --rebuild' if rebuild else '' return shell( f'{app.config.docker_cmd} run --rm -i {volumes} {app.image} build{options}', chdir=home) else: super().docker_build(rebuild=rebuild)
class Project(meta.Entity): kind = meta.Kind() name = meta.String(required=True) cname = meta.String() @property def home(self): return App().home / self.name def get_doc_dir(self): return '.' def get_src_links(self): return None def get_msg_dir(self): return None def get_bld_dir(self): return None def get_htm_dir(self): return None def get_build_cmd(self, *, rebuild=False): raise NotImplementedError def get_build_dir(self): return '.' def _create_symlink(self, symlink, to): np = len(pathlib.Path(os.path.commonpath([symlink, to])).parts) parts = ('..', ) * (len(symlink.parts) - np - 1) + to.parts[np:] relpath = os.path.sep.join(parts) symlink.parent.mkdir(parents=True, exist_ok=True) symlink.symlink_to(relpath, target_is_directory=to.is_dir()) def setup(self): pass def docker_build(self, *, rebuild=False): app = App() home = str(app.home) volumes = f'-v {home}/{self.name}:/python-docs-ko/{self.name}' options = f'--project={self.name}' if rebuild: options += ' --rebuild' return shell( f'{app.config.docker_cmd} run --rm -i {volumes} {app.image} build {options}', chdir=home) def _prune_dir(self, root): if root.exists(): with os.scandir(root) as it: for entry in it: if not entry.name.startswith('.'): path = os.path.join(root, entry.name) if entry.is_file(): os.remove(path) else: shutil.rmtree(path) def build(self, *, rebuild=False): app = App() if app.config.docker: tmp_dir = self.home / 'tmp' if tmp_dir.exists(): shutil.rmtree(tmp_dir) pub_dir = self.home / 'pub' publish = pub_dir.exists() and rebuild if publish: self._prune_dir(self.home / 'bld') self.copy_doc() self.link_msg() self.link_bld() shell(self.get_build_cmd(rebuild=rebuild), chdir=tmp_dir / self.get_build_dir()) if publish: self._prune_dir(pub_dir) self.copy_pub() else: self.docker_build(rebuild=rebuild) def _annotate(self, src, dst, ann): dst.mkdir(parents=True, exist_ok=True) for src_child in src.iterdir(): dst_child = dst / src_child.name ann_child = ann / src_child.name if src_child.is_dir(): if src_child.name not in {'__pycache__'}: self._annotate(src_child, dst_child, ann_child) elif ann_child.exists(): original = src_child.read_text() aofile = AOFile(ann_child) annotated = aofile.render(original) dst_child.write_text(annotated) mtime0 = src_child.stat().st_mtime mtime1 = ann_child.stat().st_mtime if mtime1 > mtime0: times = (ann_child.stat().st_atime, mtime1) else: times = (src_child.stat().st_atime, mtime0) os.utime(dst_child, times) else: shutil.copy2(src_child, dst_child) def copy_doc(self): src_dir = self.home / 'src' / self.get_doc_dir() dst_dir = self.home / 'tmp' / self.get_doc_dir() mod_dir = self.home / 'mod' if mod_dir.exists(): self._annotate(src_dir, dst_dir, mod_dir) else: if not dst_dir.exists() or not src_dir.samefile(dst_dir): shutil.copytree(src_dir, dst_dir, ignore=shutil.ignore_patterns('.git')) for link in (self.get_src_links() or []): self._create_symlink(self.home / 'tmp' / link, self.home / 'src' / link) def _link_dir(self, target_dir, source_dir): if source_dir: (self.home / target_dir).mkdir(exist_ok=True) self._create_symlink(self.home / 'tmp' / source_dir, self.home / target_dir) def link_msg(self): self._link_dir('msg', self.get_msg_dir()) def link_bld(self): self._link_dir('bld', self.get_bld_dir()) def copy_pub(self): htm_dir = self.get_htm_dir() if htm_dir: src = self.home / 'bld' / htm_dir if src.exists(): ignore = shutil.ignore_patterns('.*') dst = self.home / 'pub' for child in src.iterdir(): if child.name.startswith('.'): continue if child.is_dir(): shutil.copytree(child, dst / child.name, ignore=ignore) else: shutil.copy2(child, dst / child.name) # create empty files for name in ['.nojekyll']: path = dst / name if not path.exists(): path.write_text('') # create CNAME if self.cname: (dst / 'CNAME').write_text(self.cname)
class X(meta.Entity): p = meta.Tuple(meta.Integer(), meta.String(view='secret'))