Source code for jenni.models.folderbase
import logging
import sys
from abc import ABC
from importlib import import_module
from io import TextIOWrapper
from pathlib import Path
from types import ModuleType
from typing import Type, Optional
from jenni.models import itembase
from jenni.models.itembase import ItemBase
from jenni.utils import tidy_text, quote3xs
[docs]class FolderBase(ItemBase, ABC):
[docs] def yield_items(self, module_name_to_load: str = ""):
"""
Yield this folder and any items generated by python files below this folder.
Overwrite in subclasses to dynamically generate items, but always insert this:
``yield from super().yield_items(module_name_to_load)``
"""
# logging.debug(f"yield_items({self}, '{module_name_to_load}'")
yield from super().yield_items(module_name_to_load)
module: ModuleType = sys.modules[self.__module__]
# For dynamically generated modules we do not scan for nested .py files.
if getattr(module, "is_dynamically_generated", False):
return
py_file: Path
folder_path = Path(module.__file__).parent
for py_file in list(folder_path.glob("*.py")) + list(folder_path.glob("*/__init__.py")):
if py_file.name == "__init__.py":
if py_file.parent == folder_path:
continue
item_name = py_file.parent.name
module_name = f"{self.__module__}.{py_file.parent.name}.{py_file.name}"[:-12]
else:
item_name = py_file.name[:-3]
module_name = f"{self.__module__}.{py_file.name}"[:-3]
logging.debug(f"Importing module {module_name}")
module = import_module(module_name)
item: Optional[ItemBase] = itembase.item_by_module.get(module_name)
if item is None:
module.__parent_item__ = self
module.__item_name__ = item_name
if module.__file__.endswith("__init__.py"):
if hasattr(module, "Folder"):
item = module.Folder()
item.parent.add_new_folder(item)
else:
raise SystemExit(f"Module {module} should contain Folder class")
else:
if hasattr(module, "Job"):
item = module.Job()
item.parent.add_new_job(item)
else:
raise SystemExit(f"Module {module} should contain Job class")
yield from item.yield_items()
[docs] def add_new_job(self, job: "jenni.models.jobbase.JobBase"):
"""
Called after a job has been added to this folder.
The job can be customised by overriding this method.
"""
pass
[docs] def add_new_folder(self, sub_folder: "jenni.models.folderbase.FolderBase"):
"""
Called after a sub-folder has been added to this folder.
The sub-folder can be customised by overriding this method.
Note yield_items() is not yet called on this job.
"""
pass
[docs] def yield_items_pre_sub_item(self, sub_item: ItemBase):
"""
Called before sub_item.yield_items() is called.
:param sub_item: the sub-item of this folder, just before calling yield_items on it.
"""
yield from ()
[docs] def yield_items_post_sub_item(self, sub_item: ItemBase):
"""
Called after sub_item.yield_items() has been called.
:param sub_item: the sub-item of this folder, just after calling yield_items on it.
"""
yield from ()
[docs] def sub_item_completed_handler(self, sub_item: ItemBase):
"""
Called after a sub-item has been added to this folder
and all yielding has completed for it.
The item can be customised by overriding this method.
"""
pass
[docs] def write_jobdsl(self, fp: TextIOWrapper):
logging.debug(f"write_jobdsl start {self}")
# Root folder doesn't need creating:
if self.parent is None:
return
jobdsl = [
"folder('" + self.jenkins_path + "') {",
f" displayName({quote3xs(self.name if self.title == '' else self.title)})",
f""" description({quote3xs(tidy_text(self.description))})""",
"}",
]
fp.write("\n".join(jobdsl))