Example #1
0
        def worksheet(self, uuid, fetch_items, get_permissions, interpreted):
            """
            Return information about a worksheet. Calls
            - get_worksheet_info: get basic info
            - resolve_interpreted_items: get more information about a worksheet.
            In the future, for large worksheets, might want to break this up so
            that we can render something basic.
            """
            worksheet_info = self.client.get_worksheet_info(uuid, fetch_items, get_permissions)

            if fetch_items:
                worksheet_info['raw'] = worksheet_util.get_worksheet_lines(worksheet_info)

            # Set permissions
            worksheet_info['edit_permission'] = (worksheet_info['permission'] == GROUP_OBJECT_PERMISSION_ALL)
            # Format permissions into strings
            worksheet_info['permission_str'] = permission_str(worksheet_info['permission'])
            for group_permission in worksheet_info['group_permissions']:
                group_permission['permission_str'] = permission_str(group_permission['permission'])

            # Go and fetch more information about the worksheet contents by
            # resolving the interpreted items.
            if interpreted:
                try:
                    interpreted_items = worksheet_util.interpret_items(
                                        worksheet_util.get_default_schemas(),
                                        worksheet_info['items'])
                except UsageError, e:
                    interpreted_items = {'items': []}
                    worksheet_info['error'] = str(e)

                worksheet_info['items'] = self.client.resolve_interpreted_items(interpreted_items['items'])
                # Currently, only certain fields are base64 encoded.
                for item in worksheet_info['items']:
                    if item['mode'] in ['html', 'contents']:
                        if item['interpreted'] is None:
                            item['interpreted'] = [formatting.contents_str(item['interpreted'])]
                        else:
                            item['interpreted'] = map(base64.b64decode, item['interpreted'])
                    elif item['mode'] == 'table':
                        for row_map in item['interpreted'][1]:
                            for k, v in row_map.iteritems():
                                if v is None:
                                     row_map[k] = formatting.contents_str(v)
                    elif 'bundle_info' in item:
                        infos = []
                        if isinstance(item['bundle_info'], list):
                            infos = item['bundle_info']
                        elif isinstance(item['bundle_info'], dict):
                            infos = [item['bundle_info']]
                        for bundle_info in infos:
                            try:
                                if isinstance(bundle_info, dict):
                                    worksheet_util.format_metadata(bundle_info.get('metadata'))
                            except Exception, e:
                                print e
                                import ipdb; ipdb.set_trace()
def get_worksheet_lines(worksheet_info):
    """
    Generator that returns pretty-printed lines of text for the given worksheet.
    """
    lines = []
    for item in worksheet_info['items']:
        (bundle_info, subworksheet_info, value_obj, item_type) = item[:4]

        if item_type == TYPE_MARKUP:
            lines.append(value_obj)
        elif item_type == TYPE_DIRECTIVE:
            if len(value_obj) > 0 and value_obj[0] == DIRECTIVE_CHAR:
                # A comment
                # TODO: figure out why this form is consider a comment...
                lines.append('//' + ' '.join(value_obj[1:]))
            else:
                # A normal directive
                value = formatting.tokens_to_string(value_obj)
                value = (
                    DIRECTIVE_CHAR
                    + ('' if len(value) == 0 or value.startswith(DIRECTIVE_CHAR) else ' ')
                    + value
                )
                lines.append(value)
        elif item_type == TYPE_BUNDLE:
            if 'metadata' not in bundle_info:
                # This happens when we add bundles by uuid and don't actually make sure they exist
                # lines.append('ERROR: non-existent bundle %s' % bundle_info['uuid'])
                description = formatting.contents_str(None)
            else:
                metadata = bundle_info['metadata']
                # raise Exception(metadata)
                description = bundle_info['bundle_type']
                description += ' ' + metadata['name']
                deps = interpret_genpath(bundle_info, 'dependencies')
                if deps:
                    description += ' -- ' + deps
                command = bundle_info.get('command')
                if command:
                    command = command.replace('\n', ' ')
                    description += ' : ' + command
            lines.append(bundle_line(description, bundle_info['uuid']))
        elif item_type == TYPE_WORKSHEET:
            lines.append(
                worksheet_line(
                    'worksheet ' + formatting.contents_str(subworksheet_info.get('name')),
                    subworksheet_info['uuid'],
                )
            )
        else:
            raise RuntimeError('Invalid worksheet item type: %s' % type)
    return lines
