Ejemplo n.º 1
0
def safe_join(base, *paths):
    """
    Joins one or more path components to the base path component intelligently.
    Returns a normalized, absolute version of the final path.

    The final path must be located inside of the base path component (otherwise
    a ValueError is raised).
    """
    base = force_text(base)
    paths = [force_text(p) for p in paths]
    final_path = abspathu(join(base, *paths))
    base_path = abspathu(base)
    # Ensure final_path starts with base_path (using normcase to ensure we
    # don't false-negative on case insensitive operating systems like Windows),
    # further, one of the following conditions must be true:
    #  a) The next character is the path separator (to prevent conditions like
    #     safe_join("/dir", "/../d"))
    #  b) The final path must be the same as the base path.
    #  c) The base path must be the most root path (meaning either "/" or "C:\\")
    if (not normcase(final_path).startswith(normcase(base_path + sep))
            and normcase(final_path) != normcase(base_path)
            and dirname(normcase(base_path)) != normcase(base_path)):
        raise SuspiciousFileOperation(
            'The joined path ({}) is located outside of the base path '
            'component ({})'.format(final_path, base_path))
    return final_path
Ejemplo n.º 2
0
def popen_wrapper(args, os_err_exc_type=CommandError, stdout_encoding='utf-8'):
    """
    Friendly wrapper around Popen.

    Returns stdout output, stderr output and OS status code.
    """
    try:
        p = Popen(args,
                  shell=False,
                  stdout=PIPE,
                  stderr=PIPE,
                  close_fds=os.name != 'nt')
    except OSError as e:
        strerror = force_text(e.strerror,
                              DEFAULT_LOCALE_ENCODING,
                              strings_only=True)
        six.reraise(
            os_err_exc_type,
            os_err_exc_type('Error executing %s: %s' % (args[0], strerror)),
            sys.exc_info()[2])
    output, errors = p.communicate()
    return (force_text(output,
                       stdout_encoding,
                       strings_only=True,
                       errors='strict'),
            force_text(errors,
                       DEFAULT_LOCALE_ENCODING,
                       strings_only=True,
                       errors='replace'), p.returncode)
Ejemplo n.º 3
0
 def get_dump_object(self, obj):
     data = OrderedDict([('model', force_text(obj._meta))])
     if not self.use_natural_primary_keys or not hasattr(
             obj, 'natural_key'):
         data["pk"] = force_text(obj._get_pk_val(), strings_only=True)
     data['fields'] = self._current
     return data
Ejemplo n.º 4
0
 def format(self, formatstr):
     pieces = []
     for i, piece in enumerate(re_formatchars.split(force_text(formatstr))):
         if i % 2:
             if type(self.data) is datetime.date and hasattr(
                     TimeFormat, piece):
                 raise TypeError(
                     "The format for date objects may not contain "
                     "time-related format specifiers (found '%s')." % piece)
             pieces.append(force_text(getattr(self, piece)()))
         elif piece:
             pieces.append(re_escaped.sub(r'\1', piece))
     return ''.join(pieces)
Ejemplo n.º 5
0
def wrap(text, width):
    """
    A word-wrap function that preserves existing line breaks. Expects that
    existing line breaks are posix newlines.

    All white space is preserved except added line breaks consume the space on
    which they break the line.

    Long words are not wrapped, so the output text may have lines longer than
    ``width``.
    """
    text = force_text(text)

    def _generator():
        for line in text.splitlines(True):  # True keeps trailing linebreaks
            max_width = min((line.endswith('\n') and width + 1 or width),
                            width)
            while len(line) > max_width:
                space = line[:max_width + 1].rfind(' ') + 1
                if space == 0:
                    space = line.find(' ') + 1
                    if space == 0:
                        yield line
                        line = ''
                        break
                yield '%s\n' % line[:space - 1]
                line = line[space:]
                max_width = min((line.endswith('\n') and width + 1 or width),
                                width)
            if line:
                yield line

    return ''.join(_generator())
