Exemple #1
0
def construct_sequence_items(name, values):
    maybe_deep_name = name + '.'
    result_sequence = defaultdict(dict)
    for key, value in values.items():
        if not value:
            continue

        if key == name:
            key_first = ''
        elif key.startswith(maybe_deep_name):
            key_first = key.split(maybe_deep_name, 1)[1]
        else:
            continue

        value = maybe_list(value)
        if '.' in key_first:
            maybe_number, second_key = key_first.split('.', 1)
            maybe_number = maybe_integer(maybe_number)
            if maybe_number is not None:
                key = '%s.%s' % (name, second_key)
                result_sequence[maybe_number][key] = value[0]
                continue

        elif key_first:
            maybe_number = maybe_integer(key_first)
            if maybe_number is not None:
                result_sequence[maybe_number][name] = value[0]
                continue

        for i, key_value in enumerate(value):
            result_sequence[i][key] = key_value

    return [v for i, v in sorted(result_sequence.items())]
Exemple #2
0
def construct_sequence_items(name, values):
    maybe_deep_name = name + '.'
    result_sequence = MissingDict()
    for key, value in values.items():
        if not value:
            continue

        if key == name:
            key_first = ''
        elif key.startswith(maybe_deep_name):
            key_first = key.split(maybe_deep_name, 1)[1]
        else:
            continue

        value = maybe_list(value)
        if '.' in key_first:
            maybe_number, key_second = key_first.split('.', 1)
            maybe_number = maybe_integer(maybe_number)
            if maybe_number is not None:
                key = u'.'.join([name, key_second])
                result_sequence[maybe_number][key] = value[0]
                continue

        elif key_first:
            maybe_number = maybe_integer(key_first)
            if maybe_number is not None:
                result_sequence[maybe_number][name] = value[0]
                continue

        for i, key_value in enumerate(value):
            result_sequence[i][key] = key_value

    result_sequence = result_sequence.items()
    result_sequence.sort()
    return [v for i, v in result_sequence]
Exemple #3
0
def construct_sequence_items(name, values):
    maybe_deep_name = name + '.'
    result_sequence = MissingDict()
    for key, value in values.items():
        if not value:
            continue

        if key == name:
            key_first = ''
        elif key.startswith(maybe_deep_name):
            key_first = key.split(maybe_deep_name, 1)[1]
        else:
            continue

        value = maybe_list(value)
        if '.' in key_first:
            maybe_number, key_second = key_first.split('.', 1)
            maybe_number = maybe_integer(maybe_number)
            if maybe_number is not None:
                key = u'.'.join([name, key_second])
                result_sequence[maybe_number][key] = value[0]
                continue

        elif key_first:
            maybe_number = maybe_integer(key_first)
            if maybe_number is not None:
                result_sequence[maybe_number][name] = value[0]
                continue

        for i, key_value in enumerate(value):
            result_sequence[i][key] = key_value

    result_sequence = result_sequence.items()
    result_sequence.sort()
    return [v for i, v in result_sequence]
Exemple #4
0
    def clean_junk_locks(self):
        for path, dirnames, filenames in walk_on_path(self.path):
            filenames = filenames or []
            for dirname in dirnames:
                folder_path = join_paths(path, dirname)
                for filename in get_dir_filenames(folder_path):
                    if not filename.startswith('.'):
                        filenames.append(join_paths(dirname, filename))

            for filename in filenames:
                filename = to_string(filename)
                if filename.startswith('.'):
                    continue

                file_path = join_paths(path, filename)
                if '.' in filename:
                    # Delete inactive positions locks
                    binary = get_file_binary(file_path, mode='r')
                    if binary:
                        info = binary.split()
                        if len(info) >= 2 and info[0] == DOMAIN_NAME and maybe_integer(info[1]):
                            try:
                                getpgid(int(info[1]))
                            except OSError as error:
                                if error.errno is errno.ESRCH:
                                    remove_file_quietly(
                                        file_path,
                                        retries=self.retries,
                                        retry_errno=self.retry_errno)

                else:
                    # Clean locks wait list
                    # Get last modified time, to check if file as been updated in the process
                    modified_time = file_modified_time(file_path)
                    if modified_time:
                        binary = get_file_binary(file_path, mode='r')
                        if binary:
                            # Find alive locks
                            keep_codes = binary.splitlines()
                            for i, line in enumerate(keep_codes):
                                info = line.split()
                                if len(info) >= 2 and info[0] == DOMAIN_NAME and maybe_integer(info[1]):
                                    try:
                                        getpgid(int(info[1]))
                                    except OSError as error:
                                        if error.errno is errno.ESRCH:
                                            # Add empty line to keep position number
                                            keep_codes[i] = ''

                            # Check if file as been updated in the process
                            last_modified_time = file_modified_time(file_path)
                            if last_modified_time and modified_time == last_modified_time:
                                if not any(keep_codes):
                                    remove_file_quietly(file_path)
                                else:
                                    with open(file_path, 'w') as f:
                                        f.write(NEW_LINE.join(keep_codes))
Exemple #5
0
    def start_applications(self, debug=False):
        settings = get_appsettings(self.config_path)
        not_found_application = settings.local_conf.pop(
            'not_found_application',
            settings.global_conf.get('not_found_application'))
        if not_found_application:
            not_found_application = loadapp(
                not_found_application,
                global_conf=settings.global_conf)
        else:
            not_found_application = not_found_api_application(
                settings.global_conf, **settings.local_conf)
        self.not_found_application = not_found_application

        self.validate_config_seconds = maybe_integer(
            settings.local_conf.pop('validate_config_seconds', None))

        for path, app_name in settings.local_conf.items():
            path = parse_path_expression(path)
            self[path] = get_app(self.config_path, app_name)

            if debug:
                print (
                    'Application %s reloaded on pid %s'
                    % (app_name, getpid()))
Exemple #6
0
    def __init__(self, page=1, limit_per_page=20):
        super(PaginationClass, self).__init__()

        if str(limit_per_page).lower() == 'all':
            self.limit_per_page = 'all'
        else:
            self.limit_per_page = maybe_integer(limit_per_page)
            if not self.limit_per_page or self.limit_per_page < 1:
                self.limit_per_page = 20

        self.number_of_results = 0

        self.page = maybe_integer(page)
        if not self.page or self.page < 1:
            self.page = 1
        self.last_page = self.page
Exemple #7
0
    def unlock(self, name):
        name_256 = self.format_name(name)
        last_position = maybe_integer(self.memcache.get(name_256))
        if last_position:
            for position in range(1, last_position + 1):
                position_name_256 = self.format_position_name(name_256, position)
                if self.memcache.get(position_name_256) and self.memcache.delete(position_name_256):
                    return True

        # If no position found, delete base lock
        return self.memcache.delete(name_256)
Exemple #8
0
def resolve_deform_error(form, error):
    if not ValidationFailure:
        raise NotImplementedError('deform package missing')

    if isinstance(error, Invalid):
        key = error.node.name
        message = error.msg
    else:
        key = error.key
        message = error.message

    form_error = Invalid(form, message)

    node = form
    node_form_error = form_error
    key_parts = key.split('.')
    last_key_part = key_parts.pop()

    for key_part in key_parts:
        if isinstance(node.typ, Sequence):
            position = maybe_integer(key_part)
            if position is not None:
                try:
                    node = node.children[position]
                except IndexError:
                    pass
                else:
                    node_error = Invalid(node, '')
                    node_form_error.add(node_error, position)
                    node_form_error = node_error
                    continue

            form.hide_global_error = False
            break
        else:
            for position, child in enumerate(node.children):
                if child.name == key_part:
                    node = child
                    node_error = Invalid(node, '')
                    node_form_error.add(node_error, position)
                    node_form_error = node_error
                    break
            else:
                form.hide_global_error = False
                break

    try:
        node_form_error[last_key_part] = message
    except:
        form.hide_global_error = False

    form.widget.handle_error(form, form_error)
    return ValidationFailure(form, form_error.value, form_error)
Exemple #9
0
    def __init__(
            self,
            path,
            expire=None,
            retry_errno=None,
            retries=3,
            **lock_settings):

        self.expire = maybe_integer(expire)
        self.path = make_dir(path)
        self.retries = maybe_integer(retries) or 3
        self.retry_errno = maybe_set(retry_errno)
        self.retry_errno.update(DEFAULT_RETRY_ERRNO)

        # Lock settings
        settings = {}
        for key, value in list(lock_settings.items()):
            if key.startswith('lock_'):
                settings[key.split('lock_', 1)[1]] = value

        lock_path = settings.pop('path', None) or join_paths(self.path, 'locks')
        self.lockme = LockMe(lock_path, **settings)