Example #3
0
def get_worksheet_lines(worksheet_info):
    """
    Generator that returns pretty-printed lines of text for the given worksheet.
    """
    lines = []
    for item in worksheet_info['items']:
        (bundle_info, subworksheet_info, value_obj, item_type) = item

        if item_type == TYPE_MARKUP:
            lines.append(value_obj)
        elif item_type == TYPE_DIRECTIVE:
            if len(value_obj) > 0 and value_obj[0] == DIRECTIVE_CHAR:
                # A comment directive
                lines.append('//' + ' '.join(value_obj[1:]))
            else:
                # A normal directive
                value = formatting.tokens_to_string(value_obj)
                value = (
                    DIRECTIVE_CHAR
                    + ('' if len(value) == 0 or value.startswith(DIRECTIVE_CHAR) else ' ')
                    + value
                )
                lines.append(value)
        elif item_type == TYPE_BUNDLE:
            if 'metadata' not in bundle_info:
                # This happens when we add bundles by uuid and don't actually make sure they exist
                # lines.append('ERROR: non-existent bundle %s' % bundle_info['uuid'])
                description = formatting.contents_str(None)
            else:
                metadata = bundle_info['metadata']
                # raise Exception(metadata)
                description = bundle_info['bundle_type']
                description += ' ' + metadata['name']
                deps = interpret_genpath(bundle_info, 'dependencies')
                if deps:
                    description += ' -- ' + deps
                command = bundle_info.get('command')
                if command:
                    description += ' : ' + command
            lines.append(bundle_line(description, bundle_info['uuid']))
        elif item_type == TYPE_WORKSHEET:
            lines.append(
                worksheet_line(
                    'worksheet ' + formatting.contents_str(subworksheet_info.get('name')),
                    subworksheet_info['uuid'],
                )
            )
        else:
            raise RuntimeError('Invalid worksheet item type: %s' % type)
    return lines
Example #4
0
def fetch_interpreted_worksheet(uuid):
    """
    Return information about a worksheet. Calls
    - get_worksheet_info: get basic info
    - resolve_interpreted_items: get more information about a worksheet.
    In the future, for large worksheets, might want to break this up so
    that we can render something basic.
    """
    bundle_uuids = request.query.getall('bundle_uuid')
    worksheet_info = get_worksheet_info(uuid, fetch_items=True, fetch_permissions=True)

    # Shim in additional data for the frontend
    worksheet_info['items'] = resolve_items_into_infos(worksheet_info['items'])
    if worksheet_info['owner_id'] is None:
        worksheet_info['owner_name'] = None
    else:
        owner = local.model.get_user(user_id=worksheet_info['owner_id'])
        worksheet_info['owner_name'] = owner.user_name

    # Fetch items.
    worksheet_info['raw'] = get_worksheet_lines(worksheet_info)

    # Replace searches with raw items.
    # This needs to be done before get_worksheet_lines because this replaces
    # user-written raw items.
    worksheet_info['items'] = expand_raw_items(worksheet_info['items'])

    # Set permissions
    worksheet_info['edit_permission'] = worksheet_info['permission'] == GROUP_OBJECT_PERMISSION_ALL
    # Check enable chat box
    worksheet_info['enable_chat'] = local.config.get('enable_chat', False)
    # Format permissions into strings
    worksheet_info['permission_spec'] = permission_str(worksheet_info['permission'])
    for group_permission in worksheet_info['group_permissions']:
        group_permission['permission_spec'] = permission_str(group_permission['permission'])

    # Go and fetch more information about the worksheet contents by
    # resolving the interpreted items.
    try:
        interpreted_blocks = interpret_items(get_default_schemas(), worksheet_info['items'])
    except UsageError as e:
        interpreted_blocks = {'blocks': []}
        worksheet_info['error'] = str(e)

    # bundle_uuids is an optional argument that, if exists, contain the uuids of all the unfinished run bundles that need updating
    # In this case, full_worksheet will return a list of item parallel to ws.info.items that contain only items that need updating.
    # More specifically, all blocks that don't contain run bundles that need updating are None.
    # Also, a non-None block could contain a list of bundle_infos, which represent a list of bundles. Usually not all of them need updating.
    # The bundle_infos for bundles that don't need updating are also None.
    if bundle_uuids:
        for i, block in enumerate(interpreted_blocks['blocks']):
            if 'bundle_info' not in block:
                interpreted_blocks['blocks'][i] = None
            else:
                if isinstance(block['bundle_info'], dict):
                    block['bundle_info'] = [block['bundle_info']]
                is_relevant_block = False
                for j, bundle in enumerate(block['bundle_info']):
                    if bundle['uuid'] in bundle_uuids:
                        is_relevant_block = True
                    else:
                        block['bundle_info'][j] = None
                if not is_relevant_block:
                    interpreted_blocks['blocks'][i] = None

    worksheet_info['items'] = resolve_interpreted_blocks(interpreted_blocks['blocks'])
    worksheet_info['raw_to_block'] = interpreted_blocks['raw_to_block']
    worksheet_info['block_to_raw'] = interpreted_blocks['block_to_raw']

    for item in worksheet_info['items']:
        if item is None:
            continue
        if item['mode'] == 'table':
            for row_map in item['rows']:
                for k, v in row_map.iteritems():
                    if v is None:
                        row_map[k] = formatting.contents_str(v)
        if 'bundle_info' in item:
            infos = []
            if isinstance(item['bundle_info'], list):
                infos = item['bundle_info']
            elif isinstance(item['bundle_info'], dict):
                infos = [item['bundle_info']]
            for bundle_info in infos:
                if bundle_info is None:
                    continue
                if 'bundle_type' not in bundle_info:
                    continue  # empty info: invalid bundle reference
                if isinstance(bundle_info, dict):
                    format_metadata(bundle_info.get('metadata'))
    if bundle_uuids:
        return {'items': worksheet_info['items']}
    return worksheet_info
