Exemplo n.º 1
0
def parse_worksheet_form(form_result, client, worksheet_uuid):
    """
    Input: form_result is a list of lines.
    Return (list of (bundle_info, subworksheet_info, value, type) tuples, commands to execute)
    """

    def get_line_type(line):
        if line.startswith('!'):  # Run commands
            return 'command'
        elif line.startswith('//'):
            return 'comment'
        elif BUNDLE_REGEX.match(line) is not None:
            return TYPE_BUNDLE
        elif SUBWORKSHEET_REGEX.match(line) is not None:
            return TYPE_WORKSHEET
        elif DIRECTIVE_REGEX.match(line) is not None:
            return TYPE_DIRECTIVE
        else:
            return TYPE_MARKUP

    line_types = [get_line_type(line) for line in form_result]

    # Extract bundle specs and resolve uuids in one batch
    # bundle_specs = (line_indices, bundle_specs)
    bundle_lines = [
        (i, BUNDLE_REGEX.match(line).group(3))
        for i, line in enumerate(form_result)
        if line_types[i] == TYPE_BUNDLE
        ]
    bundle_specs = zip(*bundle_lines) if len(bundle_lines) > 0 else [(), ()]
    # bundle_uuids = {line_i: bundle_uuid, ...}
    bundle_uuids = dict(zip(bundle_specs[0], get_bundle_uuids(client, worksheet_uuid, bundle_specs[1])))

    commands = []
    items = []
    for line_i, (line_type, line) in enumerate(izip(line_types, form_result)):
        if line_type == 'command':
            command = formatting.string_to_tokens(line[1:].strip())
            # The user can specify '!<command> ^', which perform actions on the previous bundle.
            # Replace ^ with the reference to the last bundle.
            command = [(bundle_uuids[-1][1] if arg == '^' else arg) for arg in command]
            commands.append(command)
        elif line_type == 'comment':
            comment = line[2:]
            items.append(directive_item([DIRECTIVE_CHAR, comment]))
        elif line_type == TYPE_BUNDLE:
            bundle_info = {'uuid': bundle_uuids[line_i]}  # info doesn't need anything other than uuid
            items.append(bundle_item(bundle_info))
        elif line_type == TYPE_WORKSHEET:
            subworksheet_spec = SUBWORKSHEET_REGEX.match(line).group(3)
            try:
                subworksheet_uuid = get_worksheet_uuid(client, worksheet_uuid, subworksheet_spec)
                subworksheet_info = {'uuid': subworksheet_uuid}  # info doesn't need anything other than uuid
                items.append(subworksheet_item(subworksheet_info))
            except UsageError, e:
                items.append(markup_item(e.message + ': ' + line))
        elif line_type == TYPE_DIRECTIVE:
            directive = DIRECTIVE_REGEX.match(line).group(1)
            items.append(directive_item(formatting.string_to_tokens(directive)))