Ejemplo n.º 6
0
 def __init__(self,
              app_label,
              name,
              fields,
              options=None,
              bases=None,
              managers=None):
     self.app_label = app_label
     self.name = force_text(name)
     self.fields = fields
     self.options = options or {}
     self.bases = bases or (models.Model, )
     self.managers = managers or []
     # Sanity-check that fields is NOT a dict. It must be ordered.
     if isinstance(self.fields, dict):
         raise ValueError(
             "ModelState.fields cannot be a dict - it must be a list of 2-tuples."
         )
     for name, field in fields:
         # Sanity-check that fields are NOT already bound to a model.
         if hasattr(field, 'model'):
             raise ValueError(
                 'ModelState.fields cannot be bound to a model - "%s" is.' %
                 name)
         # Sanity-check that relation fields are NOT referring to a model class.
         if field.is_relation and hasattr(field.related_model, '_meta'):
             raise ValueError(
                 'ModelState.fields cannot refer to a model class - "%s.to" does. '
                 'Use a string reference instead.' % name)
         if field.many_to_many and hasattr(field.remote_field.through,
                                           '_meta'):
             raise ValueError(
                 'ModelState.fields cannot refer to a model class - "%s.through" does. '
                 'Use a string reference instead.' % name)
Ejemplo n.º 7
0
    def get_prep_value(self, value):
        value = super(HStoreField, self).get_prep_value(value)

        if isinstance(value, dict):
            prep_value = {}
            for key, val in value.items():
                key = force_text(key)
                if val is not None:
                    val = force_text(val)
                prep_value[key] = val
            value = prep_value

        if isinstance(value, list):
            value = [force_text(item) for item in value]

        return value
Ejemplo n.º 8
0
 def __call__(self, value):
     """
     Validates that the input matches the regular expression
     if inverse_match is False, otherwise raises ValidationError.
     """
     if not (self.inverse_match is not bool(
             self.regex.search(force_text(value)))):
         raise ValidationError(self.message, code=self.code)
Ejemplo n.º 9
0
def pgettext(context, message):
    msg_with_ctxt = "%s%s%s" % (context, CONTEXT_SEPARATOR, message)
    result = ugettext(msg_with_ctxt)
    if CONTEXT_SEPARATOR in result:
        # Translation not found
        # force unicode, because lazy version expects unicode
        result = force_text(message)
    return result
Ejemplo n.º 10
0
 def m2m_convert(value):
     if hasattr(value, '__iter__') and not isinstance(
             value, six.text_type):
         return model._default_manager.db_manager(
             db).get_by_natural_key(*value).pk
     else:
         return force_text(model._meta.pk.to_python(value),
                           strings_only=True)
Ejemplo n.º 11
0
 def verbose_name_raw(self):
     """
     There are a few places where the untranslated verbose name is needed
     (so that we get the same value regardless of currently active
     locale).
     """
     with override(None):
         return force_text(self.verbose_name)
Ejemplo n.º 12
0
def to_unicode(s):
    """
    Convert strings to Unicode objects (and return all other data types
    unchanged).
    """
    if isinstance(s, six.string_types):
        return force_text(s)
    return s
Ejemplo n.º 13
0
def urlquote_plus(url, safe=''):
    """
    A version of Python's urllib.quote_plus() function that can operate on
    unicode strings. The url is first UTF-8 encoded before quoting. The
    returned string can safely be used as part of an argument to a subsequent
    iri_to_uri() call without double-quoting occurring.
    """
    return force_text(quote_plus(force_str(url), force_str(safe)))
Ejemplo n.º 14
0
 def get_directory_name(self):
     warnings.warn(
         'FileField now delegates file name and folder processing to the '
         'storage. get_directory_name() will be removed in Django 2.0.',
         RemovedInDjango20Warning,
         stacklevel=2)
     return os.path.normpath(
         force_text(datetime.datetime.now().strftime(
             force_str(self.upload_to))))
Ejemplo n.º 15
0
 def get_table_description(self, cursor, table_name):
     "Returns a description of the table, with the DB-API cursor.description interface."
     # As cursor.description does not return reliably the nullable property,
     # we have to query the information_schema (#7783)
     cursor.execute(
         """
         SELECT column_name, is_nullable, column_default
         FROM information_schema.columns
         WHERE table_name = %s""", [table_name])
     field_map = {line[0]: line[1:] for line in cursor.fetchall()}
     cursor.execute("SELECT * FROM %s LIMIT 1" %
                    self.connection.ops.quote_name(table_name))
     return [
         FieldInfo(*((force_text(line[0]), ) + line[1:6] +
                     (field_map[force_text(line[0])][0] == 'YES',
                      field_map[force_text(line[0])][1])))
         for line in cursor.description
     ]