Example #5
0
        def worksheet(self, uuid, fetch_items, get_permissions, interpreted):
            """
            Return information about a worksheet. Calls
            - get_worksheet_info: get basic info
            - resolve_interpreted_items: get more information about a worksheet.
            In the future, for large worksheets, might want to break this up so
            that we can render something basic.
            """
            worksheet_info = self.client.get_worksheet_info(
                uuid, fetch_items, get_permissions)

            if fetch_items:
                worksheet_info['raw'] = worksheet_util.get_worksheet_lines(
                    worksheet_info)

            # Set permissions
            worksheet_info['edit_permission'] = (
                worksheet_info['permission'] == GROUP_OBJECT_PERMISSION_ALL)
            # Format permissions into strings
            worksheet_info['permission_str'] = permission_str(
                worksheet_info['permission'])
            for group_permission in worksheet_info['group_permissions']:
                group_permission['permission_str'] = permission_str(
                    group_permission['permission'])

            # Go and fetch more information about the worksheet contents by
            # resolving the interpreted items.
            if interpreted:
                try:
                    interpreted_items = worksheet_util.interpret_items(
                        worksheet_util.get_default_schemas(),
                        worksheet_info['items'])
                except UsageError, e:
                    interpreted_items = {'items': []}
                    worksheet_info['error'] = str(e)

                worksheet_info[
                    'items'] = self.client.resolve_interpreted_items(
                        interpreted_items['items'])
                # Currently, only certain fields are base64 encoded.
                for item in worksheet_info['items']:
                    if item['mode'] in ['html', 'contents']:
                        if item['interpreted'] is None:
                            item['interpreted'] = [
                                formatting.contents_str(item['interpreted'])
                            ]
                        else:
                            item['interpreted'] = map(base64.b64decode,
                                                      item['interpreted'])
                    elif item['mode'] == 'table':
                        for row_map in item['interpreted'][1]:
                            for k, v in row_map.iteritems():
                                if v is None:
                                    row_map[k] = formatting.contents_str(v)
                    elif 'bundle_info' in item:
                        infos = []
                        if isinstance(item['bundle_info'], list):
                            infos = item['bundle_info']
                        elif isinstance(item['bundle_info'], dict):
                            infos = [item['bundle_info']]
                        for bundle_info in infos:
                            try:
                                if isinstance(bundle_info, dict):
                                    worksheet_util.format_metadata(
                                        bundle_info.get('metadata'))
                            except Exception, e:
                                print e
                                import ipdb
                                ipdb.set_trace()
Example #6
0
 def decode_lines(interpreted):
     # interpreted is None or list of base64 encoded lines
     if interpreted is None:
         return formatting.contents_str(None)
     else:
         return map(base64.b64decode, interpreted)
Example #7
0
    worksheet_info['items'] = resolve_interpreted_items(
        interpreted_items['items'])
    worksheet_info['raw_to_interpreted'] = interpreted_items[
        'raw_to_interpreted']
    worksheet_info['interpreted_to_raw'] = interpreted_items[
        'interpreted_to_raw']

    for item in worksheet_info['items']:
        if item is None:
            continue
        if item['mode'] == 'table':
            for row_map in item['interpreted'][1]:
                for k, v in row_map.iteritems():
                    if v is None:
                        row_map[k] = formatting.contents_str(v)
        if 'bundle_info' in item:
            infos = []
            if isinstance(item['bundle_info'], list):
                infos = item['bundle_info']
            elif isinstance(item['bundle_info'], dict):
                infos = [item['bundle_info']]
            for bundle_info in infos:
                if bundle_info is None:
                    continue
                if 'bundle_type' not in bundle_info:
                    continue  # empty info: invalid bundle reference
                if isinstance(bundle_info, dict):
                    format_metadata(bundle_info.get('metadata'))
    if bundle_uuids:
        return {'items': worksheet_info['items']}