Exemple #10
0
    def __init__(self, query, page=1, limit_per_page=20):
        super(Pagination, self).__init__()

        self.limit_per_page = maybe_integer(limit_per_page)
        if not self.limit_per_page or self.limit_per_page < 1:
            self.limit_per_page = 20
        elif self.limit_per_page > 5000:
            self.limit_per_page = 5000

        if query is None:
            self.number_of_results = 0
            self.last_page = 1
            self.page = 1
        else:
            # See https://bitbucket.org/zzzeek/sqlalchemy/issue/3320
            if SQLALCHEMY_VERSION >= '1.0':
                entities = set(d['entity'] for d in query.column_descriptions)
            else:
                entities = set(e.entity_zero for e in query._entities if e.entity_zero)

            self.number_of_results = (
                query
                .with_entities(func.count(1), *entities)
                .order_by(None)
                .first()[0])
            self.last_page = int(ceil(
                self.number_of_results / float(self.limit_per_page))) or 1

            self.page = maybe_integer(page)
            if not self.page or self.page < 1:
                self.page = 1
            elif self.page > self.last_page:
                self.page = self.last_page

            end_slice = self.page * self.limit_per_page
            start_slice = end_slice - self.limit_per_page
            self.extend(query.slice(start_slice, end_slice).all())

        self.number_of_page_results = len(self)
Exemple #11
0
    def __init__(self, query, page=1, limit_per_page=20):
        super(Pagination, self).__init__()

        self.limit_per_page = maybe_integer(limit_per_page)
        if not self.limit_per_page or self.limit_per_page < 1:
            self.limit_per_page = 20
        elif self.limit_per_page > 5000:
            self.limit_per_page = 5000

        if query is None:
            self.number_of_results = 0
            self.last_page = 1
            self.page = 1
        else:
            # See https://bitbucket.org/zzzeek/sqlalchemy/issue/3320
            if SQLALCHEMY_VERSION >= '1.0':
                entities = set(d['entity'] for d in query.column_descriptions)
            else:
                entities = set(e.entity_zero for e in query._entities
                               if e.entity_zero)

            self.number_of_results = (query.with_entities(
                func.count(1), *entities).order_by(None).first()[0])
            self.last_page = int(
                ceil(self.number_of_results / float(self.limit_per_page))) or 1

            self.page = maybe_integer(page)
            if not self.page or self.page < 1:
                self.page = 1
            elif self.page > self.last_page:
                self.page = self.last_page

            end_slice = self.page * self.limit_per_page
            start_slice = end_slice - self.limit_per_page
            self.extend(query.slice(start_slice, end_slice).all())

        self.number_of_page_results = len(self)
Exemple #12
0
    def __init__(
            self,
            url,
            expire=None,
            **settings):

        # Lock settings
        lock_settings = {}
        for key in list(settings.keys()):
            if key.startswith('lock_'):
                lock_settings[key.split('lock_', 1)[1]] = settings.pop(key)
        lock_settings.update(settings)

        self.memcache_module = _import_module('memcache')
        self.memcache = self.memcache_module.Client(url.split(';'), **settings)
        self.expire = maybe_integer(expire)
        self.lockme = LockMeMemcached(url, **lock_settings)
Exemple #13
0
    def __init__(
            self,
            path,
            timeout=30,
            delete_lock_on_timeout=False,
            retry_errno=None,
            retries=3):

        self.path = make_dir(path)
        self.timeout = int(timeout)
        self.delete_lock_on_timeout = delete_lock_on_timeout
        self.retries = maybe_integer(retries) or 3
        self.retry_errno = maybe_set(retry_errno)
        self.retry_errno.update(DEFAULT_RETRY_ERRNO)

        # Clean locks!
        self.clean_junk_locks_as_daemon()
Exemple #14
0
    def start_applications(self, debug=False):
        settings = get_appsettings(self.config_path)
        not_found_application = settings.local_conf.pop(
            'not_found_application',
            settings.global_conf.get('not_found_application'))
        if not_found_application:
            not_found_application = loadapp(not_found_application,
                                            global_conf=settings.global_conf)
        else:
            not_found_application = not_found_api_application(
                settings.global_conf, **settings.local_conf)
        self.not_found_application = not_found_application

        self.validate_config_seconds = maybe_integer(
            settings.local_conf.pop('validate_config_seconds', None))

        for path, app_name in settings.local_conf.items():
            path = parse_path_expression(path)
            self[path] = get_app(self.config_path, app_name)

            if debug:
                print('Application %s reloaded on pid %s' %
                      (app_name, getpid()))
Exemple #15
0
    def clean_junk_locks(self, name_256):
        last_position = maybe_integer(self.memcache.get(name_256))
        if last_position:
            active_positions = 0
            for position in range(1, last_position + 1):
                position_name_256 = self.format_position_name(name_256, position)
                binary = self.memcache.get(position_name_256)
                if not binary:
                    continue

                info = binary.split()
                if len(info) >= 2 and info[0] == DOMAIN_NAME and info[1].isnumeric():
                    try:
                        getpgid(int(info[1]))
                    except OSError as error:
                        if error.errno is errno.ESRCH:
                            self.memcache.delete(position_name_256)
                            continue

                active_positions += 1

            if not active_positions:
                self.memcache.delete(name_256)
                return True
Exemple #16
0
def format_crontab_options(**kwargs):
    for key in kwargs.keys():
        if key not in DATES_RANGES:
            raise ValueError("Invalid cron key %s" % key)

    options = {}
    for key, (start_range, end_range) in DATES_RANGES.items():
        values = kwargs.get(key)
        if values is None:
            continue

        if not is_nonstr_iter(values):
            values = [values]
        if "*" in values:
            continue

        key_options = set()
        for value in set(values):
            value = to_string(value)

            if key == "day" and value.lower() == "l":
                options["last_day_of_month"] = True
                continue

            int_values = set()
            ignore_options_add = False

            if key == "weekday" and value.lower().endswith("l"):
                weekday = maybe_integer(value[0])
                if weekday is None:
                    message = 'Invalid %s integer on "%s"' % (key, value)
                    raise ValueError(message)
                int_values.add(weekday)
                options["last_weekday_of_month"] = weekday
                ignore_options_add = True

            elif value.isnumeric():
                int_values.add(int(value))

            elif value == "?":
                now = NOW()
                if key == "weekday":
                    int_values.add(now.weekday())
                else:
                    int_values.add(getattr(now, key))

            elif "/" in value:
                range_int, interval = value.split("/", 1)

                interval = maybe_integer(interval)
                if interval is None or interval < 1:
                    message = 'Invalid %s interval for "%s"' % (key, value)
                    raise ValueError(message)

                if range_int == "*":
                    start = start_range
                    end = end_range
                elif "-" in range_int:
                    start, end = range_int.split("-", 1)
                    start = maybe_integer(start)
                    end = maybe_integer(end)
                    if start is None or end is None:
                        message = 'Invalid %s integer on "%s"' % (key, value)
                        raise ValueError(message)
                else:
                    message = 'Invalid %s format "%s"' % (key, value)
                    raise ValueError(message)

                int_values.update(range(start, end + 1, interval))

            elif "," in value:
                for int_value in value.split(","):
                    int_value = maybe_integer(int_value)
                    if int_value is None:
                        message = 'Invalid %s integer on "%s"' % (key, value)
                        raise ValueError(message)
                    int_values.add(int_value)

            elif "-" in value:
                start, end = value.split("-", 1)
                start = maybe_integer(start)
                end = maybe_integer(end)
                if start is None or end is None:
                    message = 'Invalid %s integer on "%s"' % (key, value)
                    raise ValueError(message)
                int_values.update(range(start, end + 1))

            else:
                message = 'Invalid %s integer "%s"' % (key, value)
                raise ValueError(message)

            for int_value in int_values:
                if start_range > int_value or int_value > end_range:
                    message = 'Invalid %s "%s". Start: %s End: %s' % (key, value, start_range, end_range)
                    raise ValueError(message)

            if not ignore_options_add:
                key_options.update(int_values)

        if key_options:
            options[key] = sorted(key_options)

    return options
Exemple #17
0
 def max_age(self):
     return maybe_integer(self.settings.get('max_age'))
Exemple #18
0
 def token_expire_seconds(self):
     if not self.request.is_production_environ and 'tokenLifetime' in self.request.GET:
         maybe_seconds = maybe_integer(self.request.GET['tokenLifetime'])
         if maybe_seconds and maybe_seconds >= 1:
             return maybe_seconds
     return int(self.settings['token.expire_seconds'])