Ejemplo n.º 16
0
 def __iter__(self):
     if hasattr(self, 'error_dict'):
         for field, errors in self.error_dict.items():
             yield field, list(ValidationError(errors))
     else:
         for error in self.error_list:
             message = error.message
             if error.params:
                 message %= error.params
             yield force_text(message)
Ejemplo n.º 17
0
def get_valid_filename(s):
    """
    Returns the given string converted to a string that can be used for a clean
    filename. Specifically, leading and trailing spaces are removed; other
    spaces are converted to underscores; and anything that is not a unicode
    alphanumeric, dash, underscore, or dot, is removed.
    >>> get_valid_filename("john's portrait in 2004.jpg")
    'johns_portrait_in_2004.jpg'
    """
    s = force_text(s).strip().replace(' ', '_')
    return re.sub(r'(?u)[^-\w.]', '', s)
Ejemplo n.º 18
0
def call_command(command_name, *args, **options):
    """
    Calls the given command, with the given options and args/kwargs.

    This is the primary API you should use for calling specific commands.

    `name` may be a string or a command object. Using a string is preferred
    unless the command object is required for further processing or testing.

    Some examples:
        call_command('migrate')
        call_command('shell', plain=True)
        call_command('sqlmigrate', 'myapp')

        from arouse._dj.core.management.commands import flush
        cmd = flush.Command()
        call_command(cmd, verbosity=0, interactive=False)
        # Do something with cmd ...
    """
    if isinstance(command_name, BaseCommand):
        # Command object passed in.
        command = command_name
        command_name = command.__class__.__module__.split('.')[-1]
    else:
        # Load the command object by name.
        try:
            app_name = get_commands()[command_name]
        except KeyError:
            raise CommandError("Unknown command: %r" % command_name)

        if isinstance(app_name, BaseCommand):
            # If the command is already loaded, use it directly.
            command = app_name
        else:
            command = load_command_class(app_name, command_name)

    # Simulate argument parsing to get the option defaults (see #10080 for details).
    parser = command.create_parser('', command_name)
    # Use the `dest` option name from the parser option
    opt_mapping = {
        sorted(s_opt.option_strings)[0].lstrip('-').replace('-', '_'): s_opt.dest
        for s_opt in parser._actions if s_opt.option_strings
    }
    arg_options = {opt_mapping.get(key, key): value for key, value in options.items()}
    defaults = parser.parse_args(args=[force_text(a) for a in args])
    defaults = dict(defaults._get_kwargs(), **arg_options)
    # Move positional args out of options to mimic legacy optparse
    args = defaults.pop('args', ())
    if 'skip_checks' not in options:
        defaults['skip_checks'] = True

    return command.execute(*args, **defaults)
Ejemplo n.º 19
0
def get_text_list(list_, last_word=ugettext_lazy('or')):
    """
    >>> get_text_list(['a', 'b', 'c', 'd'])
    'a, b, c or d'
    >>> get_text_list(['a', 'b', 'c'], 'and')
    'a, b and c'
    >>> get_text_list(['a', 'b'], 'and')
    'a and b'
    >>> get_text_list(['a'])
    'a'
    >>> get_text_list([])
    ''
    """
    if len(list_) == 0:
        return ''
    if len(list_) == 1:
        return force_text(list_[0])
    return '%s %s %s' % (
        # Translators: This string is used as a separator between list elements
        _(', ').join(force_text(i) for i in list_[:-1]),
        force_text(last_word),
        force_text(list_[-1]))
Ejemplo n.º 20
0
 def add_truncation_text(self, text, truncate=None):
     if truncate is None:
         truncate = pgettext('String to return when truncating text',
                             '%(truncated_text)s...')
     truncate = force_text(truncate)
     if '%(truncated_text)s' in truncate:
         return truncate % {'truncated_text': text}
     # The truncation text didn't contain the %(truncated_text)s string
     # replacement argument so just append it to the text.
     if text.endswith(truncate):
         # But don't append the truncation text if the current text already
         # ends in this.
         return text
     return '%s%s' % (text, truncate)
