您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

generate.py 3.1 KiB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. import os
  2. import sys
  3. from typing import Iterable
  4. from jinja2 import Environment, FileSystemLoader, Template
  5. import config as cfg
  6. from . import app_root_dir, doc_root_dir, resource_dir, template_dir
  7. _usage = "Usage: generate.py <provider>"
  8. def load_tmpl(tmpl: str) -> Template:
  9. env = Environment(loader=FileSystemLoader(template_dir()))
  10. env.filters["up_or_title"] = up_or_title
  11. return env.get_template(tmpl)
  12. def up_or_title(pvd: str, s: str) -> str:
  13. if s in cfg.UPPER_WORDS.get(pvd, ()):
  14. return s.upper()
  15. if s in cfg.TITLE_WORDS.get(pvd, {}):
  16. return cfg.TITLE_WORDS[pvd][s]
  17. return s.title()
  18. def gen_classes(pvd: str, typ: str, paths: Iterable[str]) -> str:
  19. """Generate all service node classes based on resources paths with class templates."""
  20. tmpl = load_tmpl(cfg.TMPL_MODULE)
  21. # TODO: extract the gen class metas for sharing
  22. # TODO: independent function for generating all pvd/typ/paths pairs
  23. def _gen_class_meta(path: str) -> dict:
  24. base = os.path.splitext(path)[0]
  25. name = "".join([up_or_title(pvd, s) for s in base.split("-")])
  26. return {"name": name, "icon": path}
  27. metas = map(_gen_class_meta, paths)
  28. aliases = cfg.ALIASES[pvd][typ] if typ in cfg.ALIASES[pvd] else {}
  29. return tmpl.render(pvd=pvd, typ=typ, metas=metas, aliases=aliases)
  30. def gen_apidoc(pvd: str, typ_paths: dict) -> str:
  31. tmpl = load_tmpl(cfg.TMPL_APIDOC)
  32. # TODO: remove
  33. def _gen_class_name(path: str) -> str:
  34. base = os.path.splitext(path)[0]
  35. name = "".join([up_or_title(pvd, s) for s in base.split("-")])
  36. return name
  37. typ_classes = {}
  38. for typ, paths in sorted(typ_paths.items()):
  39. typ_classes[typ] = []
  40. for name in map(_gen_class_name, paths):
  41. alias = cfg.ALIASES[pvd].get(typ, {}).get(name)
  42. typ_classes[typ].append({"name": name, "alias": alias})
  43. return tmpl.render(pvd=pvd, typ_classes=typ_classes)
  44. def make_module(pvd: str, typ: str, classes: str) -> None:
  45. """Create a module file"""
  46. mod_path = os.path.join(app_root_dir(pvd), f"{typ}.py")
  47. with open(mod_path, "w+") as f:
  48. f.write(classes)
  49. def make_apidoc(pvd: str, content: str) -> None:
  50. """Create an api documentation file"""
  51. mod_path = os.path.join(doc_root_dir(), f"{pvd}.md")
  52. with open(mod_path, "w+") as f:
  53. f.write(content)
  54. def generate(pvd: str) -> None:
  55. """Generates a service node classes."""
  56. typ_paths = {}
  57. for root, _, files in os.walk(resource_dir(pvd)):
  58. # Extract the names and paths from resources.
  59. files.sort()
  60. pngs = list(filter(lambda f: f.endswith(".png"), files))
  61. paths = list(filter(lambda f: "rounded" not in f, pngs))
  62. # Skip the top-root directory.
  63. typ = os.path.basename(root)
  64. if typ == pvd:
  65. continue
  66. classes = gen_classes(pvd, typ, paths)
  67. make_module(pvd, typ, classes)
  68. typ_paths[typ] = paths
  69. # Build API documentation
  70. apidoc = gen_apidoc(pvd, typ_paths)
  71. make_apidoc(pvd, apidoc)
  72. if __name__ == "__main__":
  73. pvd = sys.argv[1]
  74. if pvd not in cfg.PROVIDERS:
  75. sys.exit()
  76. generate(pvd)