コード例 #1
0
 def _validate_vmci(self, endpoint):
     iface, port = self._validate_port_pair(
         endpoint, "interface", wildcard_ok=self.side is self.Side.BIND)
     if iface == "*":
         if self.side is not self.Side.BIND:
             raise V.ValidationError(
                 "wildcard interface not valid in this context")
     elif not iface.isdigit():
         raise V.ValidationError(f"interface {iface!r} must be an integer")
コード例 #2
0
 def validate(self, value, adapt=True):
     if not value:
         raise v.ValidationError('No email')
     addr = parseaddr(value)[1]
     hostname = addr[addr.find('@') + 1:]
     try:
         dns.resolver.query(hostname, 'MX')
     except dns.exception.DNSException:
         raise v.ValidationError('No MX record for %s' % hostname)
     return value
コード例 #3
0
 def _validate_tcp_endpoint(self, endpoint, wildcard_ok=False):
     host, port = self._validate_port_pair(endpoint,
                                           "host",
                                           wildcard_ok=wildcard_ok)
     if host == "*":
         if not wildcard_ok:
             raise V.ValidationError(
                 "wildcard host not valid in this context")
     elif not DNS_OR_IP_REGEX.match(host):
         raise V.ValidationError(f"host {host!r} does not look like a "
                                 "valid hostname nor an IP address")
コード例 #4
0
 def _validate_port_pair(self, endpoint, rest_name, wildcard_ok=False):
     rest, sep, port = endpoint.rpartition(":")
     if not sep:
         raise V.ValidationError(f"endpoint {endpoint} does not follow the "
                                 f"format of {rest_name}:port")
     if port == "*":
         if not wildcard_ok:
             # XXX: what context?
             raise V.ValidationError(
                 "wildcard port not valid in this context")
     elif not port.isdigit():
         raise V.ValidationError(f"port {port!r} must be an integer")
     return rest, port
コード例 #5
0
 def _validate_pgm(self, endpoint):
     rest, port = self._validate_port_pair(endpoint, "interface;multicast")
     iface, sep, multicast = rest.rpartition(";")
     if not sep:
         raise V.ValidationError("missing semicolon separator")
     # XXX: is it worth validating iface?
     try:
         multicast = ipaddress.IPv4Address(multicast)
     except ipaddress.AddressValueError as e:
         # XXX: what address is causing the error?
         raise V.ValidationError(str(e)) from None
     if not multicast.is_multicast:
         raise V.ValidationError(f"{str(multicast)!r} is not a multicast "
                                 "address")
コード例 #6
0
 def validate(self, value, adapt=True):
     super().validate(value, adapt=adapt)
     transports = {
         "tcp": self._validate_tcp,
         "ipc": self._validate_ipc,
         "inproc": self._validate_inproc,
         "pgm": self._validate_pgm,
         "epgm": self._validate_pgm,
         "vmci": self._validate_vmci,
     }
     transport, sep, endpoint = value.partition("://")
     if not sep:
         raise V.ValidationError("missing transport://")
     if transport not in transports:
         raise V.ValidationError(f"invalid transport {transport!r}")
     transports[transport](endpoint)
     return value
コード例 #7
0
    def _validate_tcp(self, endpoint):
        source_endpoint, sep, endpoint = endpoint.rpartition(";")
        if sep:
            if self.side is not self.Side.CONNECT:
                raise V.ValidationError(
                    "must not specify source in bindable endpoint")
            self._validate_tcp_endpoint(source_endpoint, wildcard_ok=True)

        self._validate_tcp_endpoint(endpoint,
                                    wildcard_ok=self.side is self.Side.BIND)
コード例 #8
0
 def _validate_inproc(self, endpoint):
     if not endpoint:
         raise V.ValidationError("inproc name must not be empty")
     if len(endpoint) > 256:
         raise V.ValidationError("inproc name must not be longer than 256 "
                                 "characters")
コード例 #9
0
 def _validate_ipc(self, endpoint):
     if "\0" in endpoint:
         raise V.ValidationError("paths must not contain NUL bytes")