Ejemplo n.º 21
0
 def generate_filename(self, instance, filename):
     """
     Apply (if callable) or prepend (if a string) upload_to to the filename,
     then delegate further processing of the name to the storage backend.
     Until the storage layer, all file paths are expected to be Unix style
     (with forward slashes).
     """
     if callable(self.upload_to):
         filename = self.upload_to(instance, filename)
     else:
         dirname = force_text(datetime.datetime.now().strftime(
             force_str(self.upload_to)))
         filename = posixpath.join(dirname, filename)
     return self.storage.generate_filename(filename)
Ejemplo n.º 22
0
 def get_table_description(self, cursor, table_name):
     "Returns a description of the table, with the DB-API cursor.description interface."
     self.cache_bust_counter += 1
     cursor.execute("SELECT * FROM {} WHERE ROWNUM < 2 AND {} > 0".format(
         self.connection.ops.quote_name(table_name),
         self.cache_bust_counter))
     description = []
     for desc in cursor.description:
         name = force_text(
             desc[0]
         )  # cx_Oracle always returns a 'str' on both Python 2 and 3
         name = name % {
         }  # cx_Oracle, for some reason, doubles percent signs.
         description.append(FieldInfo(*(name.lower(), ) + desc[1:]))
     return description
Ejemplo n.º 23
0
 def construct_managers(self):
     "Deep-clone the managers using deconstruction"
     # Sort all managers by their creation counter
     sorted_managers = sorted(self.managers,
                              key=lambda v: v[1].creation_counter)
     for mgr_name, manager in sorted_managers:
         mgr_name = force_text(mgr_name)
         as_manager, manager_path, qs_path, args, kwargs = manager.deconstruct(
         )
         if as_manager:
             qs_class = import_string(qs_path)
             yield mgr_name, qs_class.as_manager()
         else:
             manager_class = import_string(manager_path)
             yield mgr_name, manager_class(*args, **kwargs)
Ejemplo n.º 24
0
def slugify(value, allow_unicode=False):
    """
    Convert to ASCII if 'allow_unicode' is False. Convert spaces to hyphens.
    Remove characters that aren't alphanumerics, underscores, or hyphens.
    Convert to lowercase. Also strip leading and trailing whitespace.
    """
    value = force_text(value)
    if allow_unicode:
        value = unicodedata.normalize('NFKC', value)
        value = re.sub('[^\w\s-]', '', value, flags=re.U).strip().lower()
        return mark_safe(re.sub('[-\s]+', '-', value, flags=re.U))
    value = unicodedata.normalize('NFKD',
                                  value).encode('ascii',
                                                'ignore').decode('ascii')
    value = re.sub('[^\w\s-]', '', value).strip().lower()
    return mark_safe(re.sub('[-\s]+', '-', value))
Ejemplo n.º 25
0
def smart_split(text):
    r"""
    Generator that splits a string by spaces, leaving quoted phrases together.
    Supports both single and double quotes, and supports escaping quotes with
    backslashes. In the output, strings will keep their initial and trailing
    quote marks and escaped quotes will remain escaped (the results can then
    be further processed with unescape_string_literal()).

    >>> list(smart_split(r'This is "a person\'s" test.'))
    ['This', 'is', '"a person\\\'s"', 'test.']
    >>> list(smart_split(r"Another 'person\'s' test."))
    ['Another', "'person\\'s'", 'test.']
    >>> list(smart_split(r'A "\"funky\" style" test.'))
    ['A', '"\\"funky\\" style"', 'test.']
    """
    text = force_text(text)
    for bit in smart_split_re.finditer(text):
        yield bit.group(0)
