Пример #1
0
    def _construct_models(self):
        # only do this once
        if '_models' in self.__dict__:
            return

        # collect fields for all the models
        blueprints = copy.deepcopy(BASE_MODELS)
        from feedplatform import addins
        for addin in addins.get_addins():
            if hasattr(addin, 'get_fields'):
                for table, new_fields in addin.get_fields().items():
                    if not table in blueprints:
                        blueprints[table] = {}
                    blueprints[table].update(new_fields)

        # "Unregister" current models from storm - otherwise we'll see stuff
        # like "PropertyPathError: Path 'feed_id' matches multiple properties".
        Storm._storm_property_registry.clear()

        # create the actual model objects
        new_models = {}
        for name, fields in blueprints.items():
            table_options = config.TABLES.get(name)
            model_name = cap_model_name(name)
            attrs = {'__storm_table__':
                        getattr(table_options, '__table__', name)}

            for field_name, field_value in fields.items():
                if isinstance(field_value, tuple):
                    klass, args, kwargs = field_value
                    field_value = klass(*args, **kwargs)
                attrs[field_name] = field_value

                # user may want to map this field to a custom table column
                column_name = getattr(table_options, field_name, None)
                if column_name:
                    attrs[field_name]._name = column_name

            model = type(model_name, (Storm,), attrs)
            new_models[model_name] = model

        # don't let invalid entries in config.TABLES go unnoticed
        # XXX: the whole config.TABLES code needs testing
        for model_name, table in config.TABLES.items():
            model_name = cap_model_name(model_name)
            if not model_name in new_models:
                raise ValueError('Failed to process TABLES setting: '
                    '"%s" is not a valid model name' % model_name)

        self._models = new_models
Пример #2
0
def get_commands():
    """Returns a dictionary mapping all available command names to
    either a Command class, or the module name in which the command
    class is defined.

    Commands can be defined:

        - in ``feedplatform/management/commands``, each file
          representing an individual command.

        - by addins.

    The list is loaded once, and then cached.
    """
    global _COMMANDS
    if _COMMANDS is None:
        _COMMANDS = {}
        # load from filesystem
        try:
            command_dir = os.path.join(__path__[0], "commands")
            _COMMANDS.update(
                dict(
                    [
                        (file[:-3], "feedplatform.management.commands")
                        for file in os.listdir(command_dir)
                        if not file.startswith("_") and file.endswith(".py")
                    ]
                )
            )
        except OSError:
            pass

        # load from addins
        for addin in get_addins():
            if hasattr(addin, "get_commands"):
                _COMMANDS.update(addin.get_commands())

    return _COMMANDS
Пример #3
0
    def handle(self, *args, **options):

        # setup the log according to the options requested
        loglevel = options.get('level')
        if loglevel:
            try:
                loglevel = logging._levelNames[loglevel.upper()]
            except KeyError:
                raise CommandError('invalid value for --level: %s' % loglevel)

        logfile = options.get('log')
        if logfile:
            filehandler = logging.FileHandler(logfile)
            filehandler.setFormatter(logging.Formatter(
                '%(asctime)-18s %(name)-12s: %(levelname)-8s %(message)s',
                '%m-%d-%y %H:%M:%S'))
            handlers=[filehandler]
        else:
            handlers = None

        if loglevel or handlers:
            log.reset(level=loglevel, handlers=handlers)


        # determine which daemons are available, and which one to run
        # TODO: better handle duplicate names
        named_daemons = {}
        unnamed_daemons = []
        for addin in addins.get_addins():
            if isinstance(addin, base_daemon):
                if addin.name:
                    named_daemons[addin.name] = addin
                else:
                    unnamed_daemons.append(addin)

        args = list(args)   # make mutable

        if len(named_daemons) + len(unnamed_daemons) == 1:
            # If only one daemon is available, we can start it pretty
            # much right away.
            if named_daemons and args and named_daemons.keys()[0] == args[0]:
                # If the user specified the only existing daemon by
                # name, we make sure that name is not passed along
                # as a subargument to the daemon itself.
                args.remove(args[0])
            daemon_to_start = unnamed_daemons and \
                unnamed_daemons[0] or \
                named_daemons.values()[0]
        # Otherwise, we have to determine which one the use wants to start
        else:
            s_daemon_list = ''
            for name in named_daemons.keys():
                s_daemon_list += '    %s\n' % name
            if unnamed_daemons:
                s_daemon_list += 'Additionally, %d unnamed daemons are '+\
                    'installed.\n' % len(unnamed_daemons)

            if len(args) == 0:
                raise CommandError('multiple daemons are installed, you '
                                   'need to specify which one to run:\n%s' %
                                        s_daemon_list)
            else:
                daemon_name = args[0]
                args.remove(args[0])
                if not daemon_name in named_daemons:
                    raise CommandError('"%s" is not a known daemon, '+
                                       'installed are:\n%s' % s_daemon_list)
                else:
                    daemon_to_start = named_daemons[daemon_name]

        # fork off as daemon, if requested
        if options.get('daemonize'):
            if os.name != 'posix':
                raise CommandError('--daemonize not supported on this platform')
            daemon.daemonize()

        try:
            # If daemon threads make trouble (http://bugs.python.org/issue1856),
            # we can always disable it. It's there for convenience's sake,
            # but our daemons/threads have a stop-flag mechanism that should
            # work just fine as well.
            # TODO: parse the rest of the args, pass along as args/options
            daemon_to_start.start(daemon=True)
            while daemon_to_start.isAlive():
                # join with a timeout, so KeyboardInterrupts get through
                daemon_to_start.join(DEFAULT_LOOP_SLEEP)
        except KeyboardInterrupt:
            daemon_to_start.stop()