コード例 #10
0
    def __call__(self, validated):

        # Selects
        # -------

        # need to add all the groupbys
        for g in self._groupby:
            found = False
            for s in self._selects:
                #                         |v|       | v         |
                # matches "extract(..) as day" and "gph.productid as product"
                if s.startswith(g) or s.endswith(g):
                    found = True
                    break
            if not found:
                self._selects[g] = (g, None, None, None)

        if self._aggs and set(self._aggs) & set(self._where.keys()) and self._groupby:

            # --------------
            # New Main Query
            # --------------
            With = Query()

            # select all the columns (by as)
            [With.select(col) for col in self._selects.keys()]
            With.into(True)
            With.tables("from _data")
            [With.where(col, *self._where.pop(col)) for col in self._aggs if col in self._where]

            # ~~groupby~~ no need
            if self._sortby:
                With.sortby(*self._sortby)
                # need to select sorts in next query
                for sort in self._sortby:
                    if sort not in self._selects.keys():
                        self._selects[sort] = (sort, None, None, None)
                self._sortby = []
            # only need to pop these when sorting methods present
            limit = validated.pop('limit') if 'limit' in validated else None
            offset = validated.pop('offset') if 'offset' in validated else None

            # ----------------------
            # Change Self Properties
            # ----------------------
            With._with = self._with
            self._with = []

            self.into(False)
            # remove sorting from **this** query

            # ---------
            # With Self
            # ---------
            self._aggs = []
            With.with_(self(validated), as_="_data")

            validated['limit'] = limit
            validated['offset'] = offset
            return With(validated)

        elif str(validated.get('limit', '')).endswith('%'):
            """
            ### Making the with query below

            ```psql
            with _limited as (select total from orders where total > 10) 
            select total from _limited order by total asc limit (select round(count(*)*.1) from _limited)
            ```
            """
            # column, agg, as, distinct
            # only AGG: peice 3: select sum(column) from _ll
            _l = Query()
            _l._selects = dict(map(lambda d: (d[0], (d[1][2] or d[1][0], d[1][1], d[1][2], None)), self._selects.items()))
            _l.tables("from _ll")

            # only ORDER BY and LIMIT: peice 2
            _ll = Query()

            # select table.column as as_column
            _ll._selects = dict(map(lambda d: (d[0], (d[1][2] or d[1][0], None, None, None)), self._selects.items()))
            _ll.tables("from _l")
            _ll.into(False)
            [_ll.agg(a) for a in self._aggs]
            if self._sortby:
                _ll.sortby(*self._sortby)
                # need to select sorts in next query
                for sort in self._sortby:
                    if sort not in self._selects.keys():
                        self._selects[sort] = sort
                self._sortby = []

            self._selects = dict(map(lambda d: (d[0], (d[1][0], None, d[1][2], d[1][3])), self._selects.items()))
            self._aggs = []
            self.into(False)

            limit = validated.pop('limit')
            _l.with_(self(validated), "_l")
            validated['limit'] = "(select round(count(*)*%s) from _l)" % (float(limit[:-1])/100)
            _l.with_(_ll(validated), "_ll")
            validated.pop('limit')
            return _l(validated)

        else:

            query = self._query

            elements = {}

            # With
            # ----
            elements['with'] = ("with %s "%', '.join(self._with)) if self._with else ""

            # Select
            # ---------------
            # add sortby to select (only needed for DISTINCT)
            if self._sortby:
                for sort in self._sortby:
                    if sort not in self._selects.keys():
                        self._selects[sort] = (sort, None, None, None)

            elements["select"] = ', '.join(map(self._column, 
                                               sorted(self._selects.values(), 
                                                      key=lambda a: (not a[3], a[0]))))
            
            # Into
            # ----
            elements['into'] = "__into__" if self._into else ""

            # Tables
            # ------
            _from = None
            for table in self._tables:
                if table.startswith('from') or table == "":
                    _from = table
            if _from is None:
                raise valideer.ValidationError("Not enough arguments supplied to formulate a tables for query")

            newtables = self._tables[self._tables.index(_from):]
            oldtables = self._tables[:self._tables.index(_from)]
            newtables.extend([t for t in oldtables if not t.startswith('from')])
            self._tables = unique(newtables)
            elements["tables"] = " ".join(self._tables)

            # Group By
            # --------
            elements['groupby'] = (" group by " + ','.join(map(lambda g: ('"%s"'%g) if g == 'group' else g,
                                                               self._groupby))) if self._groupby else ""

            # Sort By
            # -------
            # http://www.postgresql.org/docs/8.1/static/queries-order.html
            #   Each column specification may be followed by an optional ASC or DESC to set the sort direction to ascending or descending. 
            #   ASC order is the default
            elements['sortby'] = (" order by %s %s" % (",".join(self._sortby), validated.get('dir', 'asc'))) if self._sortby else ""

            # Limit
            # -----
            limit = validated.get('limit')

            elements['limit'] = (" limit %s" % validated['limit']) if limit else ""

            # Offset
            # ------
            elements['offset'] = (" offset %s" % validated['offset']) if validated.get('offset') else ""

            # Where
            # -----
            # custom ?where=this|that
            if validated.get('where'):

                # valideer produces the tuple below
                keys, string = validated.pop("where")
                try:
                    self._where.setdefault('_', []).append(string % self._algebra(self._where))
                except KeyError as e:
                    raise valideer.ValidationError("Missing argument `%s` needed in provided where clause" % str(e)[1:-1], str(e)[1:-1])
                [self._where.pop(key) for key in keys if key in self._where]

            wheres = list(itertools.chain(*self._where.values()))
            if self.debug: wheres = sorted(wheres)
            elements['where'] = (" where " + ' and '.join(wheres)) if wheres else ""

            # ----------
            # Format SQL
            # ----------
            try:
                # return (query % elements) % validated
                try:
                    return (query % elements) % validated
                # except ValueError:
                #     return (self.escape.sub('%%', query) % elements) % validated
                except KeyError:
                    validated.update(elements)
                    return ((query % validated) % validated) % validated
            except Exception as e:
                raise# SyntaxError("failed to create query", e)
