:tags: bug, engine
:tickets: 2873
- The :func:`_sa.create_engine` routine and the related
- :func:`.make_url` function no longer considers the ``+`` sign
- to be a space within the password field. The parsing has been
- adjusted to match RFC 1738 exactly, in that both ``username``
- and ``password`` expect only ``:``, ``@``, and ``/`` to be
+ The :func:`_sa.create_engine` routine and the related :func:`.make_url`
+ function no longer considers the ``+`` sign to be a space within the
+ password field. The parsing in this area has been adjusted to match
+ more closely to how RFC 1738 handles these tokens, in that both
+ ``username`` and ``password`` expect only ``:``, ``@``, and ``/`` to be
encoded.
.. seealso::
Database URLs
=============
-The :func:`_sa.create_engine` function produces an :class:`_engine.Engine` object based
-on a URL. These URLs follow `RFC-1738
-<https://www.ietf.org/rfc/rfc1738.txt>`_, and usually can include username, password,
-hostname, database name as well as optional keyword arguments for additional configuration.
-In some cases a file path is accepted, and in others a "data source name" replaces
-the "host" and "database" portions. The typical form of a database URL is:
+The :func:`_sa.create_engine` function produces an :class:`_engine.Engine`
+object based on a URL. The format of the URL generally follows `RFC-1738
+<https://www.ietf.org/rfc/rfc1738.txt>`_, with some exceptions, including that
+underscores, not dashes or periods, are accepted within the "scheme" portion.
+URLs typically include username, password, hostname, database name fields, as
+well as optional keyword arguments for additional configuration. In some cases
+a file path is accepted, and in others a "data source name" replaces the "host"
+and "database" portions. The typical form of a database URL is:
.. sourcecode:: none
Represent the components of a URL used to connect to a database.
This object is suitable to be passed directly to a
- :func:`_sa.create_engine` call. The fields of the URL are parsed
- from a string by the :func:`.make_url` function. The string
- format of the URL is an RFC-1738-style string.
+ :func:`_sa.create_engine` call. The fields of the URL are parsed from a
+ string by the :func:`.make_url` function. The string format of the URL
+ generally follows `RFC-1738 <https://www.ietf.org/rfc/rfc1738.txt>`_, with
+ some exceptions.
To create a new :class:`_engine.URL` object, use the
:func:`.make_url` function. To construct a :class:`_engine.URL`
"""
s = self.drivername + "://"
if self.username is not None:
- s += _rfc_1738_quote(self.username)
+ s += _sqla_url_quote(self.username)
if self.password is not None:
s += ":" + (
"***"
if hide_password
- else _rfc_1738_quote(str(self.password))
+ else _sqla_url_quote(str(self.password))
)
s += "@"
if self.host is not None:
def make_url(name_or_url: Union[str, URL]) -> URL:
"""Given a string, produce a new URL instance.
- The given string is parsed according to the RFC 1738 spec. If an
- existing URL object is passed, just returns the object.
+ The format of the URL generally follows `RFC-1738
+ <https://www.ietf.org/rfc/rfc1738.txt>`_, with some exceptions, including
+ that underscores, and not dashes or periods, are accepted within the
+ "scheme" portion.
+
+ If a :class:`.URL` object is passed, it is returned as is.
.. seealso::
"""
if isinstance(name_or_url, str):
- return _parse_rfc1738_args(name_or_url)
+ return _parse_url(name_or_url)
else:
return name_or_url
-def _parse_rfc1738_args(name: str) -> URL:
+def _parse_url(name: str) -> URL:
pattern = re.compile(
r"""
(?P<name>[\w\+]+)://
components["query"] = query
if components["username"] is not None:
- components["username"] = _rfc_1738_unquote(components["username"])
+ components["username"] = _sqla_url_unquote(components["username"])
if components["password"] is not None:
- components["password"] = _rfc_1738_unquote(components["password"])
+ components["password"] = _sqla_url_unquote(components["password"])
ipv4host = components.pop("ipv4host")
ipv6host = components.pop("ipv6host")
else:
raise exc.ArgumentError(
- "Could not parse rfc1738 URL from string '%s'" % name
+ "Could not parse SQLAlchemy URL from string '%s'" % name
)
-def _rfc_1738_quote(text: str) -> str:
+def _sqla_url_quote(text: str) -> str:
return re.sub(r"[:@/]", lambda m: "%%%X" % ord(m.group(0)), text)
-_rfc_1738_unquote = unquote
+_sqla_url_unquote = unquote