Example #8
0
def fetch_interpreted_worksheet(uuid):
    """
    Return information about a worksheet. Calls
    - get_worksheet_info: get basic info
    - resolve_interpreted_items: get more information about a worksheet.
    In the future, for large worksheets, might want to break this up so
    that we can render something basic.
    Return:
        worksheet_info dict{}:
            key:[value_type] <description>
            blocks:[list]
                    Resolved worksheet blocks from raw_items.
                        Bundles will be grouped into table block items,
                        text items might be grouped into one markdown block etc.
            source:[list] source lines
            raw_to_block:[list]
                            Raw_items to its block index pair.
                                For example, assume the first resolved block item is a bundle table that has 2 rows,
                                then the 2nd element in the list would be [0, 1]
                                [0, 1]: 0 means the item belongs to the first block,
                                        1 means the item is the second item of the block (2nd bundle in our example)
                                NOTE: Used for setting focus on frontend
            block_to_raw:[dict]
                            Maps the blocks (table, markdown, records) to their corresponding source line indices,
                            it's mostly a reverse mapping of raw_to_block, by mostly: raw_to_block has some bug,
                            please refer to worksheet_utils flush_bundles function.
                            This can be used to index the source on the frontend
                            Example:
                            [0, 0]: 0
                            [0, 1]: 1
                            [1, 0]: 9
                            This means the first blocks' first item corresponds to the first line in source,
                            the second item corresponds to the second line in source
                            The second block corresponds the 10th line in source.
                            2-8 can be skipped for multiple reasons: blank lines, comments, schema lines etc.
                                NOTE: Used for setting focus on frontend
    This endpoint can be called with &brief=1 in order to give an abbreviated version,
    which does not resolve searches or wsearches.
    To return an interpreted worksheet that only resolves a particular search/wsearch,
    pass in the search query to the "directive" argument. The value for this argument
    must be a search/wsearch query -- for example, &directive=search 0x .limit=100
    """
    bundle_uuids = request.query.getall('bundle_uuid')
    brief = request.query.get("brief", "0") == "1"

    directive = request.query.get("directive", None)
    search_results = []

    worksheet_info = get_worksheet_info(uuid,
                                        fetch_items=True,
                                        fetch_permissions=True)

    # Shim in additional data for the frontend
    worksheet_info['items'] = resolve_items_into_infos(worksheet_info['items'])

    if worksheet_info['owner_id'] is None:
        worksheet_info['owner_name'] = None
    else:
        owner = local.model.get_user(user_id=worksheet_info['owner_id'])
        worksheet_info['owner_name'] = owner.user_name

    # Fetch items.
    worksheet_info['source'] = get_worksheet_lines(worksheet_info)

    if not directive and not brief:
        expanded_items = []
        for index, raw_item in enumerate(worksheet_info['items']):
            expanded = expand_search_item(raw_item)
            expanded_items.append(expanded)
            # Multiple items can correspond to the same source line (i.e: search directives)
            # raw_items_to_source_index.extend([index] * len(expanded))
        worksheet_info['items'] = list(chain.from_iterable(expanded_items))
    elif directive:
        # Only expand the search item corresponding to the given directive.
        # Used in async loading to only load a single table.
        items_to_show = []
        for i, item in enumerate(worksheet_info['items']):
            (bundle_info, subworksheet_info, value_obj, item_type, id,
             sort_key) = item
            if directive == formatting.tokens_to_string(value_obj):
                search_results = perform_search_query(value_obj)
                items_to_show.append(item)
                break
            elif item_type == TYPE_DIRECTIVE:
                # We need to include previous directives
                # so that the final search result can be properly
                # rendered (it may depend on a schema defined earlier
                # in the worksheet).
                items_to_show.append(item)
        # Make sure the search item is at the end of worksheet_info['items'],
        # so we can isolate it later after interpret_items is called.
        worksheet_info['items'] = items_to_show
        worksheet_info['items'].extend(search_results)

    # Set permissions
    worksheet_info['edit_permission'] = worksheet_info[
        'permission'] == GROUP_OBJECT_PERMISSION_ALL
    # Check enable chat box
    worksheet_info['enable_chat'] = local.config.get('enable_chat', False)
    # Format permissions into strings
    worksheet_info['permission_spec'] = permission_str(
        worksheet_info['permission'])
    for group_permission in worksheet_info['group_permissions']:
        group_permission['permission_spec'] = permission_str(
            group_permission['permission'])

    # Go and fetch more information about the worksheet contents by
    # resolving the interpreted items.
    try:
        interpreted_blocks = interpret_items(get_default_schemas(),
                                             worksheet_info['items'],
                                             db_model=local.model)
    except UsageError as e:
        interpreted_blocks = {'blocks': []}
        worksheet_info['error'] = str(e)

    # bundle_uuids is an optional argument that, if exists, contain the uuids of all the unfinished run bundles that need updating
    # In this case, full_worksheet will return a list of item parallel to ws.info.items that contain only items that need updating.
    # More specifically, all blocks that don't contain run bundles that need updating are None.
    # Also, a non-None block could contain a list of bundle_infos, which represent a list of bundles. Usually not all of them need updating.
    # The bundle_infos for bundles that don't need updating are also None.
    if bundle_uuids:
        for i, block in enumerate(interpreted_blocks['blocks']):
            if 'bundle_info' not in block:
                interpreted_blocks['blocks'][i] = None
            else:
                if isinstance(block['bundle_info'], dict):
                    block['bundle_info'] = [block['bundle_info']]
                is_relevant_block = False
                for j, bundle in enumerate(block['bundle_info']):
                    if bundle['uuid'] in bundle_uuids:
                        is_relevant_block = True
                    else:
                        block['bundle_info'][j] = None
                if not is_relevant_block:
                    interpreted_blocks['blocks'][i] = None
    # Grouped individual items into blocks
    worksheet_info['blocks'] = resolve_interpreted_blocks(
        interpreted_blocks['blocks'], brief=brief)
    worksheet_info['raw_to_block'] = interpreted_blocks['raw_to_block']
    worksheet_info['block_to_raw'] = interpreted_blocks['block_to_raw']

    if directive:
        # If we're only async loading a single table_block / subworksheets_block,
        # return only that block (which is at the end of worksheet_info['items'])
        worksheet_info['blocks'] = [worksheet_info['blocks'][-1]
                                    ] if len(search_results) else []

    for block in worksheet_info['blocks']:
        if block is None:
            continue
        if block['mode'] == 'table':
            for row_map in block['rows']:
                for k, v in row_map.items():
                    if v is None:
                        row_map[k] = formatting.contents_str(v)
        if 'bundle_info' in block:
            infos = []
            if isinstance(block['bundle_info'], list):
                infos = block['bundle_info']
            elif isinstance(block['bundle_info'], dict):
                infos = [block['bundle_info']]
            for bundle_info in infos:
                if bundle_info is None:
                    continue
                if 'bundle_type' not in bundle_info:
                    continue  # empty info: invalid bundle reference
                if isinstance(bundle_info, dict):
                    format_metadata(bundle_info.get('metadata'))
    # Frontend doesn't use individual 'items' for now
    del worksheet_info['items']
    if bundle_uuids:
        return {'blocks': worksheet_info['blocks']}
    return worksheet_info