Exemplo n.º 2
0
def parse_worksheet_form(form_result, model, user, worksheet_uuid):
    """
    Input: form_result is a list of lines.
    Return (list of (bundle_info, subworksheet_info, value, type) tuples, commands to execute)
    """

    def get_line_type(line):
        if line.startswith('!'):  # Run commands
            return 'command'
        elif line.startswith('//'):
            return 'comment'
        elif BUNDLE_REGEX.match(line) is not None:
            return TYPE_BUNDLE
        elif SUBWORKSHEET_REGEX.match(line) is not None:
            return TYPE_WORKSHEET
        elif DIRECTIVE_REGEX.match(line) is not None:
            return TYPE_DIRECTIVE
        else:
            return TYPE_MARKUP

    line_types = [get_line_type(line) for line in form_result]

    # Extract bundle specs and resolve uuids in one batch
    bundle_lines = [
        (i, BUNDLE_REGEX.match(line).group(3))
        for i, line in enumerate(form_result)
        if line_types[i] == TYPE_BUNDLE
        ]
    # bundle_specs = (line_indices, bundle_specs)
    bundle_specs = zip(*bundle_lines) if len(bundle_lines) > 0 else [(), ()]
    # bundle_uuids = {line_i: bundle_uuid, ...}
    bundle_uuids = dict(zip(bundle_specs[0], canonicalize.get_bundle_uuids(model, user, worksheet_uuid, bundle_specs[1])))

    commands = []
    items = []
    for line_i, (line_type, line) in enumerate(izip(line_types, form_result)):
        if line_type == 'command':
            command = formatting.string_to_tokens(line[1:].strip())
            # The user can specify '!<command> ^', which perform actions on the previous bundle.
            # Replace ^ with the reference to the last bundle.
            command = [(bundle_uuids[-1][1] if arg == '^' else arg) for arg in command]
            commands.append(command)
        elif line_type == 'comment':
            comment = line[2:]
            items.append(directive_item([DIRECTIVE_CHAR, comment]))
        elif line_type == TYPE_BUNDLE:
            bundle_info = {'uuid': bundle_uuids[line_i]}  # info doesn't need anything other than uuid
            items.append(bundle_item(bundle_info))
        elif line_type == TYPE_WORKSHEET:
            subworksheet_spec = SUBWORKSHEET_REGEX.match(line).group(3)
            try:
                subworksheet_uuid = canonicalize.get_worksheet_uuid(model, user, worksheet_uuid, subworksheet_spec)
                subworksheet_info = {'uuid': subworksheet_uuid}  # info doesn't need anything other than uuid
                items.append(subworksheet_item(subworksheet_info))
            except UsageError, e:
                items.append(markup_item(e.message + ': ' + line))
        elif line_type == TYPE_DIRECTIVE:
            directive = DIRECTIVE_REGEX.match(line).group(1)
            items.append(directive_item(formatting.string_to_tokens(directive)))
Exemplo n.º 3
0
def convert_items_from_db(items):
    """
    Helper function.
    (bundle_uuid, subworksheet_uuid, value, type) -> (bundle_info, subworksheet_info, value_obj, type)
    """
    # Database only contains the uuid; need to expand to info.
    # We need to do to convert the bundle_uuids into bundle_info dicts.
    # However, we still make O(1) database calls because we use the
    # optimized batch_get_bundles multiget method.
    bundle_uuids = set(bundle_uuid for (bundle_uuid, subworksheet_uuid, value,
                                        type) in items
                       if bundle_uuid is not None)

    bundle_dict = get_bundle_infos(bundle_uuids)

    # Go through the items and substitute the components
    new_items = []
    for (bundle_uuid, subworksheet_uuid, value, type) in items:
        bundle_info = bundle_dict.get(
            bundle_uuid, {'uuid': bundle_uuid}) if bundle_uuid else None
        if subworksheet_uuid:
            try:
                subworksheet_info = local.model.get_worksheet(
                    subworksheet_uuid, fetch_items=False).to_dict(legacy=True)
            except UsageError, e:
                # If can't get the subworksheet, it's probably invalid, so just replace it with an error
                # type = worksheet_util.TYPE_MARKUP
                subworksheet_info = {'uuid': subworksheet_uuid}
                # value = 'ERROR: non-existent worksheet %s' % subworksheet_uuid
        else:
            subworksheet_info = None
        value_obj = formatting.string_to_tokens(
            value) if type == worksheet_util.TYPE_DIRECTIVE else value
        new_items.append((bundle_info, subworksheet_info, value_obj, type))
