Exemplo n.º 1
0
    async def post(self, uid):
        """Analyze the asset for additional meta data"""

        asset = self.get_asset(
            uid,
            projection={
                '_id': True,
                'type': True,
                'expires': True
            }
        )

        # Extract the analyzers from the request body
        try:
            raw_analyzers = json.loads(self.get_body_argument('analyzers'))
        except:
            raise APIError(
                'invalid_request',
                hint='Analyzers argument is not valid JSON.'
            )

        analyzers = self.validate_analyzers(asset.type, raw_analyzers)

        # Add a task to perform the asset analysis
        notification_url = self.get_body_argument('notification_url', None)

        task = AnalyzeTask(
            self.account._id,
            asset._id,
            analyzers,
            notification_url
        )

        if notification_url:

            # Fire and forget
            await self.add_task_and_forget(task)
            self.finish()

        else:

            # Wait for response
            event = await self.add_task_and_wait(task)

            if not event:
                raise APIError('error', 'Connection lost')

            elif event.type == 'task_error':
                raise APIError('error', event.reason)

            # Fetch the asset again now the analysis is complete
            with Asset.with_options(read_preference=ReadPreference.PRIMARY):
                asset = self.get_asset(
                    uid,
                    projection={
                        'uid': True,
                        'expires': True,
                        'ext': True,
                        'meta': True,
                        'name': True
                    }
                )

            # Handle image expiry
            if not asset:
                raise APIError(
                    'not_found',
                    hint='Asset expired whilst being analyzed'
                )

            json_type = asset.to_json_type()

            self.write({
                'uid': json_type['uid'],
                'meta': json_type['meta']
            })
Exemplo n.º 2
0
    async def put(self):
        """Generate variations for one or more assets"""

        assets = self.get_assets(projection={
            '_id': True,
            'type': True,
            'uid': True
        })

        # Extract the variations from the variations argument
        try:
            raw_variations = json.loads(self.get_body_argument('variations'))
        except ValueError:
            raise APIError('invalid_request',
                           hint='Variations argument is not valid JSON.')

        # Peek to determine if the user wants the variations applied globally
        # or locally.
        if self.get_body_argument('local', False):

            # Variations must be defined for each uid
            uids = set(self.get_body_arguments('uids'))
            variation_keys = set(list(raw_variations.keys()))

            if uids != variation_keys:
                raise APIError('invalid_request',
                               hint='Each uid must be assigned a variation.')

            variations = {
                a.uid: self.validate_variations(a.type, raw_variations[a.uid])
                for a in assets
            }

        else:
            # Global application

            # Ensure all assets are of the same type
            asset_types = set([a.type for a in assets])
            if len(asset_types) > 1:
                raise APIError('invalid_request',
                               hint='All assets must be of the same type.')

            local_variations = self.validate_variations(
                asset_types.pop(), raw_variations)
            variations = {a.uid: local_variations for a in assets}

        # Add a set of tasks to generate the asset variations
        notification_url = self.get_body_argument('notification_url', None)

        tasks = []
        task_names = []

        for asset in assets:

            local_variations = variations[asset.uid]
            for variation_name, transforms in local_variations.items():

                task = GenerateVariationTask(self.account._id, asset._id,
                                             variation_name, transforms,
                                             notification_url)

                if notification_url:
                    tasks.append(self.add_task_and_forget(task))
                else:
                    tasks.append(self.add_task_and_wait(task))

                task_names.append(f'{asset.uid}:{variation_name}')

        if notification_url:

            # Fire and forget
            await asyncio.gather(*tasks)
            self.finish()

        else:

            # Wait for response
            events = await asyncio.gather(*tasks)

            # Collect any errors
            errors = {}
            for i, event in enumerate(events):
                if not event:
                    errors[task_names[i]] = ['Connection lost']

                elif event.type == 'task_error':
                    errors[task_names[i]] = [event.reason]

            if errors:
                raise APIError('error', arg_errors=errors)

            # Fetch the asset again now the variations have been generated
            with Asset.with_options(read_preference=ReadPreference.PRIMARY):
                assets = self.get_assets(
                    projection={
                        'uid': True,
                        'expires': True,
                        'ext': True,
                        'meta': True,
                        'name': True,
                        'variations': {
                            '$sub.': Variation
                        }
                    })

            results = [a.to_json_type() for a in assets]

            self.write({
                'results': [{
                    'uid': r['uid'],
                    'variations': r['variations']
                } for r in results]
            })