Example #9
0
class BundleService(object):
    """
    Methods for legacy frontend API.
    """

    @staticmethod
    def _rest_url():
        return 'http://{rest_host}:{rest_port}'.format(**local.config['server'])

    @staticmethod
    def get_bundle_info(uuid):
        bundle_info = get_bundle_info(uuid, True, True, True)

        if bundle_info is None:
            return None
        # Set permissions
        bundle_info['edit_permission'] = (bundle_info['permission'] == GROUP_OBJECT_PERMISSION_ALL)
        # Format permissions into strings
        bundle_info['permission_str'] = permission_str(bundle_info['permission'])
        for group_permission in bundle_info['group_permissions']:
            group_permission['permission_str'] = permission_str(group_permission['permission'])

        metadata = bundle_info['metadata']

        cls = get_bundle_subclass(bundle_info['bundle_type'])
        for key, value in worksheet_util.get_formatted_metadata(cls, metadata):
            metadata[key] = value

        bundle_info['metadata'] = metadata
        bundle_info['editable_metadata_fields'] = worksheet_util.get_editable_metadata_fields(cls)

        return bundle_info

    @staticmethod
    def get_bundle_infos(uuids, get_children=False, get_host_worksheets=False, get_permissions=False):
        """
        get_children, get_host_worksheets, get_permissions: whether we want to return more detailed information.
        Return map from bundle uuid to info.
        """
        return get_bundle_infos(
            uuids,
            get_children=get_children,
            get_host_worksheets=get_host_worksheets,
            get_permissions=get_permissions)

    # Used by RPC
    def interpret_genpath_table_contents(self, contents):
        return worksheet_util.interpret_genpath_table_contents(self, contents)

    # Used by RPC
    def interpret_search(self, worksheet_uuid, data):
        return worksheet_util.interpret_search(self, worksheet_uuid, data)

    # Used by RPC
    def interpret_wsearch(self, data):
        return worksheet_util.interpret_wsearch(self, data)

    @staticmethod
    def search_worksheets(keywords, worksheet_uuid=None):
        keywords = resolve_owner_in_keywords(keywords)
        results = local.model.search_worksheets(request.user.user_id, keywords)
        BundleService._set_owner_names(results)
        return results

    @staticmethod
    def _set_owner_names(results):
        """
        Helper function: Set owner_name given owner_id of each item in results.
        """
        owners = [local.model.get_user(r['owner_id']) for r in results]
        for r, o in zip(results, owners):
            r['owner_name'] = o.user_name

    def full_worksheet(self, uuid, bundle_uuids=None):
        """
        Return information about a worksheet. Calls
        - get_worksheet_info: get basic info
        - resolve_interpreted_items: get more information about a worksheet.
        In the future, for large worksheets, might want to break this up so
        that we can render something basic.
        """
        worksheet_info = get_worksheet_info(uuid, fetch_items=True, fetch_permission=True, legacy=True)

        # Fetch items.
        worksheet_info['raw'] = worksheet_util.get_worksheet_lines(worksheet_info)

        # Set permissions
        worksheet_info['edit_permission'] = (worksheet_info['permission'] == GROUP_OBJECT_PERMISSION_ALL)
        # Check enable chat box
        worksheet_info['enable_chat'] = local.config.get('enable_chat', False)
        # Format permissions into strings
        worksheet_info['permission_str'] = permission_str(worksheet_info['permission'])
        for group_permission in worksheet_info['group_permissions']:
            group_permission['permission_str'] = permission_str(group_permission['permission'])

        # Go and fetch more information about the worksheet contents by
        # resolving the interpreted items.
        try:
            interpreted_items = worksheet_util.interpret_items(
                                worksheet_util.get_default_schemas(),
                                worksheet_info['items'])
        except UsageError, e:
            interpreted_items = {'items': []}
            worksheet_info['error'] = str(e)

        # bundle_uuids is an optional argument that, if exists, contain the uuids of all the unfinished run bundles that need updating
        # In this case, full_worksheet will return a list of item parallel to ws.info.items that contain only items that need updating.
        # More specifically, all items that don't contain run bundles that need updating are None.
        # Also, a non-None item could contain a list of bundle_infos, which represent a list of bundles. Usually not all of them need updating.
        # The bundle_infos for bundles that don't need updating are also None.
        if bundle_uuids:
            for i, item in enumerate(interpreted_items['items']):
                if 'bundle_info' not in item:
                    interpreted_items['items'][i] = None
                else:
                    if isinstance(item['bundle_info'], dict):
                        item['bundle_info'] = [item['bundle_info']]
                    is_relevant_item = False
                    for j, bundle in enumerate(item['bundle_info']):
                        if bundle['uuid'] in bundle_uuids:
                            is_relevant_item = True
                        else:
                            item['bundle_info'][j] = None
                    if not is_relevant_item:
                        interpreted_items['items'][i] = None

        worksheet_info['items'] = self.resolve_interpreted_items(interpreted_items['items'])
        worksheet_info['raw_to_interpreted'] = interpreted_items['raw_to_interpreted']
        worksheet_info['interpreted_to_raw'] = interpreted_items['interpreted_to_raw']

        def decode_lines(interpreted):
            # interpreted is None or list of base64 encoded lines
            if interpreted is None:
                return formatting.contents_str(None)
            else:
                return map(base64.b64decode, interpreted)

        # Currently, only certain fields are base64 encoded.
        for item in worksheet_info['items']:
            if item is None:
                continue
            if item['mode'] in ['html', 'contents']:
                item['interpreted'] = decode_lines(item['interpreted'])
            elif item['mode'] == 'table':
                for row_map in item['interpreted'][1]:
                    for k, v in row_map.iteritems():
                        if v is None:
                            row_map[k] = formatting.contents_str(v)
            if 'bundle_info' in item:
                infos = []
                if isinstance(item['bundle_info'], list):
                    infos = item['bundle_info']
                elif isinstance(item['bundle_info'], dict):
                    infos = [item['bundle_info']]
                for bundle_info in infos:
                    if bundle_info is None:
                        continue
                    if 'bundle_type' not in bundle_info:
                        continue  # empty info: invalid bundle reference
                    if bundle_info['bundle_type'] != PrivateBundle.BUNDLE_TYPE:
                        target_info = self.get_top_level_contents((bundle_info['uuid'], ''))
                        bundle_info['target_info'] = target_info
                    if isinstance(bundle_info, dict):
                        worksheet_util.format_metadata(bundle_info.get('metadata'))
        if bundle_uuids:
            return {'items': worksheet_info['items']}
        return worksheet_info