Exemple #19
0
    def resize_image(self, fid, application_code, resize_name):
        if application_code not in self.api_session_manager.resizes:
            raise Error('application_code', u('Invalid application code: %s') % application_code)

        resize = self.api_session_manager.resizes[application_code].get(resize_name)
        if not resize:
            raise Error('resize_name', u('Invalid resize name: %s') % resize_name)
        resize_width = maybe_integer(resize.get('width'))
        resize_height = maybe_integer(resize.get('height'))
        if not resize_width and not resize_height:
            raise Error('resize', 'Invalid resize options')

        file_info = self.get_file(
            id=fid,
            application_code=application_code,
            attributes=['open_file', 'key', 'filename', 'title', 'code_key'])
        if not file_info:
            raise Error('file', 'File ID not found')

        temporary_path = None
        type_key = u('resize-%s') % resize_name
        filename = None
        if file_info.filename:
            filename = u('%s-%s') % (resize_name, file_info.filename)

        lock_key = 'create image resize %s %s' % (fid, resize_name)
        self.cache.lock(lock_key)
        try:
            existing = (
                self.session
                .query(File)
                .filter(File.parent_id == fid)
                .filter(File.application_code == application_code)
                .filter(File.type_key == type_key)
                .first())

            if not existing:
                original_temporary_path, original_file = create_temporary_file(mode='wb')
                original_file.write(file_info.open_file.read())
                original_file.close()

                original_file = get_open_file(original_temporary_path)
                im = self.api_session_manager.image_cls.open(original_file)

                width = int(im.size[0])
                height = int(im.size[1])

                if not resize_width:
                    resize_width = ceil((float(width) * resize_height) / height)

                elif not resize_height:
                    resize_height = ceil((float(resize_width) * height) / width)

                else:
                    resize_racio = resize_width / float(resize_height)
                    image_racio = width / float(height)

                    if image_racio < resize_racio:
                        # Crop image on height
                        crop_size = ceil(round(height - (width / resize_racio)) / 2)
                        lower_position = int(height - int(crop_size))
                        # Crop as left, upper, right, and lower pixel
                        im = im.crop((0, int(crop_size), width, lower_position))

                    elif image_racio > resize_racio:
                        crop_size = ceil(round(width - (height * resize_racio)) / 2)
                        right_position = int(width - int(crop_size))
                        # Crop as left, upper, right, and lower pixel
                        im = im.crop((int(crop_size), 0, right_position, height))

                # Resize image
                im = im.resize((int(resize_width), int(resize_height)), self.api_session_manager.resize_quality)
                temporary_path = save_temporary_image(im)
                resized = get_open_file(temporary_path)

                original_file.close()
                remove_file_quietly(original_temporary_path)

                self.save_file(
                    resized,
                    application_code=application_code,
                    code_key=file_info.code_key,
                    type_key=type_key,
                    filename=filename,
                    title=file_info.title,
                    parent_id=fid)

        finally:
            self.cache.unlock(lock_key)

            if temporary_path:
                remove_file_quietly(temporary_path)

        return True
