Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions elastic_transport/connection/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ class Connection(object):
:arg user_agent: 'User-Agent' HTTP header for the given service.
"""

HTTP_CLIENT_META = None

def __init__(
self,
host="localhost",
Expand Down
20 changes: 12 additions & 8 deletions elastic_transport/connection/http_requests.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,19 @@

import urllib3

from ..compat import urlencode
from ..exceptions import ConnectionError, ConnectionTimeout
from ..utils import DEFAULT, client_meta_version, normalize_headers
from .base import Connection

try:
import requests

REQUESTS_AVAILABLE = True
_REQUESTS_AVAILABLE = True
_REQUESTS_META_VERSION = client_meta_version(requests.__version__)
except ImportError: # pragma: nocover
REQUESTS_AVAILABLE = False

from ..compat import urlencode
from ..exceptions import ConnectionError, ConnectionTimeout
from ..utils import DEFAULT, normalize_headers
from .base import Connection
_REQUESTS_AVAILABLE = False
_REQUESTS_META_VERSION = ""


class RequestsHttpConnection(Connection):
Expand All @@ -52,6 +54,8 @@ class RequestsHttpConnection(Connection):
For tracing all requests made by this transport.
"""

HTTP_CLIENT_META = ("rq", _REQUESTS_META_VERSION)

def __init__(
self,
host="localhost",
Expand All @@ -67,7 +71,7 @@ def __init__(
opaque_id=None,
**kwargs
):
if not REQUESTS_AVAILABLE: # pragma: nocover
if not _REQUESTS_AVAILABLE: # pragma: nocover
raise ValueError(
"You must have 'requests' installed to use RequestsHttpConnection"
)
Expand Down
4 changes: 3 additions & 1 deletion elastic_transport/connection/http_urllib3.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@

from ..compat import urlencode
from ..exceptions import ConnectionError, ConnectionTimeout
from ..utils import DEFAULT, normalize_headers
from ..utils import DEFAULT, client_meta_version, normalize_headers
from .base import Connection

CA_CERTS = None
Expand Down Expand Up @@ -70,6 +70,8 @@ class Urllib3HttpConnection(Connection):
For tracing all requests made by this transport.
"""

HTTP_CLIENT_META = ("ur", client_meta_version(urllib3.__version__))

def __init__(
self,
host="localhost",
Expand Down
18 changes: 17 additions & 1 deletion elastic_transport/transport.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,16 @@
# specific language governing permissions and limitations
# under the License.

from platform import python_version

from ._version import __version__
from .compat import string_types, urlparse
from .connection import RequestsHttpConnection, Urllib3HttpConnection
from .connection_pool import ConnectionPool, DummyConnectionPool, EmptyConnectionPool
from .exceptions import ConnectionError, ConnectionTimeout, TransportError
from .response import DictResponse, ListResponse, Response
from .serializer import DEFAULT_SERIALIZERS, Deserializer
from .utils import DEFAULT, normalize_headers
from .utils import DEFAULT, client_meta_version, normalize_headers

# Allows for using a connection_class by name rather than import.
CONNECTION_CLASS_NAMES = {
Expand Down Expand Up @@ -89,6 +92,19 @@ def __init__(
)
connection_class = CONNECTION_CLASS_NAMES[connection_class]

# Create the default metadata for the x-elastic-client-meta
# HTTP header. Only requires adding the (service, service_version)
# tuple to the beginning of the client_meta
self.transport_client_meta = (
("py", client_meta_version(python_version())),
("t", client_meta_version(__version__)),
)

# Grab the 'HTTP_CLIENT_META' property from the connection class
http_client_meta = getattr(connection_class, "HTTP_CLIENT_META", None)
if http_client_meta:
self.transport_client_meta += (http_client_meta,)

# serialization config
_serializers = DEFAULT_SERIALIZERS.copy()
# if custom serializers map has been supplied, override the defaults with it
Expand Down
11 changes: 11 additions & 0 deletions elastic_transport/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
# under the License.

import binascii
import re
from collections import namedtuple
from platform import python_version

Expand All @@ -39,6 +40,16 @@ def create_user_agent(name, version):
)


def client_meta_version(ver):
"""Converts a Python package version to a meta version.
Meta version simply adds a 'p' suffix for all pre-releases
"""
ver, ver_is_pre = re.match(r"^([0-9][0-9.]*[0-9]|[0-9])(.*)$", ver).groups()
if ver_is_pre:
ver += "p"
return ver


def normalize_headers(headers):
"""Normalizes HTTP headers to be lowercase to ensure
there are no case-collisions deeper within the stack.
Expand Down
20 changes: 20 additions & 0 deletions tests/test_transport.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
# specific language governing permissions and limitations
# under the License.

import re

import mock
import pytest

Expand Down Expand Up @@ -398,3 +400,21 @@ def test_head_response_ignore_status(status):
assert resp == False # noqa
assert resp.body is False
assert bool(resp) is False


@pytest.mark.parametrize(
"connection_class",
["urllib3", "requests", Urllib3HttpConnection, RequestsHttpConnection],
)
def test_transport_client_meta_connection_class(connection_class):
t = Transport(connection_class=connection_class)
assert t.transport_client_meta[2] == t.connection_class.HTTP_CLIENT_META
assert t.transport_client_meta[2][0] in ("ur", "rq")
assert re.match(
r"^py=[0-9.]+p?,t=[0-9.]+p?,(?:ur|rq)=[0-9.]+p?$",
",".join("%s=%s" % (k, v) for k, v in t.transport_client_meta),
)

t = Transport()
assert t.transport_client_meta[2][0] == "ur"
assert [x[0] for x in t.transport_client_meta[:2]] == ["py", "t"]
19 changes: 18 additions & 1 deletion tests/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,11 @@
import pytest

from elastic_transport import __version__
from elastic_transport.utils import create_user_agent, parse_cloud_id
from elastic_transport.utils import (
client_meta_version,
create_user_agent,
parse_cloud_id,
)


def test_create_user_agent():
Expand All @@ -33,6 +37,19 @@ def test_create_user_agent():
)


@pytest.mark.parametrize(
["version", "meta_version"],
[
("7.10.0", "7.10.0"),
("7.10.0-alpha1", "7.10.0p"),
("3.9.0b1", "3.9.0p"),
("3.9.pre1", "3.9p"),
],
)
def test_client_meta_version(version, meta_version):
assert client_meta_version(version) == meta_version


def test_parse_cloud_id():
cloud_id = parse_cloud_id(
"cluster:dXMtZWFzdC0xLmF3cy5mb3VuZC5pbyQ0ZmE4ODIxZTc1NjM0MDMyYmVkMWNmMjIxMTBlMmY5NyQ0ZmE4ODIxZTc1NjM0MDMyYmVkMWNmMjIxMTBlMmY5Ng=="
Expand Down