def cleanup(self): """ Cleanup whenever the task runner is terminated. Clear status file and remove pid file. """ TaskRunner.remove_status() TaskRunner.signal_terminated()
class MediaBackendSection(BackendSection): """ Backend section for editing general media content such as images and documents. """ title = 'Media' sections = [ ImageBackendSection(), DocumentBackendSection(), FolderBackendSection() ] + ([ProcessingMediaSection()] if TaskRunner.is_available() else [])
def create_blank_external_media(self, url, filename=None, caption=None, folder=None): """ Create a new (blank) media item with the given external url and optionally the given parent folder. """ media = Media() media.is_blank = True media.external_url = url # generate filename based on given url url_parts = urlparse.urlparse(url) path = url_parts.path # filename if filename: media.filename = filename else: media.filename = os.path.basename(path) # generate caption from filename if caption: media.caption = caption else: media.caption = get_caption_from_filename(media.filename) # folder if folder: media.folder = folder media.save() # notify task runner that there is something to do TaskRunner.notify() return media
def handle(self, *args, **options): """ Run command. """ # sleep for a random amount of time in case we are trying to # start the task runner multiple times. time.sleep(random.uniform(0.0, 3.0)) # immediatly exit if another instance of the task runner is # already running... if TaskRunner.is_running(): return # mark ourselves as running TaskRunner.signal_running() # setup cleanup handler that is executed whenever we terminate signal.signal(signal.SIGTERM, self.kill_handler) # whenever we have a fresh re-start, notify yourself, so that we might # pick up any work that is left to do for us, we might have missed # a previous notification... TaskRunner.notify() # continiously execute background work unless we do not have any more # work while True: if TaskRunner.has_work(): # indicate that there is no more work, since we are about to run TaskRunner.signal_no_work() # execute background tasks runner = self.create_task_runner() runner.run() # wait for further work to appear... if not self.wait_for_work(): break # terminate self.cleanup()
def wait_for_work(self): """ Periodically check if there is more work. After having waited for more work to appear for a while, stop waiting. """ start_time = time.time() while not TaskRunner.has_work(): # sleep and stop waiting if we get interrupted by user try: time.sleep(self.WAIT_FOR_WORK_SLEEP_SEC) except KeyboardInterrupt: return False # determine total waiting time so far and stop waiting once # we waited long enought... time_ellapsed_sec = time.time() - start_time if time_ellapsed_sec > self.MAX_WAIT_FOR_WORK_SEC: return False return True
def download_media(self, url, folder=None): """ Download a media asset with given link (or receive from previously downloaded asset). """ url = self.get_download_link(url) try: m = Media.objects.get(external_url=url) except Media.DoesNotExist: # create empty media item if TaskRunner.is_available(): m = self.cms.create_blank_external_media(url, folder=folder) else: m = self.cms.create_media_from_url(url, folder=folder) m.external_url = url if m.pk is None or m.parent_id != folder.pk: m.parent = folder m.save() return m
def import_from_stream(self, request, stream, encoding=DETECT_ENCODING): """ Import shop data from given stream, read the data as CSV data, process the data through model forms and import successfully validated data for products, SKUs, categories and images. """ # create CSV reader self._reader = csv.reader(utf8_stream(stream, encoding=encoding), delimiter=b',', quotechar=b'"', quoting=csv.QUOTE_ALL) self._request = request self._line = 1 self._user = request.user self._errors = [] self._row_error_occured = False self._num_records_processed = 0 # get cms self.cms = get_cms() # skip lines lines_skipped = settings.CUBANE_SHOP_IMPORT.get('skip') self._skip_lines(lines_skipped) # read headers (header, header_labels) = self._get_headers() # read data lines as dict. data = self._get_lines_as_dict(header) # verify input data self.verify_data(data) # import categories self.import_categories(data) # import varieties and options varieties = self.import_varieties(header_labels) self.import_varity_options(data, varieties) # import products, variety assignments and SKUs groups = self.import_products(data) self.import_variety_assignments(groups, varieties) self.import_product_sku(groups, varieties) # download and import images, but only if we have not observed any # errors yet, otherwise it is likely that we will end up downloading # media data for no good reason, since we will revert all changes due # to errors anyhow... if self._import_images and not self.has_errors: self.import_images(groups) if TaskRunner.is_available(): TaskRunner.notify() # collect row-specific errors for row in data: if self._row_has_errors(row): for error in row.get('_errors', []): self._error_on_line( row.get('_line_number'), error.get('message'), self._get_row_html_excerpt(row, error.get('field'), header_labels)) # sort error messages by line number self._errors.sort(key=lambda error: error.get('line')) # number of records processed self._num_records_processed = len(data)
def terminate_task_runner(self): """ Terminate task runner if running. """ if TaskRunner.is_available(): TaskRunner.terminate()
def create_task_runner(self): """ Create a new instance of the task runner. """ return TaskRunner()
def _create_edit(self, request, pk=None, edit=False, duplicate=False): if not edit and len(request.FILES.getlist('media')) > 1: # cancel? if request.POST.get('cubane_form_cancel', '0') == '1': return self._redirect(request, 'index') kwargs = {} # create form if request.method == 'POST': form = MultiMediaForm(request.POST, request.FILES, **kwargs) else: form = MultiMediaForm(**kwargs) form.configure(request) # validate form if request.method == 'POST' and form.is_valid(): # update properties in model instance d = form.cleaned_data if 'media' in request.FILES: file_list = request.FILES.getlist('media') n = 0 Progress.start(request, len(file_list)) first_instance = None for f in file_list: instance = self.model() instance.parent = d.get('parent') if first_instance is None: first_instance = instance # auto fit if settings.IMAGE_FITTING_ENABLED and settings.IMAGE_FITTING_SHAPES: instance.auto_fit = d.get('auto_fit') # jpeg quality instance.jpeg_quality = d.get('jpeg_quality') # save instance.save() instance.upload_save_from_stream(f, request=request) n += 1 request.changelog.create(instance) # notify task runner to do the job if instance.is_blank: TaskRunner.notify() # report progress made Progress.set_progress(request, n) # commit changes message = '<em>%d</em> %s created.' % ( n, self.model._meta.verbose_name_plural) change = request.changelog.commit(message, model=self.model) Progress.stop(request) # ajax operation, simply return success and message # information if request.is_ajax(): return to_json_response({ 'success': True, 'message': message, 'change': change, 'next': self._get_url(request, 'index', namespace=True), 'instance_id': first_instance.pk, 'instance_title': unicode(first_instance), }) # dialog or screen? if request.GET.get('create', 'false') == 'true': return { 'dialog_created_id': instance.pk, 'dialog_created_title': unicode(instance) } else: return self._redirect(request, 'index') elif request.is_ajax(): return to_json_response({ 'success': False, 'errors': form.errors }) context = { 'form': form, 'permissions': { 'create': self.user_has_permission(request.user, 'add'), 'view': self.user_has_permission(request.user, 'view'), 'edit': self.user_has_permission(request.user, 'edit') }, 'verbose_name': 'Multiple Media' } else: if request.method == 'POST': Progress.start(request, 1) context = super(MediaView, self)._create_edit(request, pk, edit, duplicate) if isinstance(context, dict): context['is_images'] = isinstance(self, ImageView) return context