コード例 #11
0
    def _harvest_validate(self, userkwargs):
        """Validate and Plant user provided arguments
        - Go through and plants the seedlings
          for any user arguments provided.
        - Validate the arguments, cleaning and adapting (valideer wise)
        - Extract negatives "!" arguments
        """
        # the valideer to parse the
        # user arguemnts when watering
        parser = {}

        userkwargs.update(self.network_kwargs)
        # a simple set of original provided argument keys (used in IGNORES)
        original_kwargs = set(
            map(lambda k: k.split('_')[1] if k.find('_') > -1 else k,
                userkwargs.keys()))
        # list of columns that are required from seeds
        requires = []

        # -------------
        # Clean up Aggs
        # -------------
        for key in userkwargs.keys():
            # agg example: "avg_total", "max_tax"
            if key.find('_') > 0:
                agg, base = tuple(key.split('_'))
                if base in userkwargs:
                    if type(userkwargs[base]) is not list:
                        userkwargs[base] = [(None, userkwargs[base])]
                    userkwargs[base].append((agg, userkwargs.pop(key)))
                else:
                    userkwargs[base] = [(agg, userkwargs.pop(key))]

        # -----------------
        # Process Arguments
        # -----------------
        for key, seed in self.arguments.iteritems():
            # --------------
            # Argument Alias
            # --------------
            if seed.get('alias') and key in userkwargs:
                # pop the value form the user kwargs (to change the key later)
                value = userkwargs.pop(
                    key) if key in userkwargs else NotImplemented
                # for duplicate keys
                oldkey = key + ""
                # change the key
                key = seed.get('alias')
                # change the seed
                seed = get(self.arguments, seed.get('alias'))
                # set the new key:value
                if value is not NotImplemented:
                    if key in userkwargs:
                        raise valideer.ValidationError(
                            "Argument alias already specified for `%s` via `%s`"
                            % (oldkey, key), oldkey)
                    userkwargs[key] = value

            # can provide multiple arguments
            if key.endswith('[]'):
                multi = True
                key = key[:-2]
            else:
                multi = False

            # get value(s) from user
            if key in userkwargs:
                value = userkwargs.pop(key)
            elif seed.get('copy'):
                value = userkwargs.get(seed.get('copy'))
            else:
                value = seed.get('default')

            # no argument provided, lets continue)
            if value is None or value == []:
                if seed.get('required'):
                    raise valideer.ValidationError(
                        "missing required property: %s" % key, key)
                else:
                    continue

            # add requires
            requires.extend(array(get(seed, 'requires', [])))

            # -----------
            # Inheritance
            # -----------
            # not permited from arguements yet. would need to happen above the ""PROCESS ARGUMENT"" block
            # self._inherit(*array(get(seed, 'inherit', [])))

            if type(value) is list and type(value[0]) is tuple:
                # complex
                for v in value:
                    ud, pd = self._harvest_args(key, seed, v, multi)
                    userkwargs.update(ud)
                    parser.update(pd)
            else:
                ud, pd = self._harvest_args(key, seed, value, multi)
                userkwargs.update(ud)
                parser.update(pd)

        # ------------
        # Ignored Keys
        # ------------
        for seed in self.seeds:
            ignores = set(array(get(seed, 'ignore')))
            if ignores:
                if ignores & original_kwargs:
                    if not get(seed, 'silent'):
                        additionals = ignores & original_kwargs
                        raise valideer.ValidationError(
                            "additional properties: %s" %
                            ",".join(additionals), additionals)
                [userkwargs.pop(key) for key in ignores if key in userkwargs]

        # -------------------------
        # Custom Operators (part 1)
        # -------------------------
        operators = {}
        for key, value in userkwargs.items():
            rk = key
            agg = None
            if key.find('_') > -1:
                agg, rk = tuple(key.split('_'))
            seed = self.arguments.get(rk, self.arguments.get(rk + '[]'))
            if seed:
                if type(value) is list:
                    operators[key] = []
                    # need to remove the operator for validating
                    new_values = []
                    for v in value:
                        operator, v = self._operator(
                            v,
                            *seed.get('column', "").rsplit("::", 1))
                        new_values.append(v)
                        operators[key].append((agg,
                                               operator) if agg else operator)
                    userkwargs[key] = new_values
                else:
                    operator, value = self._operator(
                        value,
                        *seed.get('column', "").rsplit("::", 1))
                    operators[key] = (agg, operator) if agg else operator
                    userkwargs[key] = value

        # -----------------
        # Plant Sort Method
        # -----------------
        if 'sortby' in userkwargs:
            seed = self.arguments.get(
                userkwargs['sortby'].lower(),
                self.arguments.get(userkwargs['sortby'].lower() + '[]'))
            if seed:
                seed['id'] = str(userkwargs['sortby'].lower())

        for r in set(requires):
            if userkwargs.get(r) is None:
                raise valideer.ValidationError(
                    "required property not set: %s" % r, r)

        # --------
        # Validate
        # --------
        parser = valideer.parse(parser, additional_properties=False)
        validated = parser.validate(userkwargs, adapt=self.navigator.adapter())
        validated.update(self.network_kwargs)
        #   operators                   validated
        # --------------------------- | --------------------------------
        # {                           {
        #   "type": ["!", "!"],         "type": ['a', 'b'],
        #   "total": "<",               "total": "50",
        #   "tax": ("avg, ">"),         "tax": "1",
        #   "time": None                "time": "2014"
        # }                           }
        return operators, validated
