def items_differ(jsonitems, dbitems, subfield_dict):
    """ check whether or not jsonitems and dbitems differ """

    # short circuit common cases
    if len(jsonitems) == len(dbitems) == 0:
        # both are empty
        return False
    elif len(jsonitems) != len(dbitems):
        # if lengths differ, they're definitely different
        return True

    original_jsonitems = jsonitems
    jsonitems = copy.deepcopy(jsonitems)
    keys = jsonitems[0].keys()

    # go over dbitems looking for matches
    for dbitem in dbitems:
        order = getattr(dbitem, 'order', None)
        match = None
        for i, jsonitem in enumerate(jsonitems):
            # check if all keys (excluding subfields) match
            for k in keys:
                if k not in subfield_dict and getattr(dbitem, k) != jsonitem.get(k, None):
                    break
            else:
                # all fields match so far, possibly equal, just check subfields now
                for k in subfield_dict:
                    jsonsubitems = jsonitem[k]
                    dbsubitems = list(getattr(dbitem, k).all())
                    if items_differ(jsonsubitems, dbsubitems, subfield_dict[k][2]):
                        break
                else:
                    # if the dbitem sets 'order', then the order matters
                    if order is not None and int(order) != original_jsonitems.index(jsonitem):
                        break
                    # these items are equal, so let's mark it for removal
                    match = i
                    break

        if match is not None:
            # item exists in both, remove from jsonitems
            jsonitems.pop(match)
        else:
            # exists in db but not json
            return True

    # if we get here, jsonitems has to be empty because we asserted that the length was
    # the same and we found a match for each thing in dbitems, here's a safety check just in case
    if jsonitems:       # pragma: no cover
        return True

    return False
def items_differ ( jsonitems , dbitems , subfield_dict ) : if len ( jsonitems ) == len ( dbitems ) == 0 : return False elif len ( jsonitems ) != len ( dbitems ) : return True original_jsonitems = jsonitems jsonitems = copy . deepcopy ( jsonitems ) keys = jsonitems [ 0 ] . keys ( ) for dbitem in dbitems : order = getattr ( dbitem , 'order' , None ) match = None for i , jsonitem in enumerate ( jsonitems ) : for k in keys : if k not in subfield_dict and getattr ( dbitem , k ) != jsonitem . get ( k , None ) : break else : for k in subfield_dict : jsonsubitems = jsonitem [ k ] dbsubitems = list ( getattr ( dbitem , k ) . all ( ) ) if items_differ ( jsonsubitems , dbsubitems , subfield_dict [ k ] [ 2 ] ) : break else : if order is not None and int ( order ) != original_jsonitems . index ( jsonitem ) : break match = i break if match is not None : jsonitems . pop ( match ) else : return True if jsonitems : return True return False
check whether or not jsonitems and dbitems differ