Exemple #20
0
    def get_cores(
            self,
            core_name,
            attributes,
            order_by=None,
            page=None,
            limit_per_page=None,
            filters=None,
            active=True,
            key=None,
            start_date=None,
            end_date=None,
            updated_date=None,
            created_date=None,
            only_one=False):

        # Set Core defaults
        filters = filters or {}
        if key:
            filters.setdefault(core_name, {})['key'] = key
        if start_date:
            filters.setdefault(core_name, {})['start_date'] = start_date
        if end_date:
            filters.setdefault(core_name, {})['end_date'] = end_date
        if updated_date:
            filters.setdefault(core_name, {})['updated_date'] = updated_date
        if created_date:
            filters.setdefault(core_name, {})['created_date'] = created_date

        # Pagination
        with_pagination = bool(
            limit_per_page is not None
            or page is not None)
        if with_pagination:
            only_one = False
            page = maybe_integer(page)
            if not page or page < 1:
                page = 1
            limit_per_page = maybe_integer(limit_per_page)
            if not limit_per_page or limit_per_page < 1:
                limit_per_page = 1000

        table = CORE_TYPES[core_name]['table']

        # Convert attributes do dict
        if not attributes:
            attributes = dict((k, None) for k in table._sa_class_manager.keys())
        elif isinstance(attributes, dict):
            attributes = deepcopy(attributes)
        elif not is_nonstr_iter(attributes):
            attributes = {attributes: None}
        else:
            attributes = dict((k, None) for k in attributes)

        # Lookup for table columns
        columns = set()
        for key in attributes.keys():
            if key == 'active':
                attributes.pop(key)  # Dont need this attribute anymore
                columns.add(get_active_column(Core, active))

            elif not is_nonstr_iter(key) and hasattr(table, key):
                attributes.pop(key)  # Dont need this attribute anymore
                column = getattr(table, key)
                if isinstance(column, CoreColumnParent):
                    column = getattr(Core, key)
                columns.add(column)

        # Lookup for branch columns
        branches_tables = MissingSet()
        for branch in CORE_TYPES[core_name]['branches']:
            for key in attributes.keys():
                if not is_nonstr_iter(key) and hasattr(branch, key):
                    branches_tables[branch].add(key)
        if branches_tables:
            for branch, keys in branches_tables.items():
                for key in keys:
                    attributes.pop(key, None)  # Dont need this attribute anymore
                    columns.add(getattr(branch, key))

        if not columns:
            columns.add(Core.key)

        # Lookup for child columns
        relate_with_child = {}
        relate_with_foreign = {}
        if attributes:
            for child in CORE_TYPES[core_name]['childs']:
                for key in attributes.keys():
                    if is_nonstr_iter(key):
                        child_core_name, child_key, label_name = key
                        if child_core_name == child.core_name:
                            attributes.pop(key)  # Dont need this attribute anymore
                            if child.core_name not in relate_with_child:
                                alias_child = aliased(Core)
                                relate_with_child[child.core_name] = (child, alias_child)
                            else:
                                alias_child = relate_with_child[child.core_name][1]

                            column = getattr(child, child_key)
                            if isinstance(column, CoreColumnParent):
                                column = getattr(alias_child, child_key)
                            columns.add(column.label(label_name))

                    elif hasattr(child, key):
                        attributes.pop(key)  # Dont need this attribute anymore

                        if child.core_name not in relate_with_child:
                            alias_child = aliased(Core)
                            relate_with_child[child.core_name] = (child, alias_child)
                        else:
                            alias_child = relate_with_child[child.core_name][1]

                        column = getattr(child, key)
                        if isinstance(column, CoreColumnParent):
                            column = getattr(alias_child, key)
                        columns.add(column)

            core_foreign = getattr(table, 'core_foreign_key', None)
            if core_foreign is not None:
                column_key, foreign_column = core_foreign
                foreign_name = foreign_column.table.name
                if foreign_name.startswith('core_'):
                    foreign_name = foreign_name.split('core_', 1)[1]
                foreign_table = CORE_TYPES[foreign_name]['table']
                foreign_possible_pattern = getattr(foreign_table, 'core_possible_pattern', None)

                for key in attributes.keys():
                    if is_nonstr_iter(key):
                        child_core_name, child_key, label_name = key
                        if child_core_name == foreign_table.core_name:
                            attributes.pop(key)  # Dont need this attribute anymore
                            if foreign_table.core_name not in relate_with_foreign:
                                alias_child = aliased(Core)
                                relate_with_foreign[foreign_table.core_name] = (foreign_table, alias_child, column_key)
                            else:
                                alias_child = relate_with_foreign[foreign_table.core_name][1]

                            column = getattr(foreign_table, child_key)
                            if isinstance(column, CoreColumnParent):
                                column = getattr(alias_child, child_key)
                            columns.add(column.label(label_name))

                    elif hasattr(foreign_table, key):
                        attributes.pop(key)  # Dont need this attribute anymore

                        if foreign_table.core_name not in relate_with_foreign:
                            alias_child = aliased(Core)
                            relate_with_foreign[foreign_table.core_name] = (foreign_table, alias_child, column_key)
                        else:
                            alias_child = relate_with_foreign[foreign_table.core_name][1]

                        column = getattr(foreign_table, key)
                        if isinstance(column, CoreColumnParent):
                            column = getattr(alias_child, key)
                        columns.add(column)

                    elif foreign_possible_pattern and key.startswith(foreign_possible_pattern):
                        new_key = key.split(foreign_possible_pattern, 1)[1]

                        if hasattr(foreign_table, new_key):
                            attributes.pop(key, None)  # Dont need this attribute anymore

                            if foreign_table.core_name not in relate_with_foreign:
                                alias_child = aliased(Core)
                                relate_with_foreign[foreign_table.core_name] = (foreign_table, alias_child, column_key)
                            else:
                                alias_child = relate_with_foreign[foreign_table.core_name][1]

                            column = getattr(foreign_table, new_key)
                            if isinstance(column, CoreColumnParent):
                                column = getattr(alias_child, new_key)
                            columns.add(column.label(key))

        relate_with_father = False
        parent = CORE_TYPES[core_name]['parent']
        alias_parent = aliased(Core)
        parent_possible_names = getattr(parent, 'core_possible_names', None)
        if parent is not None and attributes:
            parent_possible_pattern = getattr(parent, 'core_possible_pattern', None)
            for key in attributes.keys():
                if is_nonstr_iter(key):
                    parent_core_name, parent_key, label_name = key
                    if parent_core_name == parent.core_name:
                        attributes.pop(key, None)  # Dont need this attribute anymore
                        relate_with_father = True

                        column = getattr(parent, parent_key)
                        if isinstance(column, CoreColumnParent):
                            column = getattr(alias_parent, parent_key)
                        columns.add(column.label(label_name))

                elif hasattr(parent, key):
                    attributes.pop(key, None)  # Dont need this attribute anymore
                    relate_with_father = True

                    column = getattr(parent, key)
                    if isinstance(column, CoreColumnParent):
                        column = getattr(alias_parent, key)
                    columns.add(column)

                elif parent_possible_pattern and key.startswith(parent_possible_pattern):
                    new_key = key.split(parent_possible_pattern, 1)[1]

                    if hasattr(parent, new_key):
                        attributes.pop(key, None)  # Dont need this attribute anymore
                        relate_with_father = True

                        column = getattr(parent, new_key)
                        if isinstance(column, CoreColumnParent):
                            column = getattr(alias_parent, new_key)
                        columns.add(column.label(key))

        if attributes:
            childs_names = [t.core_name for t in CORE_TYPES[core_name]['childs']]
            for key in attributes.keys():
                if key in childs_names:
                    continue

                elif parent and (
                        key == parent.core_name
                        or (parent_possible_names and key in parent_possible_names)):
                    columns.add(getattr(alias_parent, 'id').label('_parent_id_core'))
                    relate_with_father = True
                    continue

                raise ValueError(
                    'Attribute %s is not a child of %s'
                    % (key, core_name))
            columns.add(Core.id)

        queries = []
        if filters:
            filters = deepcopy(filters)
            if core_name in filters:
                for key, values in filters.pop(core_name).items():
                    column = getattr(table, key)
                    if isinstance(column, CoreColumnParent):
                        column = getattr(Core, key)

                    query_filter = create_filter_by(column, values)
                    if query_filter is not None:
                        queries.append(query_filter)

            core_foreign = getattr(table, 'core_foreign_key', None)
            if core_foreign is not None:
                column_key, foreign_column = core_foreign
                foreign_name = foreign_column.table.name
                if foreign_name.startswith('core_'):
                    foreign_name = foreign_name.split('core_', 1)[1]

                if foreign_name in filters:
                    if foreign_name in relate_with_foreign:
                        foreign_table, aliased_foreign, column_key = relate_with_foreign[foreign_name]
                    else:
                        foreign_table = CORE_TYPES[foreign_name]['table']
                        aliased_foreign = aliased(Core)
                        relate_with_foreign[foreign_name] = (foreign_table, aliased_foreign, column_key)

                    for key, values in filters.pop(foreign_name).items():
                        column = getattr(foreign_table, key)
                        if isinstance(column, CoreColumnParent):
                            column = getattr(aliased_foreign, key)

                        query_filter = create_filter_by(column, values)
                        if query_filter is not None:
                            queries.append(query_filter)

            cores_ids = set()
            looked_cores = False
            for child_core_name, values in filters.items():
                if child_core_name in relate_with_child:
                    child, alias_child = relate_with_child[child_core_name]

                    child_query = self.session.query(alias_child.parent_id)
                    for key, values in filters[child_core_name].items():
                        column = getattr(child, key)
                        if isinstance(column, CoreColumnParent):
                            column = getattr(alias_child, key)
                        if not is_nonstr_iter(values):
                            child_query  = child_query.filter(column == values)
                        else:
                            values = set(values)
                            child_query  = child_query.filter(maybe_with_none(column, values))

                    if active is not None:
                        child_query = (
                            child_query
                                .filter(alias_child.id == child.id_core)
                                .filter(get_active_filter(alias_child, active)))

                    cores_ids.update(q.parent_id for q in child_query.all())
                    looked_cores = True

                else:
                    # Look in childs
                    child_found = False
                    for child in CORE_TYPES[core_name]['childs']:
                        if child.core_name == child_core_name:
                            child_found = True
                            alias_child = aliased(Core)
                            relate_with_child[child_core_name] = (child, alias_child)

                            for key, values in filters.pop(child_core_name).items():
                                column = getattr(child, key)
                                if isinstance(column, CoreColumnParent):
                                    column = getattr(alias_child, key)

                                query_filter = create_filter_by(column, values)
                                if query_filter is not None:
                                    queries.append(query_filter)
                    if child_found:
                        continue

                    # Look in branches
                    branch_found = False
                    for branch in CORE_TYPES[core_name]['branches']:
                        if branch.core_name == child_core_name:
                            branch_found = True
                            branches_tables[branch] = None
                            for key, values in filters.pop(child_core_name).items():
                                column = getattr(branch, key)

                                query_filter = create_filter_by(column, values)
                                if query_filter is not None:
                                    queries.append(query_filter)
                    if branch_found:
                        continue

                    # Look parent
                    parent = CORE_TYPES[core_name]['parent']
                    if parent and parent.core_name == child_core_name:
                        if not relate_with_father:
                            alias_parent = aliased(Core)
                        relate_with_father = True

                        for key, values in filters.pop(child_core_name).items():
                            column = getattr(parent, key)
                            if isinstance(column, CoreColumnParent):
                                column = getattr(alias_parent, key)

                            query_filter = create_filter_by(column, values)
                            if query_filter is not None:
                                queries.append(query_filter)
                        continue

                    raise ValueError(
                        'Invalid filter %s for core %s'
                        % (child_core_name, core_name))

            if cores_ids:
                queries.append(maybe_with_none(table.id_core, cores_ids))
            elif looked_cores:
                # Pagination for main query
                if with_pagination:
                    return CorePagination(
                        page=1,
                        limit_per_page=limit_per_page,
                        last_page=1,
                        number_of_results=0)
                elif only_one:
                    return None
                else:
                    return []

        query = self.session.query(*columns)

        if relate_with_child or branches_tables:
            query = query.select_from(Core)
            for child, alias_child in relate_with_child.values():
                child_queries = [
                    alias_child.type == child.core_name,
                    alias_child.parent_id == Core.id]

                if active is not None:
                    child_queries.append(get_active_filter(alias_child, active))

                query = query.outerjoin(alias_child, and_(*child_queries))

                child_queries = [child.id_core == alias_child.id]
                #if hasattr(child, 'core_on_child_relation'):
                #    option = child.core_on_child_relation
                #    child_queries.append(getattr(child, option[0], option[1]))
                query = query.outerjoin(child, and_(*child_queries))

            for branch in branches_tables.keys():
                query = query.outerjoin(branch, branch.id_core == Core.id)

        if queries:
            query = query.filter(and_(*queries))

        if relate_with_foreign:
            for foreign_table, aliased_foreign, column_key in relate_with_foreign.values():
                query = query.filter(aliased_foreign.id == getattr(table, column_key))

                if active is not None:
                    query = query.filter(get_active_filter(aliased_foreign, active))

        if relate_with_father:
            query = (
                query
                .filter(parent.id_core == alias_parent.id)
                .filter(alias_parent.type == table_type(parent))
                .filter(Core.parent_id == alias_parent.id))
            if active is not None:
                query = query.filter(get_active_filter(alias_parent, active))

        if table is not Core:
            query = query.filter(table.id_core == Core.id).filter(Core.type == table_type(table))
        if active is not None:
            query = query.filter(get_active_filter(Core, active))

        # Set order by
        order_by = create_order_by(table, order_by)
        if order_by is not None:
            if is_nonstr_iter(order_by):
                order_by = [ob for ob in order_by if ob is not None] or None
                if order_by:
                    query = query.order_by(*order_by)
            else:
                query = query.order_by(order_by)
        if order_by is None and not only_one:
            query = query.order_by(table.id_core)

        # Pagination for main query
        if with_pagination:
            number_of_results = (
                query
                .with_entities(func.count(Core.id.distinct()))
                .first()[0])

            last_page = int(ceil(number_of_results / float(limit_per_page))) or 1
            if page > last_page:
                page = last_page
            end_slice = page * limit_per_page
            start_slice = end_slice - limit_per_page

        # Make sure if unique
        query = query.group_by(Core.id)

        if with_pagination:
            result = CorePagination(
                page,
                limit_per_page,
                last_page,
                number_of_results)
            result.extend(query.slice(start_slice, end_slice).all())
        elif only_one:
            result = query.first()
        else:
            result = query.all()

        if not attributes or not result:
            return result

        if only_one:
            result = [result]

        labels = set(result[0]._labels)
        labels.update(attributes.keys())
        labels = tuple(labels)

        references = {}
        parent_ids_reference = MissingList()
        for value in result:
            value._labels = labels
            if hasattr(value, '_parent_id_core'):
                parent_ids_reference[value._parent_id_core].append(value)
            references[value.id] = value
            for key in attributes.keys():
                if parent and (
                    key == parent.core_name
                    or (parent_possible_names and key in parent_possible_names)):
                    setattr(value, key, None)
                else:
                    setattr(value, key, [])

        for key, key_attributes in attributes.items():
            key_filters = deepcopy(filters)

            if parent and (
                    key == parent.core_name
                    or (parent_possible_names and key in parent_possible_names)):
                key_filters = {parent.core_name: {'id_core': parent_ids_reference.keys()}}
                key_attributes['id_core'] = None
                for value in self.get_cores(
                        parent.core_name,
                        key_attributes,
                        active=active,
                        filters=key_filters):
                    for child_value in parent_ids_reference[value.id_core]:
                        setattr(child_value, key, value)
            else:
                if key_filters:
                    key_parents_ids = references.keys()
                    if key in key_filters and 'parent_id' in key_filters[key]:
                        key_parents_ids = set(key_parents_ids)
                        if not is_nonstr_iter(key_filters[key]['parent_id']):
                            key_parents_ids.add(key_filters[key]['parent_id'])
                        else:
                            key_parents_ids.update(key_filters[key]['parent_id'])

                    key_filters[key] = {'parent_id': key_parents_ids}
                else:
                    key_filters = {key: {'parent_id': references.keys()}}

                key_attributes['parent_id'] = None
                for value in self.get_cores(
                        key,
                        key_attributes,
                        active=active,
                        filters=key_filters):
                    getattr(references[value.parent_id], key).append(value)

        if only_one:
            return result[0]
        else:
            return result
