def get_providers(capabilities=None, path=False) -> list: """Get all providers, and filter their sub providers""" def walk(root): """Recursively walk subclasses of <root>""" subclasses = root.__subclasses__() result = [] if subclasses != []: for subclass in subclasses: result += walk(subclass) # else: if root != BaseProvider: result += [root] return result providers = walk(BaseProvider) # Filter out the sub valid = [] for provider in list(set(providers)): provider_meta = provider.Meta(None) if provider_meta.selectable: # Optionally check for matching capabilities if capabilities: qualified = True for capability in capabilities: if capability not in provider_meta.capabilities: qualified = False if qualified: valid.append(provider) else: valid.append(provider) # if path is True, convert classes to dotted path if path: return [class_to_path(provider) for provider in valid] return sorted(valid, key=lambda provider: provider.Meta(None).ui_name)
def provider_pre_delete(sender, instance, **kwargs): """Forward signal to ChangeBuilder""" from supervisr.core.providers.multiplexer import ProviderMultiplexer from supervisr.core.providers.objects import ProviderAction from supervisr.core.models import ProviderTriggerMixin if issubclass(instance.__class__, ProviderTriggerMixin): LOGGER.debug("ProviderTriggerMixin pre_delete") args = (ProviderAction.DELETE, class_to_path(instance.__class__), instance.pk) system_user.task_apply_async(ProviderMultiplexer(), *args)
def get_form(self, *args, instance: ProviderInstance, **kwargs) -> ProviderForm: form = super().get_form(*args, instance=instance, **kwargs) providers = get_providers() credentials = BaseCredential.objects.filter(owner=self.request.user) form_providers = [(class_to_path(s), '%s (%s)' % (s.Meta(None).ui_name, s.__class__.__name__)) for s in providers] form.request = self.request form.fields['provider_path'].choices = form_providers form.fields['credentials'].queryset = credentials return form
def get_form(self, step=None, data=None, files=None): form = super(ProviderCreateView, self).get_form(step, data, files) if step is None: step = self.steps.current if step == '0': self.providers = get_providers() creds = BaseCredential.objects.filter(owner=self.request.user) form.fields['provider_path'].choices = [(class_to_path(s), s.Meta(None).ui_name) for s in self.providers] form.fields['credentials'].queryset = creds form.request = self.request return form
def get_context_data(self, form, **kwargs): context = super(ProviderCreateView, self).get_context_data(form=form, **kwargs) if self.steps.current == '0': template_provider_info = {} for provider in self.providers: provider_meta = provider.Meta(None) template_provider_info[class_to_path(provider)] = { 'ui_name': provider_meta.ui_name, 'ui_description': provider_meta.ui_description, 'capabilities': ', '.join(provider_meta.capabilities), 'author': provider_meta.get_author, } context.update({'providers': template_provider_info}) return context
def post(self, request: HttpRequest) -> HttpResponse: """Start task and redirect to ourselves with task_id""" instance = get_object_or_404(self.get_instance()) if isinstance(instance, CastableModel): instance = instance.cast() if not isinstance(instance, ProviderTriggerMixin): raise ValueError('Model instance must inherit `ProviderTriggerMixin`') action = ProviderAction(int(request.POST.get('action'))) # Start multiplexer LOGGER.debug("ProviderTriggerMixin post_save") args = (action, class_to_path(instance.__class__), instance.pk) kwargs = {'created': False, 'user_triggered': True} # User permissions are not checked here since they are checked in # GenericModelView.get_instance request.user.task_apply_async(ProviderMultiplexer(), *args, **kwargs) return self.redirect(instance)
def get_model_handlers(self, action: ProviderAction, instance: ProviderTriggerMixin, **kwargs) -> int: """Notify providers that model was saved/deleted so translation can start Args: action (ProviderAction): Which action to perform invoker (User): User invoking the task instance (Model): Model instance which has been saved """ from supervisr.core.providers.tasks import provider_do_work LOGGER.debug("instance %r, action %r", instance, action) for provider in instance.provider_instances: LOGGER.debug("\tprovider_instance %r", provider) class_path = class_to_path(instance.__class__) args = (action, provider.pk, class_path, instance.pk) CELERY_APP.control.add_consumer(class_path) LOGGER.debug("\tstarted task provider_do_work") yield provider_do_work.signature(args, kwargs).set(queue=class_path)
def dotted_path(self): """Return absolute module and class path""" return class_to_path(self.__class__)
def get_unique(self, model: Model) -> str: """Get unique Model identifier""" return "%s#%s" % (class_to_path(model.__class__), model.pk)
def get_label(self, model: Model) -> str: """Get label for model""" return "%s | %s" % (class_to_path(model.__class__), str(model))