Example #1
0
def parse_simple_token(token, manager, related_models, left=False, sibling_token=None):
    """
        Parse the simple token dict.
        :param token: a dict with 'tokenType'=='PROPERTY'|'NUMBER'|'STRING'
            and 'tokenValue'==a value of the corresponding type.
        :param manager: The django model manager
        :param related_models: Related models joined to the manager model
        :param left: Default False. If set then the token is an assignee and shouldn't be wrapped in
        an F() expression if it's a property
        :param sibling_token: the left side token if we are evaluating a right side token (left=False)
    """
    if token["tokenType"] == "PROPERTY":
        # Resolve the field path in case it's relative to a joined related_model
        field_path = resolve_field_path_via_geographies(
            "__".join(token["tokenValue"].split(".")), manager, related_models
        )
        # Wrap in an F() expression if field is a right-side argument (the thing being assigned)
        return field_path if left else F(field_path)
    elif token["tokenType"] == "NUMBER":
        return float(token["tokenValue"])
    elif token["tokenType"] in ["STRING", "null", "undefined"]:
        if token["tokenType"] in ["null", "undefined"]:
            # Accept the 'null' or 'undefined' tokenType to mean None
            value = None
        else:
            value = token["tokenValue"]

        if sibling_token and sibling_token.get("tokenType", None) == "PROPERTY":
            # If we are evaluating a right-side token, inspect the sibling_token (the left-side token)
            # to find out what type the property is. This only matters for Dates and Times
            # where we need to modify the resolved right-side value to be have a time zone
            # if one isn't specified

            # Resolve the possibly chained property
            field_path = resolve_field_path_via_geographies(
                "__".join(sibling_token["tokenValue"].split(".")), manager, related_models
            )
            field = resolve_field_of_path(manager, field_path)
            if not field:
                return

            parser_lookup = {DateTimeField: parse_datetime, DateField: parse_date, TimeField: parse_time}
            if isinstance(field, (DateTimeField, DateField, TimeField)):
                date_time = parser_lookup[field.__class__](value)
                if not date_time and isinstance(field, DateTimeField):
                    # Accept dates without times for datetimes
                    date_time = timezone.utc.localize(
                        datetime.combine(parser_lookup[DateField](value), datetime.min.time())
                    )
                if isinstance(field, (DateTimeField, TimeField)) and not date_time.tzinfo:
                    # Default the timezone to UTC
                    return date_time.replace(tzinfo=timezone.utc)
                return date_time
        return value

    # TODO handle booleans and other types
    return token["tokenType"]
Example #2
0
 def map_result_path(field_path):
     # Get the field and the optional related model
     field, related_model = resolve_field_of_path(self, field_path, True)
     field_class_path = full_module_path(field.__class__)
     # Return
     return [field_path,
             field_class_path if\
                 not return_related_models else\
                 (field_class_path, full_module_path(related_model) if related_model else None)]
Example #3
0
def parse_simple_token(token, manager, related_models, left=False, sibling_token=None):
    """
        Parse the simple token dict.
        :param token: a dict with 'tokenType'=='PROPERTY'|'NUMBER'|'STRING'
            and 'tokenValue'==a value of the corresponding type.
        :param manager: The django model manager
        :param related_models: Related models joined to the manager model
        :param left: Default False. If set then the token is an assignee and shouldn't be wrapped in
        an F() expression if it's a property
        :param sibling_token: the left side token if we are evaluating a right side token (left=False)
    """
    if token['tokenType'] == 'PROPERTY':
        # Resolve the field path in case it's relative to a joined related_model
        field_path = resolve_field_path_via_geographies('__'.join(token['tokenValue'].split('.')), manager, related_models)
        # Wrap in an F() expression if field is a right-side argument (the thing being assigned)
        return field_path if left else F(field_path)
    elif token['tokenType'] == 'NUMBER':
        return float(token['tokenValue'])
    elif token['tokenType'] in ['STRING', 'null', 'undefined']:
        if token['tokenType'] in ['null', 'undefined']:
            # Accept the 'null' or 'undefined' tokenType to mean None
            value = None
        else:
            value = token['tokenValue']

        if sibling_token and sibling_token.get('tokenType', None) == 'PROPERTY':
            # If we are evaluating a right-side token, inspect the sibling_token (the left-side token)
            # to find out what type the property is. This only matters for Dates and Times
            # where we need to modify the resolved right-side value to be have a time zone
            # if one isn't specified

            # Resolve the possibly chained property
            field_path = resolve_field_path_via_geographies('__'.join(sibling_token['tokenValue'].split('.')), manager, related_models)
            field = resolve_field_of_path(manager, field_path)
            if not field:
                return

            parser_lookup = {DateTimeField: parse_datetime, DateField: parse_date, TimeField: parse_time}
            if isinstance(field, (DateTimeField, DateField, TimeField)):
                date_time = parser_lookup[field.__class__](value)
                if not date_time and isinstance(field, DateTimeField):
                    # Accept dates without times for datetimes
                    date_time = timezone.utc.localize(datetime.combine(parser_lookup[DateField](value), datetime.min.time()))
                if isinstance(field, (DateTimeField, TimeField)) and not date_time.tzinfo:
                    # Default the timezone to UTC
                    return date_time.replace(tzinfo=timezone.utc)
                return date_time
        return value

    # TODO handle booleans and other types
    return token['tokenType']