Exemple #21
0
 def max_age(self):
     return maybe_integer(self.settings.get('max_age'))
Exemple #22
0
    def old_get_core_query(self,
                           columns,
                           active=True,
                           order_by=None,
                           page=None,
                           limit_per_page=None,
                           ignore_before_queries=True,
                           **filters):

        # Pagination
        with_pagination = bool(limit_per_page is not None or page is not None)
        if with_pagination:
            page = maybe_integer(page)
            if not page or page < 1:
                page = 1

            limit_per_page = maybe_integer(limit_per_page)
            if not limit_per_page or limit_per_page < 1:
                limit_per_page = 1000

        tables = set()
        tables_with_relations = set()
        query_columns = []
        tables_aliased = CoreAliased()

        # Create order by
        order_by = []
        if order_by:
            if not is_nonstr_iter(order_by):
                order_by = [order_by]
            for column in order_by:
                for table in get_object_tables(column):
                    name = 'core'
                    if table.name != name:
                        name = table.name.split('core_', 1)[1]
                    table = CORE_TYPES[name]['table']
                    tables.add(table)

                    if active:
                        # Find parent tables
                        tables.update(find_parent_tables(table))

                    # Find return columns
                    if isinstance(column, CoreColumnParent):
                        alias = tables_aliased[table.core_name]
                        column = column.get_alias_column(alias)
                    order_by.append((table, column))

        # Define filters tables
        before_queries = MissingList()
        for core_name, core_filters in filters.items():
            table = CORE_TYPES[core_name]['table']
            tables.add(table)

            if ignore_before_queries or not self.use_before_queries:
                continue

            indexed = self.indexed_columns[core_name]
            for key in core_filters.keys():
                if key not in indexed:
                    column = getattr(table, key)
                    if isinstance(column, CoreColumnParent):
                        continue

                    values = core_filters.pop(key)
                    if isinstance(values, ClauseElement):
                        before_queries[core_name].append(values)
                    elif not is_nonstr_iter(values):
                        before_queries[core_name].append(column == values)
                    else:
                        values = set(values)
                        values_filter = maybe_with_none(column, values)
                        before_queries[core_name].append(values_filter)

        # Find return tables in columns
        for column in columns:
            for table in get_object_tables(column):
                name = 'core'
                if table.name != name:
                    name = table.name.split('core_', 1)[1]
                table = CORE_TYPES[name]['table']
                tables.add(table)

                if active:
                    # Find parent tables
                    tables.update(find_parent_tables(table))

                # Find return columns
                if isinstance(column, CoreColumnParent):
                    alias = tables_aliased[table.core_name]
                    alias_column = column.get_alias_column(alias)
                    query_columns.append(alias_column)
                else:
                    query_columns.append(column)

        # Relations
        outerjoins = MissingList()
        queries = []
        for table in tables:
            relation, relation_table = getattr(table, 'core_relation',
                                               (None, None))
            if relation == 'branch':
                outerjoins[relation_table].append(
                    (table, relation_table.id_core == table.id_core))
                tables_with_relations.add(table)
                continue

            is_core_table = bool(table.__tablename__ == 'core')
            if not is_core_table:
                # Relation core extesion with Core base
                tables_with_relations.add(table)
                alias = tables_aliased[table.core_name]
                queries.append(table.id_core == alias.id)
                queries.append(alias.type == table.core_name)

            # Ignore inactive objects if requested
            if active:
                table_inactives = table
                if not is_core_table:
                    table_inactives = alias
                queries.append(
                    or_(table_inactives.start_date <= func.now(),
                        table_inactives.start_date.is_(None)))
                queries.append(
                    or_(table_inactives.end_date >= func.now(),
                        table_inactives.end_date.is_(None)))

            # Define parent relation if requested
            # or to validate if parent is active
            # Define branch relation
            if relation == 'parent' and (active or relation_table in tables):
                tables_with_relations.add(relation_table)
                queries.append(alias.parent_id == relation_table.id_core)

            core_foreign = getattr(table, 'core_foreign_key', None)
            if core_foreign is not None:
                column_key, foreign_column = core_foreign
                name = foreign_column.table.name
                if name.startswith('core_'):
                    name = name.split('core_', 1)[1]
                foreign_table = CORE_TYPES[name]['table']
                if foreign_table in tables:
                    tables_with_relations.add(foreign_table)
                    tables_with_relations.add(table)
                    queries.append(
                        foreign_column == getattr(table, column_key))

        # Start query
        query = self.session.query(*query_columns)
        if outerjoins:
            for table, relations in outerjoins.items():
                query = query.select_from(table)
                for join_table, on_query in relations:
                    query = query.outerjoin(join_table, on_query)
        if queries:
            query = query.filter(and_(*queries))

        # Define filters
        normal_filters = MissingList()
        for core_name, core_filters in filters.items():
            table = CORE_TYPES[core_name]['table']
            for key, values in core_filters.items():
                if isinstance(values, ClauseElement):
                    normal_filters[core_name].append(values)
                else:
                    column = getattr(table, key)
                    is_alias = isinstance(column, CoreColumnParent)
                    if is_alias:
                        alias = tables_aliased[table.core_name]
                        column = column.get_alias_column(alias)

                    if not is_nonstr_iter(values):
                        key_filter = (column == values)
                    else:
                        values = set(values)
                        key_filter = maybe_with_none(column, values)

                    if is_alias:
                        query = query.filter(key_filter)
                    else:
                        normal_filters[core_name].append(key_filter)

        missing_relations = tables.difference(tables_with_relations)
        if Core in missing_relations:
            missing_relations.remove(Core)
            if len(tables) > 1:
                message = (u'Dont use core with others cores tables. '
                           u'No relation possible.')
                raise Error('core', message)

        if missing_relations:
            message = (u'Missing tables (%s) relations' %
                       u', '.join(t.__tablename__ for t in missing_relations))
            raise Error('core', message)

        # Optimization queries
        # Make others queries if requested!
        if before_queries:
            found_something = False
            before_cores_queries = []
            for core_name, before_filters in before_queries.items():
                table = CORE_TYPES[core_name]['table']

                before_query = (self.session.query(table.id_core).filter(
                    and_(*before_filters)))
                if core_name in normal_filters:
                    before_query = before_query.filter(
                        and_(*normal_filters[core_name]))

                use_ids_if_less = 2501
                cores_ids = set(
                    c.id_core
                    for c in (before_query.slice(0, use_ids_if_less).all()))

                if not cores_ids:
                    found_something = True
                    continue
                elif len(cores_ids) < use_ids_if_less:
                    before_cores_queries.append(table.id_core.in_(cores_ids))
                else:
                    query = (query.filter(and_(*before_filters)).filter(
                        and_(*normal_filters)))

            if len(before_cores_queries) == 1:
                query = query.filter(before_cores_queries[0])
            elif before_cores_queries:
                query = query.filter(or_(*before_cores_queries))
            elif found_something:
                return None

        else:
            for table_filters in normal_filters.values():
                query = query.filter(and_(*table_filters))

        # Set order by
        if order_by:
            query = query.order_by(*(o for t, o in order_by))

        # Pagination for main query
        if with_pagination:
            query = define_pagination(query, page, limit_per_page)

        return query
