Du kannst nicht mehr als 25 Themen auswählen Themen müssen entweder mit einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.
 
 
 
 
 

108 Zeilen
3.3 KiB

  1. import os
  2. import sys
  3. from typing import Iterable
  4. from jinja2 import Environment, FileSystemLoader, Template, exceptions
  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. try:
  32. default_tmp = cfg.TMPL_APIDOC.split('.')
  33. tmpl_file = f"{default_tmp[0]}_{pvd}.{default_tmp[1]}"
  34. tmpl = load_tmpl(tmpl_file)
  35. except exceptions.TemplateNotFound:
  36. tmpl = load_tmpl(cfg.TMPL_APIDOC)
  37. # TODO: remove
  38. def _gen_class_name(path: str) -> str:
  39. base = os.path.splitext(path)[0]
  40. name = "".join([up_or_title(pvd, s) for s in base.split("-")])
  41. return name
  42. typ_classes = {}
  43. for typ, paths in sorted(typ_paths.items()):
  44. typ_classes[typ] = []
  45. for name in map(_gen_class_name, paths):
  46. alias = cfg.ALIASES[pvd].get(typ, {}).get(name)
  47. typ_classes[typ].append({"name": name, "alias": alias})
  48. return tmpl.render(pvd=pvd, typ_classes=typ_classes)
  49. def make_module(pvd: str, typ: str, classes: str) -> None:
  50. """Create a module file"""
  51. mod_path = os.path.join(app_root_dir(pvd), f"{typ}.py")
  52. with open(mod_path, "w+") as f:
  53. f.write(classes)
  54. def make_apidoc(pvd: str, content: str) -> None:
  55. """Create an api documentation file"""
  56. mod_path = os.path.join(doc_root_dir(), f"{pvd}.md")
  57. with open(mod_path, "w+") as f:
  58. f.write(content)
  59. def generate(pvd: str) -> None:
  60. """Generates a service node classes."""
  61. typ_paths = {}
  62. for root, _, files in os.walk(resource_dir(pvd)):
  63. # Extract the names and paths from resources.
  64. files.sort()
  65. pngs = list(filter(lambda f: f.endswith(".png"), files))
  66. paths = list(filter(lambda f: "rounded" not in f, pngs))
  67. # Skip the top-root directory.
  68. typ = os.path.basename(root)
  69. if typ == pvd:
  70. continue
  71. classes = gen_classes(pvd, typ, paths)
  72. make_module(pvd, typ, classes)
  73. typ_paths[typ] = paths
  74. # Build API documentation
  75. apidoc = gen_apidoc(pvd, typ_paths)
  76. make_apidoc(pvd, apidoc)
  77. if __name__ == "__main__":
  78. pvd = sys.argv[1]
  79. if pvd not in cfg.PROVIDERS:
  80. sys.exit()
  81. generate(pvd)