Exemplo n.º 3
0
    async def post(self):
        """Analyze one for more asset for additional meta data"""

        assets = self.get_assets(
            projection={
                '_id': True,
                'type': True,
                'expires': True,
                'uid': True
            }
        )

        # Extract the analyzers from the request body
        try:
            raw_analyzers = json.loads(self.get_body_argument('analyzers'))
        except:
            raise APIError(
                'invalid_request',
                hint='Analyzers argument is not valid JSON.'
            )

        # Peek to determine if the user wants the variations applied globally
        # or locally.
        if self.get_body_argument('local', False):

            # Variations must be defined for each uid
            uids = set(self.get_body_arguments('uids'))
            analyzer_keys = set(list(raw_analyzers.keys()))

            if uids != analyzer_keys:
                raise APIError(
                    'invalid_request',
                    hint='Each uid must be assigned a list of analyzers.'
                )

            analyzers = {
                a.uid: self.validate_analyzers(a.type, raw_analyzers[a.uid])
                for a in assets
            }

        else:
            # Global application

            # Ensure all assets are the same type / base type (file)
            asset_types = set([a.type for a in assets if a.type != 'file'])
            if len(asset_types) > 1:
                raise APIError(
                    'invalid_request',
                    hint=(
                        'All assets must be of the same type / base type '
                        '(file)'
                    )
                )

            local_analyzers = self.validate_analyzers(
                asset_types.pop(),
                raw_analyzers
            )
            analyzers = {a.uid: local_analyzers for a in assets}

        # Add a set of tasks to generate the asset variations
        notification_url = self.get_body_argument('notification_url', None)

        tasks = []
        task_names = []

        for asset in assets:

            task = AnalyzeTask(
                self.account._id,
                asset._id,
                analyzers[asset.uid],
                notification_url
            )

            if notification_url:
                tasks.append(self.add_task_and_forget(task))
            else:
                tasks.append(self.add_task_and_wait(task))

            task_names.append(asset.uid)

        if notification_url:

            # Fire and forget
            await self.add_task_and_forget(task)
            self.finish()

        else:

            # Wait for response
            events = await asyncio.gather(*tasks)

            # Collect any errors
            errors = {}
            for i, event in enumerate(events):
                if not event:
                    errors[task_names[i]] = ['Connection lost']

                elif event.type == 'task_error':
                    errors[task_names[i]] = [event.reason]

            if errors:
                raise APIError('error', arg_errors=errors)

            # Fetch the assets again now the analysis is complete
            with Asset.with_options(read_preference=ReadPreference.PRIMARY):
                assets = self.get_assets(
                    projection={
                        'uid': True,
                        'expires': True,
                        'ext': True,
                        'meta': True,
                        'name': True
                    }
                )

            # Handle image expiry
            if not asset:
                raise APIError(
                    'not_found',
                    hint='Asset expired whilst being analyzed'
                )

            results = [a.to_json_type() for a in assets]

            self.write({
                'results': [
                    {
                        'uid': r['uid'],
                        'meta': r['meta']
                    }
                    for r in results
                ]
            })
Exemplo n.º 4
0
    async def put(self, uid):
        """Generate variations for an asset"""

        asset = self.get_asset(uid,
                               projection={
                                   '_id': True,
                                   'type': True,
                                   'expires': True
                               })

        # Extract the variations from the variations argument
        try:
            raw_variations = json.loads(self.get_body_argument('variations'))
        except ValueError:
            raise APIError('invalid_request',
                           hint='Variations argument is not valid JSON.')

        variations = self.validate_variations(asset.type, raw_variations)

        # Add a set of tasks to generate the asset variations
        notification_url = self.get_body_argument('notification_url', None)

        tasks = []
        task_names = []
        for variation_name, transforms in variations.items():

            task = GenerateVariationTask(self.account._id, asset._id,
                                         variation_name, transforms,
                                         notification_url)

            if notification_url:
                tasks.append(self.add_task_and_forget(task))
            else:
                tasks.append(self.add_task_and_wait(task))

            task_names.append(variation_name)

        if notification_url:

            # Fire and forget
            await asyncio.gather(*tasks)
            self.finish()

        else:

            # Wait for response
            events = await asyncio.gather(*tasks)

            # Collect any errors
            errors = {}
            for i, event in enumerate(events):
                if not event:
                    errors[task_names[i]] = ['Connection lost']

                elif event.type == 'task_error':
                    errors[task_names[i]] = [event.reason]

            if errors:
                raise APIError('error', arg_errors=errors)

            # Fetch the asset again now the variations have been generated
            with Asset.with_options(read_preference=ReadPreference.PRIMARY):
                asset = self.get_asset(uid,
                                       projection={
                                           'uid': True,
                                           'expires': True,
                                           'ext': True,
                                           'meta': True,
                                           'name': True,
                                           'variations': {
                                               '$sub.': Variation
                                           }
                                       })

            # Handle image expiry
            if not asset:
                raise APIError(
                    'not_found',
                    hint=('Asset expired whilst variations where being '
                          'generated.'))

            json_type = asset.to_json_type()

            self.write({
                'uid': json_type['uid'],
                'variations': json_type['variations']
            })