Exemple #23
0
    def old_get_core_query(
            self,
            columns,
            active=True,
            order_by=None,
            page=None,
            limit_per_page=None,
            ignore_before_queries=True,
            **filters):

        # Pagination
        with_pagination = bool(
            limit_per_page is not None
            or page is not None)
        if with_pagination:
            page = maybe_integer(page)
            if not page or page < 1:
                page = 1

            limit_per_page = maybe_integer(limit_per_page)
            if not limit_per_page or limit_per_page < 1:
                limit_per_page = 1000

        tables = set()
        tables_with_relations = set()
        query_columns = []
        tables_aliased = CoreAliased()

        # Create order by
        order_by = []
        if order_by:
            if not is_nonstr_iter(order_by):
                order_by = [order_by]
            for column in order_by:
                for table in get_object_tables(column):
                    name = 'core'
                    if table.name != name:
                        name = table.name.split('core_', 1)[1]
                    table = CORE_TYPES[name]['table']
                    tables.add(table)

                    if active:
                        # Find parent tables
                        tables.update(find_parent_tables(table))

                    # Find return columns
                    if isinstance(column, CoreColumnParent):
                        alias = tables_aliased[table.core_name]
                        column = column.get_alias_column(alias)
                    order_by.append((table, column))

        # Define filters tables
        before_queries = MissingList()
        for core_name, core_filters in filters.items():
            table = CORE_TYPES[core_name]['table']
            tables.add(table)

            if ignore_before_queries or not self.use_before_queries:
                continue

            indexed = self.indexed_columns[core_name]
            for key in core_filters.keys():
                if key not in indexed:
                    column = getattr(table, key)
                    if isinstance(column, CoreColumnParent):
                        continue

                    values = core_filters.pop(key)
                    if isinstance(values, ClauseElement):
                        before_queries[core_name].append(values)
                    elif not is_nonstr_iter(values):
                        before_queries[core_name].append(column == values)
                    else:
                        values = set(values)
                        values_filter = maybe_with_none(column, values)
                        before_queries[core_name].append(values_filter)

        # Find return tables in columns
        for column in columns:
            for table in get_object_tables(column):
                name = 'core'
                if table.name != name:
                    name = table.name.split('core_', 1)[1]
                table = CORE_TYPES[name]['table']
                tables.add(table)

                if active:
                    # Find parent tables
                    tables.update(find_parent_tables(table))

                # Find return columns
                if isinstance(column, CoreColumnParent):
                    alias = tables_aliased[table.core_name]
                    alias_column = column.get_alias_column(alias)
                    query_columns.append(alias_column)
                else:
                    query_columns.append(column)

        # Relations
        outerjoins = MissingList()
        queries = []
        for table in tables:
            relation, relation_table = getattr(table, 'core_relation', (None, None))
            if relation == 'branch':
                outerjoins[relation_table].append((
                    table,
                    relation_table.id_core == table.id_core))
                tables_with_relations.add(table)
                continue

            is_core_table = bool(table.__tablename__ == 'core')
            if not is_core_table:
                # Relation core extesion with Core base
                tables_with_relations.add(table)
                alias = tables_aliased[table.core_name]
                queries.append(table.id_core == alias.id)
                queries.append(alias.type == table.core_name)

            # Ignore inactive objects if requested
            if active:
                table_inactives = table
                if not is_core_table:
                    table_inactives = alias
                queries.append(
                    or_(table_inactives.start_date <= func.now(),
                        table_inactives.start_date.is_(None)))
                queries.append(
                    or_(table_inactives.end_date >= func.now(),
                        table_inactives.end_date.is_(None)))

            # Define parent relation if requested
            # or to validate if parent is active
            # Define branch relation
            if relation == 'parent' and (active or relation_table in tables):
                tables_with_relations.add(relation_table)
                queries.append(alias.parent_id == relation_table.id_core)

            core_foreign = getattr(table, 'core_foreign_key', None)
            if core_foreign is not None:
                column_key, foreign_column = core_foreign
                name = foreign_column.table.name
                if name.startswith('core_'):
                    name = name.split('core_', 1)[1]
                foreign_table = CORE_TYPES[name]['table']
                if foreign_table in tables:
                    tables_with_relations.add(foreign_table)
                    tables_with_relations.add(table)
                    queries.append(foreign_column == getattr(table, column_key))

        # Start query
        query = self.session.query(*query_columns)
        if outerjoins:
            for table, relations in outerjoins.items():
                query = query.select_from(table)
                for join_table, on_query in relations:
                    query = query.outerjoin(join_table, on_query)
        if queries:
            query = query.filter(and_(*queries))

        # Define filters
        normal_filters = MissingList()
        for core_name, core_filters in filters.items():
            table = CORE_TYPES[core_name]['table']
            for key, values in core_filters.items():
                if isinstance(values, ClauseElement):
                    normal_filters[core_name].append(values)
                else:
                    column = getattr(table, key)
                    is_alias = isinstance(column, CoreColumnParent)
                    if is_alias:
                        alias = tables_aliased[table.core_name]
                        column = column.get_alias_column(alias)

                    if not is_nonstr_iter(values):
                        key_filter = (column == values)
                    else:
                        values = set(values)
                        key_filter = maybe_with_none(column, values)

                    if is_alias:
                        query = query.filter(key_filter)
                    else:
                        normal_filters[core_name].append(key_filter)

        missing_relations = tables.difference(tables_with_relations)
        if Core in missing_relations:
            missing_relations.remove(Core)
            if len(tables) > 1:
                message = (
                    u'Dont use core with others cores tables. '
                    u'No relation possible.')
                raise Error('core', message)

        if missing_relations:
            message = (
                u'Missing tables (%s) relations'
                % u', '.join(t.__tablename__ for t in missing_relations))
            raise Error('core', message)

        # Optimization queries
        # Make others queries if requested!
        if before_queries:
            found_something = False
            before_cores_queries = []
            for core_name, before_filters in before_queries.items():
                table = CORE_TYPES[core_name]['table']

                before_query = (
                    self.session
                    .query(table.id_core)
                    .filter(and_(*before_filters)))
                if core_name in normal_filters:
                    before_query = before_query.filter(
                        and_(*normal_filters[core_name]))

                use_ids_if_less = 2501
                cores_ids = set(
                    c.id_core for c in (
                        before_query
                        .slice(0, use_ids_if_less)
                        .all()))

                if not cores_ids:
                    found_something = True
                    continue
                elif len(cores_ids) < use_ids_if_less:
                    before_cores_queries.append(
                        table.id_core.in_(cores_ids))
                else:
                    query = (
                        query
                        .filter(and_(*before_filters))
                        .filter(and_(*normal_filters)))

            if len(before_cores_queries) == 1:
                query = query.filter(before_cores_queries[0])
            elif before_cores_queries:
                query = query.filter(or_(*before_cores_queries))
            elif found_something:
                return None

        else:
            for table_filters in normal_filters.values():
                query = query.filter(and_(*table_filters))

        # Set order by
        if order_by:
            query = query.order_by(*(o for t, o in order_by))

        # Pagination for main query
        if with_pagination:
            query = define_pagination(query, page, limit_per_page)

        return query
Exemple #24
0
def get_url_info(*args, **kwargs):
    headers = get_url_headers(*args, **kwargs)
    return {
        'size': maybe_integer(headers.get('Content-Length')) or 0,
        'type': maybe_unicode(headers.get('Content-Type')),
        'updated': guess_datetime(headers.get('Last-Modified'))}
