Exemple #1
0
 def edit(self, filename):
     """ Edit a file using the configured text editor. """
     #FIXME: edit by calling the locator and manage its local file (e.g. for a URL, point to a temp folder)
     ted = self.console.config['TEXT_EDITOR']
     if which(ted) is None:
         raise ValueError("'%s' does not exist or is not installed" % ted)
     p = Path(self.console.config['WORKSPACE']).joinpath(filename)
     if not p.exists():
         p.touch()
     call([ted, str(p)], stderr=PIPE)
Exemple #2
0
def load_entities(entities, *sources, **kwargs):
    """ Load every entity class of the given type found in the given source folders.
    
    :param sources:       paths (either with ~, relative or absolute) to folders containing entity subclasses
    :param include_base:  include the base entities provided with the package
    :param select:        selected modules in the source folder
    :param exclude:       list of entity identifiers (in custom format, or simply the entity class) to be excluded
                           (useful when including the base but not every entity is required)
    :param backref:       list of attrs to get entity's class to be bound to
    :param docstr_parser: user-defined docstring parser for populating metadata
    """
    global ENTITIES
    ENTITIES = [e.__name__ for e in entities]
    sources = list(sources)
    if kwargs.get("include_base", True):
        # this allows to use sploitkit.base for starting a project with a baseline of entities
        for n in ENTITIES:
            n = n.lower()
            for m in kwargs.get("select", {}).get(n, [""]):
                m = "../base/{}s/".format(n) + m + [".py", ""][m == ""]
                p = Path(__file__).parent.joinpath(m).resolve()
                if p.exists():
                    sources.insert(0, p)
    # load every single source (folder of modules or single module)
    for s in sources:
        if not s.exists():
            logger.debug("Source file does not exist: %s" % s)
            continue
        # bind the source to the entity main class
        for e in entities:
            e._source = str(s)
        # now, it loads every Python module from the list of source folders ; when loading entity subclasses, these are
        #  registered to entity's registry for further use (i.e. from the console)
        logger.debug("Loading Python source: %s" % s)
        PythonPath(s)
    for e in entities:
        tbr = []
        # clean up the temporary attribute
        if hasattr(e, "_source"):
            delattr(e, "_source")
        # remove proxy classes
        n = e.__name__.lower()
        for c in e.subclasses[:]:
            if len(c.__subclasses__()) > 0:
                getattr(e, "unregister_%s" % n, Entity.unregister_subclass)(c)
        # handle specific entities or sets of entities exclusions ; this will remove them from Entity's registries
        excludes = kwargs.get("exclude", {}).get(n)
        if excludes is not None:
            getattr(e, "unregister_%ss" % n, Entity.unregister_subclasses)(*excludes)
        # handle conditional entities ; this will remove entities having a "condition" method returning False
        for c in e.subclasses[:]:
            # convention: conditional entities are unregistered and removed
            if hasattr(c, "condition") and not c().condition():
                getattr(e, "unregister_%s" % n, Entity.unregister_subclass)(c)
        # now populate metadata for each class
        for c in e.subclasses:
            set_metadata(c, kwargs.get("docstr_parser", lambda s: {}))
        # bind entity's subclasses to the given attributes for back-reference
        backrefs = kwargs.get("backref", {}).get(n)
        if backrefs is not None:
            for c in e.subclasses:
                for br in backrefs:
                    try:
                        a, bn = br  # [a]ttribute, [b]ackref [n]ame
                    except ValueError:
                        a, bn = None, br[0] if isinstance(br, tuple) else br
                    bc = list(filter(lambda _: _.__name__.lower() == bn, entities))[0]  # [b]ackref [c]lass
                    if a and getattr(c, a, None):
                        c = getattr(c, a)
                    setattr(c, bn, lambda: bc._instance)
    # then trigger garbage collection (for removed classes)
    gc.collect()