Example #10
0
 def decode_lines(interpreted):
     # interpreted is None or list of base64 encoded lines
     if interpreted is None:
         return formatting.contents_str(None)
     else:
         return map(base64.b64decode, interpreted)
Example #11
0
def fetch_interpreted_worksheet(uuid):
    """
    Return information about a worksheet. Calls
    - get_worksheet_info: get basic info
    - resolve_interpreted_items: get more information about a worksheet.
    In the future, for large worksheets, might want to break this up so
    that we can render something basic.
    """
    bundle_uuids = request.query.getall('bundle_uuid')
    worksheet_info = get_worksheet_info(uuid, fetch_items=True, fetch_permissions=True)

    # Shim in additional data for the frontend
    worksheet_info['items'] = resolve_items_into_infos(worksheet_info['items'])
    if worksheet_info['owner_id'] is None:
        worksheet_info['owner_name'] = None
    else:
        owner = local.model.get_user(user_id=worksheet_info['owner_id'])
        worksheet_info['owner_name'] = owner.user_name

    # Fetch items.
    worksheet_info['raw'] = get_worksheet_lines(worksheet_info)

    # Replace searches with raw items.
    # This needs to be done before get_worksheet_lines because this replaces
    # user-written raw items.
    worksheet_info['items'] = expand_raw_items(worksheet_info['items'])

    # Set permissions
    worksheet_info['edit_permission'] = worksheet_info['permission'] == GROUP_OBJECT_PERMISSION_ALL
    # Check enable chat box
    worksheet_info['enable_chat'] = local.config.get('enable_chat', False)
    # Format permissions into strings
    worksheet_info['permission_spec'] = permission_str(worksheet_info['permission'])
    for group_permission in worksheet_info['group_permissions']:
        group_permission['permission_spec'] = permission_str(group_permission['permission'])

    # Go and fetch more information about the worksheet contents by
    # resolving the interpreted items.
    try:
        interpreted_blocks = interpret_items(
            get_default_schemas(), worksheet_info['items'], db_model=local.model
        )
    except UsageError as e:
        interpreted_blocks = {'blocks': []}
        worksheet_info['error'] = str(e)

    # bundle_uuids is an optional argument that, if exists, contain the uuids of all the unfinished run bundles that need updating
    # In this case, full_worksheet will return a list of item parallel to ws.info.items that contain only items that need updating.
    # More specifically, all blocks that don't contain run bundles that need updating are None.
    # Also, a non-None block could contain a list of bundle_infos, which represent a list of bundles. Usually not all of them need updating.
    # The bundle_infos for bundles that don't need updating are also None.
    if bundle_uuids:
        for i, block in enumerate(interpreted_blocks['blocks']):
            if 'bundle_info' not in block:
                interpreted_blocks['blocks'][i] = None
            else:
                if isinstance(block['bundle_info'], dict):
                    block['bundle_info'] = [block['bundle_info']]
                is_relevant_block = False
                for j, bundle in enumerate(block['bundle_info']):
                    if bundle['uuid'] in bundle_uuids:
                        is_relevant_block = True
                    else:
                        block['bundle_info'][j] = None
                if not is_relevant_block:
                    interpreted_blocks['blocks'][i] = None

    worksheet_info['items'] = resolve_interpreted_blocks(interpreted_blocks['blocks'])
    worksheet_info['raw_to_block'] = interpreted_blocks['raw_to_block']
    worksheet_info['block_to_raw'] = interpreted_blocks['block_to_raw']

    for item in worksheet_info['items']:
        if item is None:
            continue
        if item['mode'] == 'table':
            for row_map in item['rows']:
                for k, v in row_map.items():
                    if v is None:
                        row_map[k] = formatting.contents_str(v)
        if 'bundle_info' in item:
            infos = []
            if isinstance(item['bundle_info'], list):
                infos = item['bundle_info']
            elif isinstance(item['bundle_info'], dict):
                infos = [item['bundle_info']]
            for bundle_info in infos:
                if bundle_info is None:
                    continue
                if 'bundle_type' not in bundle_info:
                    continue  # empty info: invalid bundle reference
                if isinstance(bundle_info, dict):
                    format_metadata(bundle_info.get('metadata'))
    if bundle_uuids:
        return {'items': worksheet_info['items']}
    return worksheet_info