Exemple #25
0
    def get_cores(self,
                  core_name,
                  attributes,
                  order_by=None,
                  page=None,
                  limit_per_page=None,
                  filters=None,
                  active=True,
                  key=None,
                  start_date=None,
                  end_date=None,
                  updated_date=None,
                  created_date=None,
                  only_one=False):

        # Set Core defaults
        filters = filters or {}
        if key:
            filters.setdefault(core_name, {})['key'] = key
        if start_date:
            filters.setdefault(core_name, {})['start_date'] = start_date
        if end_date:
            filters.setdefault(core_name, {})['end_date'] = end_date
        if updated_date:
            filters.setdefault(core_name, {})['updated_date'] = updated_date
        if created_date:
            filters.setdefault(core_name, {})['created_date'] = created_date

        # Pagination
        with_pagination = bool(limit_per_page is not None or page is not None)
        if with_pagination:
            only_one = False
            page = maybe_integer(page)
            if not page or page < 1:
                page = 1
            limit_per_page = maybe_integer(limit_per_page)
            if not limit_per_page or limit_per_page < 1:
                limit_per_page = 1000

        table = CORE_TYPES[core_name]['table']

        # Convert attributes do dict
        if not attributes:
            attributes = dict(
                (k, None) for k in table._sa_class_manager.keys())
        elif isinstance(attributes, dict):
            attributes = deepcopy(attributes)
        elif not is_nonstr_iter(attributes):
            attributes = {attributes: None}
        else:
            attributes = dict((k, None) for k in attributes)

        # Lookup for table columns
        columns = set()
        for key in attributes.keys():
            if key == 'active':
                attributes.pop(key)  # Dont need this attribute anymore
                columns.add(get_active_column(Core, active))

            elif not is_nonstr_iter(key) and hasattr(table, key):
                attributes.pop(key)  # Dont need this attribute anymore
                column = getattr(table, key)
                if isinstance(column, CoreColumnParent):
                    column = getattr(Core, key)
                columns.add(column)

        # Lookup for branch columns
        branches_tables = MissingSet()
        for branch in CORE_TYPES[core_name]['branches']:
            for key in attributes.keys():
                if not is_nonstr_iter(key) and hasattr(branch, key):
                    branches_tables[branch].add(key)
        if branches_tables:
            for branch, keys in branches_tables.items():
                for key in keys:
                    attributes.pop(key,
                                   None)  # Dont need this attribute anymore
                    columns.add(getattr(branch, key))

        if not columns:
            columns.add(Core.key)

        # Lookup for child columns
        relate_with_child = {}
        relate_with_foreign = {}
        if attributes:
            for child in CORE_TYPES[core_name]['childs']:
                for key in attributes.keys():
                    if is_nonstr_iter(key):
                        child_core_name, child_key, label_name = key
                        if child_core_name == child.core_name:
                            attributes.pop(
                                key)  # Dont need this attribute anymore
                            if child.core_name not in relate_with_child:
                                alias_child = aliased(Core)
                                relate_with_child[child.core_name] = (
                                    child, alias_child)
                            else:
                                alias_child = relate_with_child[
                                    child.core_name][1]

                            column = getattr(child, child_key)
                            if isinstance(column, CoreColumnParent):
                                column = getattr(alias_child, child_key)
                            columns.add(column.label(label_name))

                    elif hasattr(child, key):
                        attributes.pop(key)  # Dont need this attribute anymore

                        if child.core_name not in relate_with_child:
                            alias_child = aliased(Core)
                            relate_with_child[child.core_name] = (child,
                                                                  alias_child)
                        else:
                            alias_child = relate_with_child[child.core_name][1]

                        column = getattr(child, key)
                        if isinstance(column, CoreColumnParent):
                            column = getattr(alias_child, key)
                        columns.add(column)

            core_foreign = getattr(table, 'core_foreign_key', None)
            if core_foreign is not None:
                column_key, foreign_column = core_foreign
                foreign_name = foreign_column.table.name
                if foreign_name.startswith('core_'):
                    foreign_name = foreign_name.split('core_', 1)[1]
                foreign_table = CORE_TYPES[foreign_name]['table']
                foreign_possible_pattern = getattr(foreign_table,
                                                   'core_possible_pattern',
                                                   None)

                for key in attributes.keys():
                    if is_nonstr_iter(key):
                        child_core_name, child_key, label_name = key
                        if child_core_name == foreign_table.core_name:
                            attributes.pop(
                                key)  # Dont need this attribute anymore
                            if foreign_table.core_name not in relate_with_foreign:
                                alias_child = aliased(Core)
                                relate_with_foreign[
                                    foreign_table.core_name] = (foreign_table,
                                                                alias_child,
                                                                column_key)
                            else:
                                alias_child = relate_with_foreign[
                                    foreign_table.core_name][1]

                            column = getattr(foreign_table, child_key)
                            if isinstance(column, CoreColumnParent):
                                column = getattr(alias_child, child_key)
                            columns.add(column.label(label_name))

                    elif hasattr(foreign_table, key):
                        attributes.pop(key)  # Dont need this attribute anymore

                        if foreign_table.core_name not in relate_with_foreign:
                            alias_child = aliased(Core)
                            relate_with_foreign[foreign_table.core_name] = (
                                foreign_table, alias_child, column_key)
                        else:
                            alias_child = relate_with_foreign[
                                foreign_table.core_name][1]

                        column = getattr(foreign_table, key)
                        if isinstance(column, CoreColumnParent):
                            column = getattr(alias_child, key)
                        columns.add(column)

                    elif foreign_possible_pattern and key.startswith(
                            foreign_possible_pattern):
                        new_key = key.split(foreign_possible_pattern, 1)[1]

                        if hasattr(foreign_table, new_key):
                            attributes.pop(
                                key, None)  # Dont need this attribute anymore

                            if foreign_table.core_name not in relate_with_foreign:
                                alias_child = aliased(Core)
                                relate_with_foreign[
                                    foreign_table.core_name] = (foreign_table,
                                                                alias_child,
                                                                column_key)
                            else:
                                alias_child = relate_with_foreign[
                                    foreign_table.core_name][1]

                            column = getattr(foreign_table, new_key)
                            if isinstance(column, CoreColumnParent):
                                column = getattr(alias_child, new_key)
                            columns.add(column.label(key))

        relate_with_father = False
        parent = CORE_TYPES[core_name]['parent']
        alias_parent = aliased(Core)
        parent_possible_names = getattr(parent, 'core_possible_names', None)
        if parent is not None and attributes:
            parent_possible_pattern = getattr(parent, 'core_possible_pattern',
                                              None)
            for key in attributes.keys():
                if is_nonstr_iter(key):
                    parent_core_name, parent_key, label_name = key
                    if parent_core_name == parent.core_name:
                        attributes.pop(
                            key, None)  # Dont need this attribute anymore
                        relate_with_father = True

                        column = getattr(parent, parent_key)
                        if isinstance(column, CoreColumnParent):
                            column = getattr(alias_parent, parent_key)
                        columns.add(column.label(label_name))

                elif hasattr(parent, key):
                    attributes.pop(key,
                                   None)  # Dont need this attribute anymore
                    relate_with_father = True

                    column = getattr(parent, key)
                    if isinstance(column, CoreColumnParent):
                        column = getattr(alias_parent, key)
                    columns.add(column)

                elif parent_possible_pattern and key.startswith(
                        parent_possible_pattern):
                    new_key = key.split(parent_possible_pattern, 1)[1]

                    if hasattr(parent, new_key):
                        attributes.pop(
                            key, None)  # Dont need this attribute anymore
                        relate_with_father = True

                        column = getattr(parent, new_key)
                        if isinstance(column, CoreColumnParent):
                            column = getattr(alias_parent, new_key)
                        columns.add(column.label(key))

        if attributes:
            childs_names = [
                t.core_name for t in CORE_TYPES[core_name]['childs']
            ]
            for key in attributes.keys():
                if key in childs_names:
                    continue

                elif parent and (key == parent.core_name or
                                 (parent_possible_names
                                  and key in parent_possible_names)):
                    columns.add(
                        getattr(alias_parent, 'id').label('_parent_id_core'))
                    relate_with_father = True
                    continue

                raise ValueError('Attribute %s is not a child of %s' %
                                 (key, core_name))
            columns.add(Core.id)

        queries = []
        if filters:
            filters = deepcopy(filters)
            if core_name in filters:
                for key, values in filters.pop(core_name).items():
                    column = getattr(table, key)
                    if isinstance(column, CoreColumnParent):
                        column = getattr(Core, key)

                    query_filter = create_filter_by(column, values)
                    if query_filter is not None:
                        queries.append(query_filter)

            core_foreign = getattr(table, 'core_foreign_key', None)
            if core_foreign is not None:
                column_key, foreign_column = core_foreign
                foreign_name = foreign_column.table.name
                if foreign_name.startswith('core_'):
                    foreign_name = foreign_name.split('core_', 1)[1]

                if foreign_name in filters:
                    if foreign_name in relate_with_foreign:
                        foreign_table, aliased_foreign, column_key = relate_with_foreign[
                            foreign_name]
                    else:
                        foreign_table = CORE_TYPES[foreign_name]['table']
                        aliased_foreign = aliased(Core)
                        relate_with_foreign[foreign_name] = (foreign_table,
                                                             aliased_foreign,
                                                             column_key)

                    for key, values in filters.pop(foreign_name).items():
                        column = getattr(foreign_table, key)
                        if isinstance(column, CoreColumnParent):
                            column = getattr(aliased_foreign, key)

                        query_filter = create_filter_by(column, values)
                        if query_filter is not None:
                            queries.append(query_filter)

            cores_ids = set()
            looked_cores = False
            for child_core_name, values in filters.items():
                if child_core_name in relate_with_child:
                    child, alias_child = relate_with_child[child_core_name]

                    child_query = self.session.query(alias_child.parent_id)
                    for key, values in filters[child_core_name].items():
                        column = getattr(child, key)
                        if isinstance(column, CoreColumnParent):
                            column = getattr(alias_child, key)
                        if not is_nonstr_iter(values):
                            child_query = child_query.filter(column == values)
                        else:
                            values = set(values)
                            child_query = child_query.filter(
                                maybe_with_none(column, values))

                    if active is not None:
                        child_query = (child_query.filter(
                            alias_child.id == child.id_core).filter(
                                get_active_filter(alias_child, active)))

                    cores_ids.update(q.parent_id for q in child_query.all())
                    looked_cores = True

                else:
                    # Look in childs
                    child_found = False
                    for child in CORE_TYPES[core_name]['childs']:
                        if child.core_name == child_core_name:
                            child_found = True
                            alias_child = aliased(Core)
                            relate_with_child[child_core_name] = (child,
                                                                  alias_child)

                            for key, values in filters.pop(
                                    child_core_name).items():
                                column = getattr(child, key)
                                if isinstance(column, CoreColumnParent):
                                    column = getattr(alias_child, key)

                                query_filter = create_filter_by(column, values)
                                if query_filter is not None:
                                    queries.append(query_filter)
                    if child_found:
                        continue

                    # Look in branches
                    branch_found = False
                    for branch in CORE_TYPES[core_name]['branches']:
                        if branch.core_name == child_core_name:
                            branch_found = True
                            branches_tables[branch] = None
                            for key, values in filters.pop(
                                    child_core_name).items():
                                column = getattr(branch, key)

                                query_filter = create_filter_by(column, values)
                                if query_filter is not None:
                                    queries.append(query_filter)
                    if branch_found:
                        continue

                    # Look parent
                    parent = CORE_TYPES[core_name]['parent']
                    if parent and parent.core_name == child_core_name:
                        if not relate_with_father:
                            alias_parent = aliased(Core)
                        relate_with_father = True

                        for key, values in filters.pop(
                                child_core_name).items():
                            column = getattr(parent, key)
                            if isinstance(column, CoreColumnParent):
                                column = getattr(alias_parent, key)

                            query_filter = create_filter_by(column, values)
                            if query_filter is not None:
                                queries.append(query_filter)
                        continue

                    raise ValueError('Invalid filter %s for core %s' %
                                     (child_core_name, core_name))

            if cores_ids:
                queries.append(maybe_with_none(table.id_core, cores_ids))
            elif looked_cores:
                # Pagination for main query
                if with_pagination:
                    return CorePagination(page=1,
                                          limit_per_page=limit_per_page,
                                          last_page=1,
                                          number_of_results=0)
                elif only_one:
                    return None
                else:
                    return []

        query = self.session.query(*columns)

        if relate_with_child or branches_tables:
            query = query.select_from(Core)
            for child, alias_child in relate_with_child.values():
                child_queries = [
                    alias_child.type == child.core_name,
                    alias_child.parent_id == Core.id
                ]

                if active is not None:
                    child_queries.append(get_active_filter(
                        alias_child, active))

                query = query.outerjoin(alias_child, and_(*child_queries))

                child_queries = [child.id_core == alias_child.id]
                #if hasattr(child, 'core_on_child_relation'):
                #    option = child.core_on_child_relation
                #    child_queries.append(getattr(child, option[0], option[1]))
                query = query.outerjoin(child, and_(*child_queries))

            for branch in branches_tables.keys():
                query = query.outerjoin(branch, branch.id_core == Core.id)

        if queries:
            query = query.filter(and_(*queries))

        if relate_with_foreign:
            for foreign_table, aliased_foreign, column_key in relate_with_foreign.values(
            ):
                query = query.filter(
                    aliased_foreign.id == getattr(table, column_key))

                if active is not None:
                    query = query.filter(
                        get_active_filter(aliased_foreign, active))

        if relate_with_father:
            query = (query.filter(parent.id_core == alias_parent.id).filter(
                alias_parent.type == table_type(parent)).filter(
                    Core.parent_id == alias_parent.id))
            if active is not None:
                query = query.filter(get_active_filter(alias_parent, active))

        if table is not Core:
            query = query.filter(table.id_core == Core.id).filter(
                Core.type == table_type(table))
        if active is not None:
            query = query.filter(get_active_filter(Core, active))

        # Set order by
        order_by = create_order_by(table, order_by)
        if order_by is not None:
            if is_nonstr_iter(order_by):
                order_by = [ob for ob in order_by if ob is not None] or None
                if order_by:
                    query = query.order_by(*order_by)
            else:
                query = query.order_by(order_by)
        if order_by is None and not only_one:
            query = query.order_by(table.id_core)

        # Pagination for main query
        if with_pagination:
            number_of_results = (query.with_entities(
                func.count(Core.id.distinct())).first()[0])

            last_page = int(ceil(
                number_of_results / float(limit_per_page))) or 1
            if page > last_page:
                page = last_page
            end_slice = page * limit_per_page
            start_slice = end_slice - limit_per_page

        # Make sure if unique
        query = query.group_by(Core.id)

        if with_pagination:
            result = CorePagination(page, limit_per_page, last_page,
                                    number_of_results)
            result.extend(query.slice(start_slice, end_slice).all())
        elif only_one:
            result = query.first()
        else:
            result = query.all()

        if not attributes or not result:
            return result

        if only_one:
            result = [result]

        labels = set(result[0]._labels)
        labels.update(attributes.keys())
        labels = tuple(labels)

        references = {}
        parent_ids_reference = MissingList()
        for value in result:
            value._labels = labels
            if hasattr(value, '_parent_id_core'):
                parent_ids_reference[value._parent_id_core].append(value)
            references[value.id] = value
            for key in attributes.keys():
                if parent and (key == parent.core_name or
                               (parent_possible_names
                                and key in parent_possible_names)):
                    setattr(value, key, None)
                else:
                    setattr(value, key, [])

        for key, key_attributes in attributes.items():
            key_filters = deepcopy(filters)

            if parent and (key == parent.core_name or
                           (parent_possible_names
                            and key in parent_possible_names)):
                key_filters = {
                    parent.core_name: {
                        'id_core': parent_ids_reference.keys()
                    }
                }
                key_attributes['id_core'] = None
                for value in self.get_cores(parent.core_name,
                                            key_attributes,
                                            active=active,
                                            filters=key_filters):
                    for child_value in parent_ids_reference[value.id_core]:
                        setattr(child_value, key, value)
            else:
                if key_filters:
                    key_parents_ids = references.keys()
                    if key in key_filters and 'parent_id' in key_filters[key]:
                        key_parents_ids = set(key_parents_ids)
                        if not is_nonstr_iter(key_filters[key]['parent_id']):
                            key_parents_ids.add(key_filters[key]['parent_id'])
                        else:
                            key_parents_ids.update(
                                key_filters[key]['parent_id'])

                    key_filters[key] = {'parent_id': key_parents_ids}
                else:
                    key_filters = {key: {'parent_id': references.keys()}}

                key_attributes['parent_id'] = None
                for value in self.get_cores(key,
                                            key_attributes,
                                            active=active,
                                            filters=key_filters):
                    getattr(references[value.parent_id], key).append(value)

        if only_one:
            return result[0]
        else:
            return result