Ejemplo n.º 26
0
    def __call__(self, value):
        value = force_text(value)
        # Check first if the scheme is valid
        scheme = value.split('://')[0].lower()
        if scheme not in self.schemes:
            raise ValidationError(self.message, code=self.code)

        # Then check full URL
        try:
            super(URLValidator, self).__call__(value)
        except ValidationError as e:
            # Trivial case failed. Try for possible IDN domain
            if value:
                try:
                    scheme, netloc, path, query, fragment = urlsplit(value)
                except ValueError:  # for example, "Invalid IPv6 URL"
                    raise ValidationError(self.message, code=self.code)
                try:
                    netloc = netloc.encode('idna').decode(
                        'ascii')  # IDN -> ACE
                except UnicodeError:  # invalid domain part
                    raise e
                url = urlunsplit((scheme, netloc, path, query, fragment))
                super(URLValidator, self).__call__(url)
            else:
                raise
        else:
            # Now verify IPv6 in the netloc part
            host_match = re.search(r'^\[(.+)\](?::\d{2,5})?$',
                                   urlsplit(value).netloc)
            if host_match:
                potential_ip = host_match.groups()[0]
                try:
                    validate_ipv6_address(potential_ip)
                except ValidationError:
                    raise ValidationError(self.message, code=self.code)
            url = value

        # The maximum length of a full host name is 253 characters per RFC 1034
        # section 3.1. It's defined to be 255 bytes or less, but this includes
        # one byte for the length of the name and one byte for the trailing dot
        # that's used to indicate absolute names in DNS.
        if len(urlsplit(value).netloc) > 253:
            raise ValidationError(self.message, code=self.code)
Ejemplo n.º 27
0
def is_safe_url(url, host=None):
    """
    Return ``True`` if the url is a safe redirection (i.e. it doesn't point to
    a different host and uses a safe scheme).

    Always returns ``False`` on an empty url.
    """
    if url is not None:
        url = url.strip()
    if not url:
        return False
    if six.PY2:
        try:
            url = force_text(url)
        except UnicodeDecodeError:
            return False
    # Chrome treats \ completely as / in paths but it could be part of some
    # basic auth credentials so we need to check both URLs.
    return _is_safe_url(url, host) and _is_safe_url(url.replace('\\', '/'),
                                                    host)
Ejemplo n.º 28
0
    def __call__(self, value):
        value = force_text(value)

        if not value or '@' not in value:
            raise ValidationError(self.message, code=self.code)

        user_part, domain_part = value.rsplit('@', 1)

        if not self.user_regex.match(user_part):
            raise ValidationError(self.message, code=self.code)

        if (domain_part not in self.domain_whitelist
                and not self.validate_domain_part(domain_part)):
            # Try for possible IDN domain-part
            try:
                domain_part = domain_part.encode('idna').decode('ascii')
                if self.validate_domain_part(domain_part):
                    return
            except UnicodeError:
                pass
            raise ValidationError(self.message, code=self.code)
Ejemplo n.º 29
0
    def get_table_description(self, cursor, table_name):
        """
        Returns a description of the table, with the DB-API cursor.description interface."
        """
        # information_schema database gives more accurate results for some figures:
        # - varchar length returned by cursor.description is an internal length,
        #   not visible length (#5725)
        # - precision and scale (for decimal fields) (#5014)
        # - auto_increment is not available in cursor.description
        cursor.execute(
            """
            SELECT column_name, data_type, character_maximum_length, numeric_precision,
                   numeric_scale, extra, column_default
            FROM information_schema.columns
            WHERE table_name = %s AND table_schema = DATABASE()""",
            [table_name])
        field_info = {line[0]: InfoLine(*line) for line in cursor.fetchall()}

        cursor.execute("SELECT * FROM %s LIMIT 1" %
                       self.connection.ops.quote_name(table_name))

        def to_int(i):
            return int(i) if i is not None else i

        fields = []
        for line in cursor.description:
            col_name = force_text(line[0])
            fields.append(
                FieldInfo(*((col_name, ) + line[1:3] + (
                    to_int(field_info[col_name].max_len) or line[3],
                    to_int(field_info[col_name].num_prec) or line[4],
                    to_int(field_info[col_name].num_scale) or line[5],
                    line[6],
                    field_info[col_name].extra,
                    field_info[col_name].column_default,
                ))))
        return fields
Ejemplo n.º 30
0
def urlunquote_plus(quoted_url):
    """
    A wrapper for Python's urllib.unquote_plus() function that can operate on
    the result of django.utils.http.urlquote_plus().
    """
    return force_text(unquote_plus(force_str(quoted_url)))