Example #12
0
class BundleService(object):
    '''
    Adapts the LocalBundleClient for REST calls.
    '''
    def __init__(self):
        self.client = LocalBundleClient('local',
                                        local.bundle_store,
                                        local.model,
                                        local.upload_manager,
                                        local.download_manager,
                                        LocalUserAuthHandler(
                                            request.user, local.model),
                                        verbose=0)

    def get_bundle_info(self, uuid):
        bundle_info = self.client.get_bundle_info(uuid, True, True, True)

        if bundle_info is None:
            return None
        # Set permissions
        bundle_info['edit_permission'] = (
            bundle_info['permission'] == GROUP_OBJECT_PERMISSION_ALL)
        # Format permissions into strings
        bundle_info['permission_str'] = permission_str(
            bundle_info['permission'])
        for group_permission in bundle_info['group_permissions']:
            group_permission['permission_str'] = permission_str(
                group_permission['permission'])

        metadata = bundle_info['metadata']

        cls = get_bundle_subclass(bundle_info['bundle_type'])
        for key, value in worksheet_util.get_formatted_metadata(cls, metadata):
            metadata[key] = value

        bundle_info['metadata'] = metadata
        bundle_info[
            'editable_metadata_fields'] = worksheet_util.get_editable_metadata_fields(
                cls, metadata)

        return bundle_info

    def search_worksheets(self, keywords, worksheet_uuid=None):
        return self.client.search_worksheets(keywords)

    def get_worksheet_uuid(self, spec):
        # generic function sometimes get uuid already just return it.
        if spec_util.UUID_REGEX.match(spec):
            return spec
        else:
            return worksheet_util.get_worksheet_uuid(self.client, None, spec)

    def full_worksheet(self, uuid):
        """
        Return information about a worksheet. Calls
        - get_worksheet_info: get basic info
        - resolve_interpreted_items: get more information about a worksheet.
        In the future, for large worksheets, might want to break this up so
        that we can render something basic.
        """
        worksheet_info = self.client.get_worksheet_info(uuid, True, True)

        # Fetch items.
        worksheet_info['raw'] = worksheet_util.get_worksheet_lines(
            worksheet_info)

        # Set permissions
        worksheet_info['edit_permission'] = (
            worksheet_info['permission'] == GROUP_OBJECT_PERMISSION_ALL)
        # Check enable chat box
        worksheet_info['enable_chat'] = local.config.get('enable_chat', False)
        # Format permissions into strings
        worksheet_info['permission_str'] = permission_str(
            worksheet_info['permission'])
        for group_permission in worksheet_info['group_permissions']:
            group_permission['permission_str'] = permission_str(
                group_permission['permission'])

        # Go and fetch more information about the worksheet contents by
        # resolving the interpreted items.
        try:
            interpreted_items = worksheet_util.interpret_items(
                worksheet_util.get_default_schemas(), worksheet_info['items'])
        except UsageError, e:
            interpreted_items = {'items': []}
            worksheet_info['error'] = str(e)

        worksheet_info['items'] = self.client.resolve_interpreted_items(
            interpreted_items['items'])
        worksheet_info['raw_to_interpreted'] = interpreted_items[
            'raw_to_interpreted']
        worksheet_info['interpreted_to_raw'] = interpreted_items[
            'interpreted_to_raw']

        def decode_lines(interpreted):
            # interpreted is None or list of base64 encoded lines
            if interpreted is None:
                return formatting.contents_str(None)
            else:
                return map(base64.b64decode, interpreted)

        # Currently, only certain fields are base64 encoded.
        for item in worksheet_info['items']:
            if item['mode'] in ['html', 'contents']:
                item['interpreted'] = decode_lines(item['interpreted'])
            elif item['mode'] == 'table':
                for row_map in item['interpreted'][1]:
                    for k, v in row_map.iteritems():
                        if v is None:
                            row_map[k] = formatting.contents_str(v)
            if 'bundle_info' in item:
                infos = []
                if isinstance(item['bundle_info'], list):
                    infos = item['bundle_info']
                elif isinstance(item['bundle_info'], dict):
                    infos = [item['bundle_info']]
                for bundle_info in infos:
                    if bundle_info['bundle_type'] != PrivateBundle.BUNDLE_TYPE:
                        target_info = self.get_top_level_contents(
                            (bundle_info['uuid'], ''))
                        bundle_info['target_info'] = target_info
                    try:
                        if isinstance(bundle_info, dict):
                            worksheet_util.format_metadata(
                                bundle_info.get('metadata'))
                    except Exception, e:
                        print e
                        import ipdb
                        ipdb.set_trace()