Exemple #26
0
def format_crontab_options(**kwargs):
    for key in kwargs.keys():
        if key not in DATES_RANGES:
            raise ValueError('Invalid cron key %s' % key)

    options = {}
    for key, (start_range, end_range) in DATES_RANGES.items():
        values = maybe_set(kwargs.get(key))
        if values is None:
            continue
        elif '*' in values:
            continue

        key_options = set()
        for value in values:
            value = to_string(value)

            if key == 'day' and value.lower() == 'l':
                options['last_day_of_month'] = True
                continue

            int_values = set()
            ignore_options_add = False

            if key == 'weekday' and value.lower().endswith('l'):
                weekday = maybe_integer(value[0])
                if weekday is None:
                    message = 'Invalid %s integer on "%s"' \
                              % (key, value)
                    raise ValueError(message)
                int_values.add(weekday)
                options['last_weekday_of_month'] = weekday
                ignore_options_add = True

            elif value.isnumeric():
                int_values.add(int(value))

            elif value == '?':
                now = NOW()
                if key == 'weekday':
                    int_values.add(now.weekday())
                else:
                    int_values.add(getattr(now, key))

            elif '/' in value:
                range_int, interval = value.split('/', 1)

                interval = maybe_integer(interval)
                if interval is None or interval < 1:
                    message = 'Invalid %s interval for "%s"' % (key, value)
                    raise ValueError(message)

                if range_int == '*':
                    start = start_range
                    end = end_range
                elif '-' in range_int:
                    start, end = range_int.split('-', 1)
                    start = maybe_integer(start)
                    end = maybe_integer(end)
                    if start is None or end is None:
                        message = 'Invalid %s integer on "%s"' % (key, value)
                        raise ValueError(message)
                else:
                    message = 'Invalid %s format "%s"' % (key, value)
                    raise ValueError(message)

                int_values.update(range(start, end + 1, interval))

            elif ',' in value:
                for int_value in value.split(','):
                    int_value = maybe_integer(int_value)
                    if int_value is None:
                        message = 'Invalid %s integer on "%s"' % (key, value)
                        raise ValueError(message)
                    int_values.add(int_value)

            elif '-' in value:
                start, end = value.split('-', 1)
                start = maybe_integer(start)
                end = maybe_integer(end)
                if start is None or end is None:
                    message = 'Invalid %s integer on "%s"' % (key, value)
                    raise ValueError(message)
                int_values.update(range(start, end + 1))

            else:
                message = 'Invalid %s integer "%s"' % (key, value)
                raise ValueError(message)

            for int_value in int_values:
                if start_range > int_value or int_value > end_range:
                    message = (
                        'Invalid %s "%s". Start: %s End: %s'
                        % (key, value, start_range, end_range))
                    raise ValueError(message)

            if not ignore_options_add:
                key_options.update(int_values)

        if key_options:
            options[key] = sorted(key_options)

    return options