Skip to content

Commit

Permalink
Update migration guide and contributing docs
Browse files Browse the repository at this point in the history
  • Loading branch information
sethmlarson authored Nov 30, 2021
1 parent bf0358a commit 1ac6ae4
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 37 deletions.
13 changes: 6 additions & 7 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,12 @@ you don't have Elasticsearch running locally the integration tests will be skipp

## API Code Generation

All the API methods (any method in `elasticsearch.client` classes decorated
with `@query_params`) are actually auto-generated from the
[rest-api-spec](https://github.com/elastic/elasticsearch/tree/master/rest-api-spec/src/main/resources/rest-api-spec/api)
found in the `Elasticsearch` or the [Elasticsearch specification](https://github.com/elastic/elasticsearch-specification)
repositories. Any changes to those methods should be done either by submitting a PR to one of these repositories
instead of directly to the Python client otherwise your change will be overwritten the
next time the APIs are generated.
All API methods for the `Elasticsearch` and `AsyncElasticsearch` client instances
(like `search()`) are automatically generated from the
[Elasticsearch specification](https://github.com/elastic/elasticsearch-specification)
and [rest-api-spec](https://github.com/elastic/elasticsearch/tree/master/rest-api-spec/src/main/resources/rest-api-spec/api).
Any changes to these methods should instead be submitted to the Elasticsearch specification project and will be imported the next time
the clients API is generated. The generator itself is currently a private project.

## Contributing Code Changes

Expand Down
71 changes: 65 additions & 6 deletions docs/guide/migration.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ from 7.x to 8.0.
** <<migration-strict-client-config>>
** <<migration-keyword-only-args>>
** <<migration-options>>
* <<migration-response-types>>

[discrete]
[[migration-compat-mode]]
Expand Down Expand Up @@ -51,20 +52,21 @@ You'll likely notice after upgrading the client to 8.0 your code is
either raising errors or `DeprecationWarning` to signal where you need
to change your code before using the 8.0 client.


[discrete]
[[migration-strict-client-config]]
==== Strict client configuration

Previously the client would use `scheme="http"`, `host="localhost"`, and `port=9200` defaults
when specifying which node(s) to connect to. Starting in 8.0 these defaults have been removed
and instead require explicit configuration of scheme, host, and port.
and instead require explicit configuration of scheme, host, and port or to be configured
using `cloud_id` to avoid confusion about which Elasticsearch instance is being connected to.

This choice was made because in Elasticsearch 8.0 HTTPS is enabled by default, so it's no
This choice was made because starting 8.0.0 Elasticsearch enables HTTPS is by default, so it's no
longer a good assumption that `http://localhost:9200` is a locally running cluster.

See documentation on <<connecting, connecting to Elasticsearch>> and <<tls-and-ssl, configuring HTTPS>>.


[discrete]
[[migration-keyword-only-args]]
==== Keyword-only arguments for APIs
Expand All @@ -85,16 +87,15 @@ client.indices.get(index="*")
client.indices.get("*")
------------------------------------


[discrete]
[[migration-options]]
==== Start using .options()
==== Start using .options() for transport parameters

Previously some per-request options like `api_key` and `ignore` were allowed within
client API methods. Starting in 8.0 this is deprecated for all APIs and for a small
number of APIs may break in unexpected ways if not changed.

The parameters `headers`, `params`, `api_key`, `http_auth`, `opaque_id`, `request_timeout`, and `ignore`
The parameters `headers`, `api_key`, `http_auth`, `opaque_id`, `request_timeout`, and `ignore`
are effected:

[source,python]
Expand Down Expand Up @@ -171,3 +172,61 @@ resp = (
)
)
------------------------------------

[discrete]
[[migration-response-types]]
==== Response types

In 7.x and earlier the return type for API methods were the raw deserialized response body.
This meant that there was no way to access HTTP status codes, headers, or other information
from the transport layer.

In 8.0.0 responses are no longer the raw deserialized response body and instead an object
with three properties, `meta`, `raw`, and `body`. Transport layer metadata about the response
like HTTP status, headers, version, and which node serviced the request are available here:

[source,python]
------------------------------------
>>> resp = client.search(...)
# Response is not longer a 'dict'
>>> resp
ObjectApiResponse({'took': 1, 'timed_out': False, ...})
# But can still be used like one:
>>> resp["hits"]["total"]
{'value': 5500, 'relation': 'eq'}
>>> resp.keys()
dict_keys(['took', 'timed_out', '_shards', 'hits'])
# HTTP status
>>> resp.meta.status
200
# HTTP headers
>>> resp.meta.headers['content-type']
'application/json'
# HTTP version
>>> resp.meta.http_version
'1.1'
------------------------------------

Because the response is no longer a dictionary, list, `str`, or `bytes` instance
calling `isintance()` on the response object will return `False`. If you need
direct access to the underlying deserialized response body you can use the `raw`
property:

[source,python]
------------------------------------
>>> resp.raw
{'took': 1, 'timed_out': False, ...}
# The response isn't a dict, but resp.raw is.
>>> isinstance(resp, dict)
False
>>> isinstance(resp.raw, dict)
True
------------------------------------
32 changes: 8 additions & 24 deletions docs/sphinx/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -51,17 +51,17 @@ Example Usage
'text': 'Elasticsearch: cool. bonsai cool.',
'timestamp': datetime.now(),
}
res = es.index(index="test-index", id=1, document=doc)
print(res['result'])
resp = es.index(index="test-index", id=1, document=doc)
print(resp['result'])
res = es.get(index="test-index", id=1)
print(res['_source'])
resp = es.get(index="test-index", id=1)
print(resp['_source'])
es.indices.refresh(index="test-index")
res = es.search(index="test-index", body={"query": {"match_all": {}}})
print("Got %d Hits:" % res['hits']['total']['value'])
for hit in res['hits']['hits']:
resp = es.search(index="test-index", query={"match_all": {}})
print("Got %d Hits:" % resp['hits']['total']['value'])
for hit in resp['hits']['hits']:
print("%(timestamp)s %(author)s: %(text)s" % hit["_source"])
Expand All @@ -75,23 +75,7 @@ Python. We have created some :ref:`helpers` to help with this issue as well as
a more high level library (`elasticsearch-dsl`_) on top of this one to provide
a more convenient way of working with Elasticsearch.

.. _elasticsearch-dsl: https://elasticsearch-dsl.readthedocs.io/


Logging
~~~~~~~

``elasticsearch-py`` uses the standard `logging library`_ from python to define
two loggers: ``elasticsearch`` and ``elasticsearch.trace``. ``elasticsearch``
is used by the client to log standard activity, depending on the log level.
``elasticsearch.trace`` can be used to log requests to the server in the form
of ``curl`` commands using pretty-printed json that can then be executed from
command line. Because it is designed to be shared (for example to demonstrate
an issue) it also just uses ``localhost:9200`` as the address instead of the
actual address of the host. If the trace logger has not been configured
already it is set to `propagate=False` so it needs to be activated separately.

.. _logging library: http://docs.python.org/3/library/logging.html
.. _elasticsearch-dsl: https://elasticsearch-dsl.readthedocs.io


Elasticsearch-DSL
Expand Down

0 comments on commit 1ac6ae4

Please sign in to comment.