コード例 #12
0
    def _harvest_args(self, key, seed, value, multi):
        agg = value[0] if type(value) is tuple else None
        value = value[1] if type(value) is tuple else value

        # adapt to proper variable types
        # if value and multi and type(value) not in (list, tuple):
        #     value = [str(value).lower()]
        # if type(value) in (int, long, float, bool):
        #     value = str(value).lower()
        if multi and type(value) not in (list, tuple):
            multi = False

        # plant this arguments seed
        key = key if not agg else ("%s_%s" % (agg, key))
        seed["id"] = key
        self.plant(seed)

        # set the value
        # userkwargs[key] = value

        # add to the parser
        # parse key "+" if required
        pkey = ("+" + key) if seed.get('required') else key

        # validation methods
        # 1) choose
        if 'options' in seed:
            replace_with = []
            if seed.get('*') and value in ('*', 'all'):
                map(self.plant, seed['options'].values())

            else:
                for _value in array(value):
                    found = False
                    for pattern, _seed in seed['options'].iteritems():
                        if re.match(pattern, _value):
                            found = True

                            # replace the value provided
                            replace_with.append(_seed.get('value', _value))

                            # add the seed
                            self.plant(_seed)

                            # add the parser, though we have already parsed properly
                            break

                    # no seed found: invalid
                    if not found:
                        raise valideer.ValidationError("Invalid value", key)

            if type(value) in (list, tuple):
                value = replace_with
                validate = valideer.HomogeneousSequence(valideer.String())
            else:
                value = replace_with[0] if replace_with else ""
                validate = valideer.String()

        elif 'validator' in seed:
            validator = seed.get('validator')
            if validator == 'currency':
                # somehow change currency to respect stores... (future)
                validator = "float"
            validate = valideer.HomogeneousSequence(
                validator) if multi else validator

        else:
            raise EnvironmentError("Missing validation method for " + key)

        return {key: value}, {pkey: validate}