Exemplo n.º 4
0
def resolve_items_into_infos(items):
    """
    Helper function.
    {'bundle_uuid': '...', 'subworksheet_uuid': '...', 'value': '...', 'type': '...')
        -> (bundle_info, subworksheet_info, value_obj, type)
    """
    # Database only contains the uuid; need to expand to info.
    # We need to do to convert the bundle_uuids into bundle_info dicts.
    # However, we still make O(1) database calls because we use the
    # optimized batch_get_bundles multiget method.
    bundle_uuids = set(
        i['bundle_uuid'] for i in items
        if i['bundle_uuid'] is not None
    )

    bundle_dict = rest_util.get_bundle_infos(bundle_uuids)

    # Go through the items and substitute the components
    new_items = []
    for i in items:
        bundle_info = bundle_dict.get(i['bundle_uuid'], {'uuid': i['bundle_uuid']}) if i['bundle_uuid'] else None
        if i['subworksheet_uuid']:
            try:
                subworksheet_info = local.model.get_worksheet(i['subworksheet_uuid'], fetch_items=False).to_dict()
            except UsageError, e:
                # If can't get the subworksheet, it's probably invalid, so just replace it with an error
                # type = worksheet_util.TYPE_MARKUP
                subworksheet_info = {'uuid': i['subworksheet_uuid']}
                # value = 'ERROR: non-existent worksheet %s' % subworksheet_uuid
        else:
            subworksheet_info = None
        value_obj = formatting.string_to_tokens(i['value']) if i['type'] == TYPE_DIRECTIVE else i['value']
        new_items.append((bundle_info, subworksheet_info, value_obj, i['type']))
Exemplo n.º 5
0
def resolve_items_into_infos(items):
    """
    Helper function.
    {'bundle_uuid': '...', 'subworksheet_uuid': '...', 'value': '...', 'type': '...')
        -> (bundle_info, subworksheet_info, value_obj, type)
    """
    # Database only contains the uuid; need to expand to info.
    # We need to do to convert the bundle_uuids into bundle_info dicts.
    # However, we still make O(1) database calls because we use the
    # optimized batch_get_bundles multiget method.
    bundle_uuids = set(i['bundle_uuid'] for i in items if i['bundle_uuid'] is not None)

    bundle_dict = rest_util.get_bundle_infos(bundle_uuids)

    # Go through the items and substitute the components
    new_items = []
    for i in items:
        bundle_info = (
            bundle_dict.get(i['bundle_uuid'], {'uuid': i['bundle_uuid']})
            if i['bundle_uuid']
            else None
        )
        if i['subworksheet_uuid']:
            try:
                subworksheet_info = local.model.get_worksheet(
                    i['subworksheet_uuid'], fetch_items=False
                ).to_dict()
            except UsageError as e:
                # If can't get the subworksheet, it's probably invalid, so just replace it with an error
                # type = worksheet_util.TYPE_MARKUP
                subworksheet_info = {'uuid': i['subworksheet_uuid']}
                # value = 'ERROR: non-existent worksheet %s' % subworksheet_uuid
        else:
            subworksheet_info = None
        value_obj = (
            formatting.string_to_tokens(i['value']) if i['type'] == TYPE_DIRECTIVE else i['value']
        )
        new_items.append((bundle_info, subworksheet_info, value_obj, i['type']))
    return new_items
Exemplo n.º 6
0
def parse_worksheet_form(form_result, model, user, worksheet_uuid):
    """
    Input: form_result is a list of lines.
    Return (list of (bundle_info, subworksheet_info, value, type) tuples, commands to execute)
    """
    def get_line_type(line):
        if line.startswith('//'):
            return 'comment'
        elif BUNDLE_REGEX.match(line) is not None:
            return TYPE_BUNDLE
        elif SUBWORKSHEET_REGEX.match(line) is not None:
            return TYPE_WORKSHEET
        elif DIRECTIVE_REGEX.match(line) is not None:
            return TYPE_DIRECTIVE
        else:
            return TYPE_MARKUP

    line_types = [get_line_type(line) for line in form_result]

    # Extract bundle specs and resolve uuids in one batch
    bundle_lines = [(i, BUNDLE_REGEX.match(line).group(3))
                    for i, line in enumerate(form_result)
                    if line_types[i] == TYPE_BUNDLE]
    # bundle_specs = (line_indices, bundle_specs)
    bundle_specs = list(zip(*bundle_lines)) if len(bundle_lines) > 0 else [(),
                                                                           ()]
    # bundle_uuids = {line_i: bundle_uuid, ...}
    bundle_uuids = dict(
        list(
            zip(
                bundle_specs[0],
                canonicalize.get_bundle_uuids(model, user, worksheet_uuid,
                                              bundle_specs[1]),
            )))

    items = []
    for line_i, (line_type, line) in enumerate(zip(line_types, form_result)):
        if line_type == 'comment':
            comment = line[2:]
            items.append(directive_item([DIRECTIVE_CHAR, comment]))
        elif line_type == TYPE_BUNDLE:
            bundle_info = {
                'uuid': bundle_uuids[line_i]
            }  # info doesn't need anything other than uuid
            items.append(bundle_item(bundle_info))
        elif line_type == TYPE_WORKSHEET:
            subworksheet_spec = SUBWORKSHEET_REGEX.match(line).group(3)
            try:
                subworksheet_uuid = canonicalize.get_worksheet_uuid(
                    model, user, worksheet_uuid, subworksheet_spec)
                subworksheet_info = {
                    'uuid': subworksheet_uuid
                }  # info doesn't need anything other than uuid
                items.append(subworksheet_item(subworksheet_info))
            except UsageError as e:
                items.append(markup_item(str(e) + ': ' + line))
        elif line_type == TYPE_DIRECTIVE:
            directive = DIRECTIVE_REGEX.match(line).group(1)
            items.append(directive_item(
                formatting.string_to_tokens(directive)))
        elif line_type == TYPE_MARKUP:
            items.append(markup_item(line))
        else:
            raise RuntimeError(
                "Invalid line type %s: this should not happen." % line_type)

    return items
Exemplo n.º 7
0
def parse_worksheet_form(form_result, model, user, worksheet_uuid):
    """
    Input: form_result is a list of lines.
    Return (list of (bundle_info, subworksheet_info, value, type) tuples, commands to execute)
    """

    def get_line_type(line):
        if line.startswith('//'):
            return 'comment'
        elif BUNDLE_REGEX.match(line) is not None:
            return TYPE_BUNDLE
        elif SUBWORKSHEET_REGEX.match(line) is not None:
            return TYPE_WORKSHEET
        elif DIRECTIVE_REGEX.match(line) is not None:
            return TYPE_DIRECTIVE
        else:
            return TYPE_MARKUP

    line_types = [get_line_type(line) for line in form_result]

    # Extract bundle specs and resolve uuids in one batch
    bundle_lines = [
        (i, BUNDLE_REGEX.match(line).group(3))
        for i, line in enumerate(form_result)
        if line_types[i] == TYPE_BUNDLE
    ]
    # bundle_specs = (line_indices, bundle_specs)
    bundle_specs = zip(*bundle_lines) if len(bundle_lines) > 0 else [(), ()]
    # bundle_uuids = {line_i: bundle_uuid, ...}
    bundle_uuids = dict(
        zip(
            bundle_specs[0],
            canonicalize.get_bundle_uuids(model, user, worksheet_uuid, bundle_specs[1]),
        )
    )

    items = []
    for line_i, (line_type, line) in enumerate(izip(line_types, form_result)):
        if line_type == 'comment':
            comment = line[2:]
            items.append(directive_item([DIRECTIVE_CHAR, comment]))
        elif line_type == TYPE_BUNDLE:
            bundle_info = {
                'uuid': bundle_uuids[line_i]
            }  # info doesn't need anything other than uuid
            items.append(bundle_item(bundle_info))
        elif line_type == TYPE_WORKSHEET:
            subworksheet_spec = SUBWORKSHEET_REGEX.match(line).group(3)
            try:
                subworksheet_uuid = canonicalize.get_worksheet_uuid(
                    model, user, worksheet_uuid, subworksheet_spec
                )
                subworksheet_info = {
                    'uuid': subworksheet_uuid
                }  # info doesn't need anything other than uuid
                items.append(subworksheet_item(subworksheet_info))
            except UsageError as e:
                items.append(markup_item(e.message + ': ' + line))
        elif line_type == TYPE_DIRECTIVE:
            directive = DIRECTIVE_REGEX.match(line).group(1)
            items.append(directive_item(formatting.string_to_tokens(directive)))
        elif line_type == TYPE_MARKUP:
            items.append(markup_item(line))
        else:
            raise RuntimeError("Invalid line type %s: this should not happen." % line_type)

    return items